diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 01:56:22 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2011-07-03 01:56:22 -0400 |
commit | 6f231dda68080759f1aed3769896e94c73099f0f (patch) | |
tree | 45b6ce02fa40e0e9c35526ac6c45950138387516 | |
parent | 59c5f46fbe01a00eedf54a23789634438bb80603 (diff) |
isci: Intel(R) C600 Series Chipset Storage Control Unit Driver
Support for the up to 2x4-port 6Gb/s SAS controllers embedded in the
chipset.
This is a snapshot of the first publicly available version of the driver,
commit 4c1db2d0 in the 'historical' branch.
git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git historical
Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Edmund Nadolski <edmund.nadolski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
104 files changed, 51230 insertions, 0 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4a1f029c4fe9..3aa664fa892e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -830,6 +830,40 @@ config SCSI_GDTH | |||
830 | To compile this driver as a module, choose M here: the | 830 | To compile this driver as a module, choose M here: the |
831 | module will be called gdth. | 831 | module will be called gdth. |
832 | 832 | ||
833 | config SCSI_ISCI | ||
834 | tristate "Intel(R) C600 Series Chipset SAS Controller" | ||
835 | depends on PCI && SCSI | ||
836 | # little endian host assumptions | ||
837 | depends on X86 | ||
838 | # (temporary): dma api misuse | ||
839 | depends on !DMAR | ||
840 | # (temporary): known alpha quality driver | ||
841 | depends on EXPERIMENTAL | ||
842 | select SCSI_SAS_LIBSAS | ||
843 | ---help--- | ||
844 | This driver supports the 6Gb/s SAS capabilities of the storage | ||
845 | control unit found in the Intel(R) C600 series chipset. | ||
846 | |||
847 | The experimental tag will be removed after the driver exits alpha | ||
848 | |||
849 | choice | ||
850 | prompt "Default Silicon Revision" | ||
851 | depends on SCSI_ISCI | ||
852 | default PBG_HBA_A2 | ||
853 | # temporary A-step silicon is pre-production | ||
854 | |||
855 | config PBG_HBA_BETA | ||
856 | bool "B0" | ||
857 | |||
858 | config PBG_HBA_A2 | ||
859 | bool "A2" | ||
860 | |||
861 | config PBG_HBA_A0 | ||
862 | bool "A0" | ||
863 | |||
864 | endchoice | ||
865 | |||
866 | |||
833 | config SCSI_GENERIC_NCR5380 | 867 | config SCSI_GENERIC_NCR5380 |
834 | tristate "Generic NCR5380/53c400 SCSI PIO support" | 868 | tristate "Generic NCR5380/53c400 SCSI PIO support" |
835 | depends on ISA && SCSI | 869 | depends on ISA && SCSI |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 7ad0b8a79ae8..3c08f5352b2d 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -73,6 +73,7 @@ obj-$(CONFIG_SCSI_AACRAID) += aacraid/ | |||
73 | obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o | 73 | obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o |
74 | obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/ | 74 | obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/ |
75 | obj-$(CONFIG_SCSI_PM8001) += pm8001/ | 75 | obj-$(CONFIG_SCSI_PM8001) += pm8001/ |
76 | obj-$(CONFIG_SCSI_ISCI) += isci/ | ||
76 | obj-$(CONFIG_SCSI_IPS) += ips.o | 77 | obj-$(CONFIG_SCSI_IPS) += ips.o |
77 | obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o | 78 | obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o |
78 | obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o | 79 | obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o |
diff --git a/drivers/scsi/isci/Makefile b/drivers/scsi/isci/Makefile new file mode 100644 index 000000000000..34f7af3525f4 --- /dev/null +++ b/drivers/scsi/isci/Makefile | |||
@@ -0,0 +1,30 @@ | |||
1 | #TODO kill SCIC_SDS_4_ENABLED it is always true for this | ||
2 | #generation of silicon | ||
3 | EXTRA_CFLAGS += -DSCIC_SDS_4_ENABLED | ||
4 | |||
5 | #temporary until atapi support ready | ||
6 | EXTRA_CFLAGS += -DDISABLE_ATAPI | ||
7 | |||
8 | EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/ | ||
9 | obj-$(CONFIG_SCSI_ISCI) += isci.o | ||
10 | isci-objs := init.o phy.o request.o sata.o \ | ||
11 | remote_device.o port.o timers.o deprecated.o \ | ||
12 | host.o task.o events.o \ | ||
13 | core/scic_sds_controller.o \ | ||
14 | core/scic_sds_remote_device.o \ | ||
15 | core/scic_sds_request.o \ | ||
16 | core/scic_sds_stp_request.o \ | ||
17 | core/scic_sds_stp_packet_request.o \ | ||
18 | core/scic_sds_stp_remote_device.o \ | ||
19 | core/scic_sds_port.o \ | ||
20 | core/scic_sds_port_configuration_agent.o \ | ||
21 | core/scic_sds_phy.o \ | ||
22 | core/scic_sds_ssp_request.o \ | ||
23 | core/scic_sds_remote_node_context.o \ | ||
24 | core/scic_sds_smp_request.o \ | ||
25 | core/scic_sds_smp_remote_device.o \ | ||
26 | core/scic_sds_remote_node_table.o \ | ||
27 | core/scic_sds_unsolicited_frame_control.o \ | ||
28 | core/sci_base_memory_descriptor_list.o \ | ||
29 | core/sci_base_state_machine.o \ | ||
30 | core/sci_util.o | ||
diff --git a/drivers/scsi/isci/core/intel_ata.h b/drivers/scsi/isci/core/intel_ata.h new file mode 100644 index 000000000000..48b297e50bd0 --- /dev/null +++ b/drivers/scsi/isci/core/intel_ata.h | |||
@@ -0,0 +1,554 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file defines all of the ATA related constants, enumerations, and types. | ||
58 | * Please note that this file does not necessarily contain an exhaustive | ||
59 | * list of all constants, commands, sub-commands, etc. | ||
60 | * | ||
61 | * | ||
62 | */ | ||
63 | |||
64 | #ifndef _ATA_H_ | ||
65 | #define _ATA_H_ | ||
66 | |||
67 | #include <linux/types.h> | ||
68 | |||
69 | /** | ||
70 | * | ||
71 | * | ||
72 | * ATA_COMMAND_CODES These constants depict the various ATA command codes | ||
73 | * defined in the ATA/ATAPI specification. | ||
74 | */ | ||
75 | #define ATA_IDENTIFY_DEVICE 0xEC | ||
76 | #define ATA_CHECK_POWER_MODE 0xE5 | ||
77 | #define ATA_STANDBY 0xE2 | ||
78 | #define ATA_STANDBY_IMMED 0xE0 | ||
79 | #define ATA_IDLE_IMMED 0xE1 | ||
80 | #define ATA_IDLE 0xE3 | ||
81 | #define ATA_FLUSH_CACHE 0xE7 | ||
82 | #define ATA_FLUSH_CACHE_EXT 0xEA | ||
83 | #define ATA_READ_DMA_EXT 0x25 | ||
84 | #define ATA_READ_DMA 0xC8 | ||
85 | #define ATA_READ_SECTORS_EXT 0x24 | ||
86 | #define ATA_READ_SECTORS 0x20 | ||
87 | #define ATA_WRITE_DMA_EXT 0x35 | ||
88 | #define ATA_WRITE_DMA 0xCA | ||
89 | #define ATA_WRITE_SECTORS_EXT 0x34 | ||
90 | #define ATA_WRITE_SECTORS 0x30 | ||
91 | #define ATA_WRITE_UNCORRECTABLE 0x45 | ||
92 | #define ATA_READ_VERIFY_SECTORS 0x40 | ||
93 | #define ATA_READ_VERIFY_SECTORS_EXT 0x42 | ||
94 | #define ATA_READ_BUFFER 0xE4 | ||
95 | #define ATA_WRITE_BUFFER 0xE8 | ||
96 | #define ATA_EXECUTE_DEVICE_DIAG 0x90 | ||
97 | #define ATA_SET_FEATURES 0xEF | ||
98 | #define ATA_SMART 0xB0 | ||
99 | #define ATA_PACKET_IDENTIFY 0xA1 | ||
100 | #define ATA_PACKET 0xA0 | ||
101 | #define ATA_READ_FPDMA 0x60 | ||
102 | #define ATA_WRITE_FPDMA 0x61 | ||
103 | #define ATA_READ_LOG_EXT 0x2F | ||
104 | #define ATA_NOP 0x00 | ||
105 | #define ATA_DEVICE_RESET 0x08 | ||
106 | #define ATA_MEDIA_EJECT 0xED | ||
107 | |||
108 | /** | ||
109 | * | ||
110 | * | ||
111 | * ATA_SMART_SUB_COMMAND_CODES These constants define the ATA SMART command | ||
112 | * sub-codes that can be executed. | ||
113 | */ | ||
114 | #define ATA_SMART_SUB_CMD_ENABLE 0xD8 | ||
115 | #define ATA_SMART_SUB_CMD_DISABLE 0xD9 | ||
116 | #define ATA_SMART_SUB_CMD_RETURN_STATUS 0xDA | ||
117 | #define ATA_SMART_SUB_CMD_READ_LOG 0xD5 | ||
118 | |||
119 | /** | ||
120 | * | ||
121 | * | ||
122 | * ATA_SET_FEATURES_SUB_COMMAND_CODES These constants define the ATA SET | ||
123 | * FEATURES command sub-codes that can be executed. | ||
124 | */ | ||
125 | #define ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE 0x02 | ||
126 | #define ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE 0x82 | ||
127 | #define ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD 0x55 | ||
128 | #define ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD 0xAA | ||
129 | #define ATA_SET_FEATURES_SUB_CMD_SET_TRANSFER_MODE 0x3 | ||
130 | |||
131 | /** | ||
132 | * | ||
133 | * | ||
134 | * ATA_READ_LOG_EXT_PAGE_CODES This is a list of log page codes available for | ||
135 | * use. | ||
136 | */ | ||
137 | #define ATA_LOG_PAGE_NCQ_ERROR 0x10 | ||
138 | #define ATA_LOG_PAGE_SMART_SELF_TEST 0x06 | ||
139 | #define ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST 0x07 | ||
140 | |||
141 | /** | ||
142 | * | ||
143 | * | ||
144 | * ATA_LOG_PAGE_NCQ_ERROR_CONSTANTS These constants define standard values for | ||
145 | * use when requesting the NCQ error log page. | ||
146 | */ | ||
147 | #define ATA_LOG_PAGE_NCQ_ERROR_SECTOR 0 | ||
148 | #define ATA_LOG_PAGE_NCQ_ERROR_SECTOR_COUNT 1 | ||
149 | |||
150 | /** | ||
151 | * | ||
152 | * | ||
153 | * ATA_STATUS_REGISTER_BITS The following are status register bit definitions | ||
154 | * per ATA/ATAPI-7. | ||
155 | */ | ||
156 | #define ATA_STATUS_REG_BSY_BIT 0x80 | ||
157 | #define ATA_STATUS_REG_DEVICE_FAULT_BIT 0x20 | ||
158 | #define ATA_STATUS_REG_ERROR_BIT 0x01 | ||
159 | |||
160 | /** | ||
161 | * | ||
162 | * | ||
163 | * ATA_ERROR_REGISTER_BITS The following are error register bit definitions per | ||
164 | * ATA/ATAPI-7. | ||
165 | */ | ||
166 | #define ATA_ERROR_REG_NO_MEDIA_BIT 0x02 | ||
167 | #define ATA_ERROR_REG_ABORT_BIT 0x04 | ||
168 | #define ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT 0x08 | ||
169 | #define ATA_ERROR_REG_ID_NOT_FOUND_BIT 0x10 | ||
170 | #define ATA_ERROR_REG_MEDIA_CHANGE_BIT 0x20 | ||
171 | #define ATA_ERROR_REG_UNCORRECTABLE_BIT 0x40 | ||
172 | #define ATA_ERROR_REG_WRITE_PROTECTED_BIT 0x40 | ||
173 | #define ATA_ERROR_REG_ICRC_BIT 0x80 | ||
174 | |||
175 | /** | ||
176 | * | ||
177 | * | ||
178 | * ATA_CONTROL_REGISTER_BITS The following are control register bit definitions | ||
179 | * per ATA/ATAPI-7 | ||
180 | */ | ||
181 | #define ATA_CONTROL_REG_INTERRUPT_ENABLE_BIT 0x02 | ||
182 | #define ATA_CONTROL_REG_SOFT_RESET_BIT 0x04 | ||
183 | #define ATA_CONTROL_REG_HIGH_ORDER_BYTE_BIT 0x80 | ||
184 | |||
185 | /** | ||
186 | * | ||
187 | * | ||
188 | * ATA_DEVICE_HEAD_REGISTER_BITS The following are device/head register bit | ||
189 | * definitions per ATA/ATAPI-7. | ||
190 | */ | ||
191 | #define ATA_DEV_HEAD_REG_LBA_MODE_ENABLE 0x40 | ||
192 | #define ATA_DEV_HEAD_REG_FUA_ENABLE 0x80 | ||
193 | |||
194 | /** | ||
195 | * | ||
196 | * | ||
197 | * ATA_IDENTIFY_DEVICE_FIELD_LENGTHS The following constants define the number | ||
198 | * of bytes contained in various fields found in the IDENTIFY DEVICE data | ||
199 | * structure. | ||
200 | */ | ||
201 | #define ATA_IDENTIFY_SERIAL_NUMBER_LEN 20 | ||
202 | #define ATA_IDENTIFY_MODEL_NUMBER_LEN 40 | ||
203 | #define ATA_IDENTIFY_FW_REVISION_LEN 8 | ||
204 | #define ATA_IDENTIFY_48_LBA_LEN 8 | ||
205 | #define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN 30 | ||
206 | #define ATA_IDENTIFY_WWN_LEN 8 | ||
207 | |||
208 | /** | ||
209 | * | ||
210 | * | ||
211 | * ATA_IDENTIFY_DEVICE_FIELD_MASKS The following constants define bit masks | ||
212 | * utilized to determine if a feature is supported/enabled or if a bit is | ||
213 | * simply set inside of the IDENTIFY DEVICE data structre. | ||
214 | */ | ||
215 | #define ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE 0x0080 | ||
216 | #define ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE 0x0100 | ||
217 | #define ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE 0x2000 | ||
218 | #define ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE 0x0001 | ||
219 | #define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400 | ||
220 | #define ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE 0x0100 | ||
221 | #define ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE 0x0001 | ||
222 | #define ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE 0x0100 | ||
223 | #define ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE 0x001F | ||
224 | #define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE 0x0100 | ||
225 | #define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK 0x000F | ||
226 | #define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE 0x2000 | ||
227 | #define ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT 0x0004 | ||
228 | #define ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED 0x0002 | ||
229 | |||
230 | /** | ||
231 | * | ||
232 | * | ||
233 | * ATAPI_IDENTIFY_DEVICE_FIELD_MASKS These constants define the various bit | ||
234 | * definitions for the fields in the PACKET IDENTIFY DEVICE data structure. | ||
235 | */ | ||
236 | #define ATAPI_IDENTIFY_16BYTE_CMD_PCKT_ENABLE 0x01 | ||
237 | |||
238 | /** | ||
239 | * | ||
240 | * | ||
241 | * ATA_PACKET_FEATURE_BITS These constants define the various bit definitions | ||
242 | * for the ATA PACKET feature register. | ||
243 | */ | ||
244 | #define ATA_PACKET_FEATURE_DMA 0x01 | ||
245 | #define ATA_PACKET_FEATURE_OVL 0x02 | ||
246 | #define ATA_PACKET_FEATURE_DMADIR 0x04 | ||
247 | |||
248 | /** | ||
249 | * | ||
250 | * | ||
251 | * ATA_Device_Power_Mode_Values These constants define the power mode values | ||
252 | * returned by ATA_Check_Power_Mode | ||
253 | */ | ||
254 | #define ATA_STANDBY_POWER_MODE 0x00 | ||
255 | #define ATA_IDLE_POWER_MODE 0x80 | ||
256 | #define ATA_ACTIVE_POWER_MODE 0xFF | ||
257 | |||
258 | /** | ||
259 | * | ||
260 | * | ||
261 | * ATA_WRITE_UNCORRECTIABLE feature field values These constants define the | ||
262 | * Write Uncorrectable feature values used with the SATI translation. | ||
263 | */ | ||
264 | #define ATA_WRITE_UNCORRECTABLE_PSUEDO 0x55 | ||
265 | #define ATA_WRITE_UNCORRECTABLE_FLAGGED 0xAA | ||
266 | |||
267 | |||
268 | |||
269 | /** | ||
270 | * struct ATA_IDENTIFY_DEVICE - This structure depicts the ATA IDENTIFY DEVICE | ||
271 | * data format. | ||
272 | * | ||
273 | * | ||
274 | */ | ||
275 | struct ata_identify_device_data { | ||
276 | u16 general_config_bits; /* word 00 */ | ||
277 | u16 obsolete0; /* word 01 (num cylinders) */ | ||
278 | u16 vendor_specific_config_bits; /* word 02 */ | ||
279 | u16 obsolete1; /* word 03 (num heads) */ | ||
280 | u16 retired1[2]; /* words 04-05 */ | ||
281 | u16 obsolete2; /* word 06 (sectors / track) */ | ||
282 | u16 reserved_for_compact_flash1[2]; /* words 07-08 */ | ||
283 | u16 retired0; /* word 09 */ | ||
284 | u8 serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */ | ||
285 | u16 retired2[2]; /* words 20-21 */ | ||
286 | u16 obsolete4; /* word 22 */ | ||
287 | u8 firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */ | ||
288 | u8 model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */ | ||
289 | u16 max_sectors_per_multiple; /* word 47 */ | ||
290 | u16 reserved0; /* word 48 */ | ||
291 | u16 capabilities1; /* word 49 */ | ||
292 | u16 capabilities2; /* word 50 */ | ||
293 | u16 obsolete5[2]; /* words 51-52 */ | ||
294 | u16 validity_bits; /* word 53 */ | ||
295 | u16 obsolete6[5]; /* | ||
296 | * words 54-58 Used to be: | ||
297 | * current cylinders, | ||
298 | * current heads, | ||
299 | * current sectors/Track, | ||
300 | * current capacity */ | ||
301 | u16 current_max_sectors_per_multiple; /* word 59 */ | ||
302 | u8 total_num_sectors[4]; /* words 60-61 */ | ||
303 | u16 obsolete7; /* word 62 */ | ||
304 | u16 multi_word_dma_mode; /* word 63 */ | ||
305 | u16 pio_modes_supported; /* word 64 */ | ||
306 | u16 min_multiword_dma_transfer_cycle; /* word 65 */ | ||
307 | u16 rec_min_multiword_dma_transfer_cycle; /* word 66 */ | ||
308 | u16 min_pio_transfer_no_flow_ctrl; /* word 67 */ | ||
309 | u16 min_pio_transfer_with_flow_ctrl; /* word 68 */ | ||
310 | u16 reserved1[2]; /* words 69-70 */ | ||
311 | u16 reserved2[4]; /* words 71-74 */ | ||
312 | u16 queue_depth; /* word 75 */ | ||
313 | u16 serial_ata_capabilities; /* word 76 */ | ||
314 | u16 serial_ata_reserved; /* word 77 */ | ||
315 | u16 serial_ata_features_supported; /* word 78 */ | ||
316 | u16 serial_ata_features_enabled; /* word 79 */ | ||
317 | u16 major_version_number; /* word 80 */ | ||
318 | u16 minor_version_number; /* word 81 */ | ||
319 | u16 command_set_supported0; /* word 82 */ | ||
320 | u16 command_set_supported1; /* word 83 */ | ||
321 | u16 command_set_supported_extention; /* word 84 */ | ||
322 | u16 command_set_enabled0; /* word 85 */ | ||
323 | u16 command_set_enabled1; /* word 86 */ | ||
324 | u16 command_set_default; /* word 87 */ | ||
325 | u16 ultra_dma_mode; /* word 88 */ | ||
326 | u16 security_erase_completion_time; /* word 89 */ | ||
327 | u16 enhanced_security_erase_time; /* word 90 */ | ||
328 | u16 current_power_mgmt_value; /* word 91 */ | ||
329 | u16 master_password_revision; /* word 92 */ | ||
330 | u16 hardware_reset_result; /* word 93 */ | ||
331 | u16 current_acoustic_management_value; /* word 94 */ | ||
332 | u16 stream_min_request_size; /* word 95 */ | ||
333 | u16 stream_transfer_time; /* word 96 */ | ||
334 | u16 stream_access_latency; /* word 97 */ | ||
335 | u16 stream_performance_granularity[2]; /* words 98-99 */ | ||
336 | u8 max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN]; /* words 100-103 */ | ||
337 | u16 streaming_transfer_time; /* word 104 */ | ||
338 | u16 reserved3; /* word 105 */ | ||
339 | u16 physical_logical_sector_info; /* word 106 */ | ||
340 | u16 acoustic_test_interseek_delay; /* word 107 */ | ||
341 | u8 world_wide_name[ATA_IDENTIFY_WWN_LEN]; /* words 108-111 */ | ||
342 | u8 reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN]; /* words 112-115 */ | ||
343 | u16 reserved4; /* word 116 */ | ||
344 | u8 words_per_logical_sector[4]; /* words 117-118 */ | ||
345 | u16 command_set_supported2; /* word 119 */ | ||
346 | u16 reserved5[7]; /* words 120-126 */ | ||
347 | u16 removable_media_status; /* word 127 */ | ||
348 | u16 security_status; /* word 128 */ | ||
349 | u16 vendor_specific1[31]; /* words 129-159 */ | ||
350 | u16 cfa_power_mode1; /* word 160 */ | ||
351 | u16 reserved_for_compact_flash2[7]; /* words 161-167 */ | ||
352 | u16 device_nominal_form_factor; /* word 168 */ | ||
353 | u16 reserved_for_compact_flash3[7]; /* words 169-175 */ | ||
354 | u16 current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN]; /* words 176-205 */ | ||
355 | u16 reserved6[3]; /* words 206-208 */ | ||
356 | u16 logical_sector_alignment; /* words 209 */ | ||
357 | u16 reserved7[7]; /* words 210-216 */ | ||
358 | u16 nominal_media_rotation_rate; /* word 217 */ | ||
359 | u16 reserved8[37]; /* words 218-254 */ | ||
360 | u16 integrity_word; /* word 255 */ | ||
361 | |||
362 | }; | ||
363 | |||
364 | #define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \ | ||
365 | ((unsigned long)&(((struct ata_identify_device_data *)0)->field_name)) | ||
366 | #define ATA_IDENTIFY_DEVICE_WCE_ENABLE 0x20 | ||
367 | #define ATA_IDENTIFY_DEVICE_RA_ENABLE 0x40 | ||
368 | |||
369 | /** | ||
370 | * struct ATAPI_IDENTIFY_PACKET_DATA - The following structure depicts the | ||
371 | * ATA-ATAPI 7 version of the IDENTIFY PACKET DEVICE data structure. | ||
372 | * | ||
373 | * | ||
374 | */ | ||
375 | struct atapi_identify_packet_device { | ||
376 | u16 generalConfigBits; /* word 00 */ | ||
377 | u16 reserved0; /* word 01 (num cylinders) */ | ||
378 | u16 uniqueConfigBits; /* word 02 */ | ||
379 | u16 reserved1[7]; /* words 03 - 09 */ | ||
380 | u8 serialNumber[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; /* word 10-19 */ | ||
381 | u16 reserved2[3]; /* words 20-22 */ | ||
382 | u8 firmwareRevision[ATA_IDENTIFY_FW_REVISION_LEN]; /* words 23-26 */ | ||
383 | u8 modelNumber[ATA_IDENTIFY_MODEL_NUMBER_LEN]; /* words 27-46 */ | ||
384 | u16 reserved4[2]; /* words 47-48 */ | ||
385 | u16 capabilities1; /* word 49 */ | ||
386 | u16 capabilities2; /* word 50 */ | ||
387 | u16 obsolete0[2]; /* words 51-52 */ | ||
388 | u16 validityBits; /* word 53 */ | ||
389 | u16 reserved[8]; /* words 54-61 */ | ||
390 | |||
391 | u16 DMADIRBitRequired; /* word 62, page2 */ | ||
392 | u16 multiWordDmaMode; /* word 63 */ | ||
393 | u16 pioModesSupported; /* word 64 */ | ||
394 | u16 minMultiwordDmaTransferCycle; /* word 65 */ | ||
395 | u16 recMinMultiwordDmaTransferCycle; /* word 66 */ | ||
396 | u16 minPioTransferNoFlowCtrl; /* word 67 */ | ||
397 | u16 minPioTransferWithFlowCtrl; /* word 68 */ | ||
398 | u16 reserved6[2]; /* words 69-70 */ | ||
399 | u16 nsFromPACKETReceiptToBusRelease; /* word 71 */ | ||
400 | u16 nsFromSERVICEReceiptToBSYreset; /* wore 72 */ | ||
401 | u16 reserved7[2]; /* words 73-74 */ | ||
402 | u16 queueDepth; /* word 75 */ | ||
403 | u16 serialAtaCapabilities; /* word 76 */ | ||
404 | u16 serialAtaReserved; /* word 77 */ | ||
405 | u16 serialAtaFeaturesSupported; /* word 78 */ | ||
406 | u16 serialAtaFeaturesEnabled; /* word 79 */ | ||
407 | |||
408 | u16 majorVersionNumber; /* word 80, page3 */ | ||
409 | u16 minorVersionNumber; /* word 81 */ | ||
410 | u16 commandSetSupported0; /* word 82 */ | ||
411 | u16 commandSetSupported1; /* word 83 */ | ||
412 | |||
413 | u16 commandSetSupportedExtention; /* word 84, page4 */ | ||
414 | u16 commandSetEnabled0; /* word 85 */ | ||
415 | u16 commandSetEnabled1; /* word 86 */ | ||
416 | u16 commandSetDefault; /* word 87 */ | ||
417 | |||
418 | u16 ultraDmaMode; /* word 88, page5 */ | ||
419 | u16 reserved8[4]; /* words 89 - 92 */ | ||
420 | |||
421 | u16 hardwareResetResult; /* word 93, page6 */ | ||
422 | u16 currentAcousticManagementValue; /* word 94 */ | ||
423 | u16 reserved9[30]; /* words 95-124 */ | ||
424 | u16 ATAPIByteCount0Behavior; /* word 125 */ | ||
425 | u16 obsolete1; /* word 126 */ | ||
426 | u16 removableMediaStatus; /* word 127, */ | ||
427 | |||
428 | u16 securityStatus; /* word 128, page7 */ | ||
429 | u16 vendorSpecific1[31]; /* words 129-159 */ | ||
430 | u16 reservedForCompactFlash[16]; /* words 160-175 */ | ||
431 | u16 reserved10[79]; /* words 176-254 */ | ||
432 | u16 integrityWord; /* word 255 */ | ||
433 | }; | ||
434 | |||
435 | /** | ||
436 | * struct ata_extended_smart_self_test_log - The following structure depicts | ||
437 | * the ATA-8 version of the Extended SMART self test log page descriptor | ||
438 | * entry. | ||
439 | * | ||
440 | * | ||
441 | */ | ||
442 | union ata_descriptor_entry { | ||
443 | struct DESCRIPTOR_ENTRY { | ||
444 | u8 lba_field; | ||
445 | u8 status_byte; | ||
446 | u8 time_stamp_low; | ||
447 | u8 time_stamp_high; | ||
448 | u8 checkpoint_byte; | ||
449 | u8 failing_lba_low; | ||
450 | u8 failing_lba_mid; | ||
451 | u8 failing_lba_high; | ||
452 | u8 failing_lba_low_ext; | ||
453 | u8 failing_lba_mid_ext; | ||
454 | u8 failing_lba_high_ext; | ||
455 | |||
456 | u8 vendor_specific1; | ||
457 | u8 vendor_specific2; | ||
458 | u8 vendor_specific3; | ||
459 | u8 vendor_specific4; | ||
460 | u8 vendor_specific5; | ||
461 | u8 vendor_specific6; | ||
462 | u8 vendor_specific7; | ||
463 | u8 vendor_specific8; | ||
464 | u8 vendor_specific9; | ||
465 | u8 vendor_specific10; | ||
466 | u8 vendor_specific11; | ||
467 | u8 vendor_specific12; | ||
468 | u8 vendor_specific13; | ||
469 | u8 vendor_specific14; | ||
470 | u8 vendor_specific15; | ||
471 | } DESCRIPTOR_ENTRY; | ||
472 | |||
473 | u8 descriptor_entry[26]; | ||
474 | |||
475 | }; | ||
476 | |||
477 | /** | ||
478 | * struct ata_extended_smart_self_test_log - The following structure depicts | ||
479 | * the ATA-8 version of the SMART self test log page descriptor entry. | ||
480 | * | ||
481 | * | ||
482 | */ | ||
483 | union ata_smart_descriptor_entry { | ||
484 | struct SMART_DESCRIPTOR_ENTRY { | ||
485 | u8 lba_field; | ||
486 | u8 status_byte; | ||
487 | u8 time_stamp_low; | ||
488 | u8 time_stamp_high; | ||
489 | u8 checkpoint_byte; | ||
490 | u8 failing_lba_low; | ||
491 | u8 failing_lba_mid; | ||
492 | u8 failing_lba_high; | ||
493 | u8 failing_lba_low_ext; | ||
494 | |||
495 | u8 vendor_specific1; | ||
496 | u8 vendor_specific2; | ||
497 | u8 vendor_specific3; | ||
498 | u8 vendor_specific4; | ||
499 | u8 vendor_specific5; | ||
500 | u8 vendor_specific6; | ||
501 | u8 vendor_specific7; | ||
502 | u8 vendor_specific8; | ||
503 | u8 vendor_specific9; | ||
504 | u8 vendor_specific10; | ||
505 | u8 vendor_specific11; | ||
506 | u8 vendor_specific12; | ||
507 | u8 vendor_specific13; | ||
508 | u8 vendor_specific14; | ||
509 | u8 vendor_specific15; | ||
510 | } SMART_DESCRIPTOR_ENTRY; | ||
511 | |||
512 | u8 smart_descriptor_entry[24]; | ||
513 | |||
514 | }; | ||
515 | |||
516 | /** | ||
517 | * struct ata_extended_smart_self_test_log - The following structure depicts | ||
518 | * the ATA-8 version of the Extended SMART self test log page. | ||
519 | * | ||
520 | * | ||
521 | */ | ||
522 | struct ata_extended_smart_self_test_log { | ||
523 | u8 self_test_log_data_structure_revision_number; /* byte 0 */ | ||
524 | u8 reserved0; /* byte 1 */ | ||
525 | u8 self_test_descriptor_index[2]; /* byte 2-3 */ | ||
526 | |||
527 | union ata_descriptor_entry descriptor_entrys[19]; /* bytes 4-497 */ | ||
528 | |||
529 | u8 vendor_specific[2]; /* byte 498-499 */ | ||
530 | u8 reserved1[11]; /* byte 500-510 */ | ||
531 | u8 data_structure_checksum; /* byte 511 */ | ||
532 | |||
533 | }; | ||
534 | |||
535 | /** | ||
536 | * struct ata_extended_smart_self_test_log - The following structure depicts | ||
537 | * the ATA-8 version of the SMART self test log page. | ||
538 | * | ||
539 | * | ||
540 | */ | ||
541 | struct ata_smart_self_test_log { | ||
542 | u8 self_test_log_data_structure_revision_number[2]; /* bytes 0-1 */ | ||
543 | |||
544 | union ata_smart_descriptor_entry descriptor_entrys[21]; /* bytes 2-505 */ | ||
545 | |||
546 | u8 vendor_specific[2]; /* byte 506-507 */ | ||
547 | u8 self_test_index; /* byte 508 */ | ||
548 | u8 reserved1[2]; /* byte 509-510 */ | ||
549 | u8 data_structure_checksum; /* byte 511 */ | ||
550 | |||
551 | }; | ||
552 | |||
553 | #endif /* _ATA_H_ */ | ||
554 | |||
diff --git a/drivers/scsi/isci/core/intel_sas.h b/drivers/scsi/isci/core/intel_sas.h new file mode 100644 index 000000000000..eb9686ea35f1 --- /dev/null +++ b/drivers/scsi/isci/core/intel_sas.h | |||
@@ -0,0 +1,948 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _INTEL_SAS_H_ | ||
57 | #define _INTEL_SAS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the definitions relating to structures, constants, | ||
61 | * etc. defined by the SAS specification. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "intel_sata.h" | ||
67 | #include "intel_scsi.h" | ||
68 | |||
69 | /** | ||
70 | * struct sci_sas_address - This structure depicts how a SAS address is | ||
71 | * represented by SCI. | ||
72 | * | ||
73 | * | ||
74 | */ | ||
75 | struct sci_sas_address { | ||
76 | /** | ||
77 | * This member contains the higher 32-bits of the SAS address. | ||
78 | */ | ||
79 | u32 high; | ||
80 | |||
81 | /** | ||
82 | * This member contains the lower 32-bits of the SAS address. | ||
83 | */ | ||
84 | u32 low; | ||
85 | |||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * struct sci_sas_identify_address_frame_protocols - This structure depicts the | ||
90 | * contents of bytes 2 and 3 in the SAS IDENTIFY ADDRESS FRAME (IAF). | ||
91 | * | ||
92 | * For specific information on each of these individual fields please reference | ||
93 | * the SAS specification Link layer section on address frames. | ||
94 | */ | ||
95 | struct sci_sas_identify_address_frame_protocols { | ||
96 | union { | ||
97 | struct { | ||
98 | u16 restricted1:1; | ||
99 | u16 smp_initiator:1; | ||
100 | u16 stp_initiator:1; | ||
101 | u16 ssp_initiator:1; | ||
102 | u16 reserved3:4; | ||
103 | u16 restricted2:1; | ||
104 | u16 smp_target:1; | ||
105 | u16 stp_target:1; | ||
106 | u16 ssp_target:1; | ||
107 | u16 reserved4:4; | ||
108 | } bits; | ||
109 | |||
110 | u16 all; | ||
111 | } u; | ||
112 | |||
113 | }; | ||
114 | |||
115 | /** | ||
116 | * struct sci_sas_identify_address_frame - This structure depicts the contents | ||
117 | * of the SAS IDENTIFY ADDRESS FRAME (IAF). | ||
118 | * | ||
119 | * For specific information on each of these individual fields please reference | ||
120 | * the SAS specification Link layer section on address frames. | ||
121 | */ | ||
122 | struct sci_sas_identify_address_frame { | ||
123 | u16 address_frame_type:4; | ||
124 | u16 device_type:3; | ||
125 | u16 reserved1:1; | ||
126 | u16 reason:4; | ||
127 | u16 reserved2:4; | ||
128 | |||
129 | struct sci_sas_identify_address_frame_protocols protocols; | ||
130 | |||
131 | struct sci_sas_address device_name; | ||
132 | struct sci_sas_address sas_address; | ||
133 | |||
134 | u32 phy_identifier:8; | ||
135 | u32 break_reply_capable:1; | ||
136 | u32 requested_in_zpsds:1; | ||
137 | u32 in_zpsds_persistent:1; | ||
138 | u32 reserved5:21; | ||
139 | |||
140 | u32 reserved6[4]; | ||
141 | |||
142 | }; | ||
143 | |||
144 | /** | ||
145 | * struct sas_capabilities - This structure depicts the various SAS | ||
146 | * capabilities supported by the directly attached target device. For | ||
147 | * specific information on each of these individual fields please reference | ||
148 | * the SAS specification Phy layer section on speed negotiation windows. | ||
149 | * | ||
150 | * | ||
151 | */ | ||
152 | struct sas_capabilities { | ||
153 | union { | ||
154 | #if defined (SCIC_SDS_4_ENABLED) | ||
155 | struct { | ||
156 | /** | ||
157 | * The SAS specification indicates the start bit shall always be set to | ||
158 | * 1. This implementation will have the start bit set to 0 if the | ||
159 | * PHY CAPABILITIES were either not received or speed negotiation failed. | ||
160 | */ | ||
161 | u32 start:1; | ||
162 | u32 tx_ssc_type:1; | ||
163 | u32 reserved1:2; | ||
164 | u32 requested_logical_link_rate:4; | ||
165 | |||
166 | u32 gen1_without_ssc_supported:1; | ||
167 | u32 gen1_with_ssc_supported:1; | ||
168 | u32 gen2_without_ssc_supported:1; | ||
169 | u32 gen2_with_ssc_supported:1; | ||
170 | u32 gen3_without_ssc_supported:1; | ||
171 | u32 gen3_with_ssc_supported:1; | ||
172 | u32 reserved2:17; | ||
173 | u32 parity:1; | ||
174 | } bits; | ||
175 | #endif /* (SCIC_SDS_4_ENABLED) */ | ||
176 | |||
177 | u32 all; | ||
178 | } u; | ||
179 | |||
180 | }; | ||
181 | |||
182 | /** | ||
183 | * enum _SCI_SAS_LINK_RATE - This enumeration depicts the SAS specification | ||
184 | * defined link speeds. | ||
185 | * | ||
186 | * | ||
187 | */ | ||
188 | enum sci_sas_link_rate { | ||
189 | SCI_SAS_NO_LINK_RATE = 0, | ||
190 | SCI_SATA_SPINUP_HOLD = 0x3, | ||
191 | SCI_SAS_150_GB = 0x8, | ||
192 | SCI_SAS_300_GB = 0x9, | ||
193 | SCI_SAS_600_GB = 0xA | ||
194 | }; | ||
195 | |||
196 | /** | ||
197 | * enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS | ||
198 | * specification defined task attribute values for a command information | ||
199 | * unit. | ||
200 | * | ||
201 | * | ||
202 | */ | ||
203 | enum sci_sas_task_attribute { | ||
204 | SCI_SAS_SIMPLE_ATTRIBUTE = 0, | ||
205 | SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE = 1, | ||
206 | SCI_SAS_ORDERED_ATTRIBUTE = 2, | ||
207 | SCI_SAS_ACA_ATTRIBUTE = 4, | ||
208 | }; | ||
209 | |||
210 | /** | ||
211 | * enum _SCI_SAS_TASK_MGMT_FUNCTION - This enumeration depicts the SAM/SAS | ||
212 | * specification defined task management functions. | ||
213 | * | ||
214 | * This HARD_RESET function listed here is not actually defined as a task | ||
215 | * management function in the industry standard. | ||
216 | */ | ||
217 | enum sci_sas_task_mgmt_function { | ||
218 | SCI_SAS_ABORT_TASK = SCSI_TASK_REQUEST_ABORT_TASK, | ||
219 | SCI_SAS_ABORT_TASK_SET = SCSI_TASK_REQUEST_ABORT_TASK_SET, | ||
220 | SCI_SAS_CLEAR_TASK_SET = SCSI_TASK_REQUEST_CLEAR_TASK_SET, | ||
221 | SCI_SAS_LOGICAL_UNIT_RESET = SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET, | ||
222 | SCI_SAS_I_T_NEXUS_RESET = SCSI_TASK_REQUEST_I_T_NEXUS_RESET, | ||
223 | SCI_SAS_CLEAR_ACA = SCSI_TASK_REQUEST_CLEAR_ACA, | ||
224 | SCI_SAS_QUERY_TASK = SCSI_TASK_REQUEST_QUERY_TASK, | ||
225 | SCI_SAS_QUERY_TASK_SET = SCSI_TASK_REQUEST_QUERY_TASK_SET, | ||
226 | SCI_SAS_QUERY_ASYNCHRONOUS_EVENT = SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION, | ||
227 | SCI_SAS_HARD_RESET = 0xFF | ||
228 | }; | ||
229 | |||
230 | |||
231 | /** | ||
232 | * enum _SCI_SAS_FRAME_TYPE - This enumeration depicts the SAS specification | ||
233 | * defined SSP frame types. | ||
234 | * | ||
235 | * | ||
236 | */ | ||
237 | enum sci_sas_frame_type { | ||
238 | SCI_SAS_DATA_FRAME = 0x01, | ||
239 | SCI_SAS_XFER_RDY_FRAME = 0x05, | ||
240 | SCI_SAS_COMMAND_FRAME = 0x06, | ||
241 | SCI_SAS_RESPONSE_FRAME = 0x07, | ||
242 | SCI_SAS_TASK_FRAME = 0x16 | ||
243 | }; | ||
244 | |||
245 | /** | ||
246 | * struct sci_ssp_command_iu - This structure depicts the contents of the SSP | ||
247 | * COMMAND INFORMATION UNIT. For specific information on each of these | ||
248 | * individual fields please reference the SAS specification SSP transport | ||
249 | * layer section. | ||
250 | * | ||
251 | * | ||
252 | */ | ||
253 | struct sci_ssp_command_iu { | ||
254 | u32 lun_upper; | ||
255 | u32 lun_lower; | ||
256 | |||
257 | u32 additional_cdb_length:6; | ||
258 | u32 reserved0:2; | ||
259 | u32 reserved1:8; | ||
260 | u32 enable_first_burst:1; | ||
261 | u32 task_priority:4; | ||
262 | u32 task_attribute:3; | ||
263 | u32 reserved2:8; | ||
264 | |||
265 | u32 cdb[4]; | ||
266 | |||
267 | }; | ||
268 | |||
269 | /** | ||
270 | * struct sci_ssp_task_iu - This structure depicts the contents of the SSP TASK | ||
271 | * INFORMATION UNIT. For specific information on each of these individual | ||
272 | * fields please reference the SAS specification SSP transport layer section. | ||
273 | * | ||
274 | * | ||
275 | */ | ||
276 | struct sci_ssp_task_iu { | ||
277 | u32 lun_upper; | ||
278 | u32 lun_lower; | ||
279 | |||
280 | u32 reserved0:8; | ||
281 | u32 task_function:8; | ||
282 | u32 reserved1:8; | ||
283 | u32 reserved2:8; | ||
284 | |||
285 | u32 reserved3:16; | ||
286 | u32 task_tag:16; | ||
287 | |||
288 | u32 reserved4[3]; | ||
289 | |||
290 | }; | ||
291 | |||
292 | #define SSP_RESPONSE_IU_MAX_DATA 64 | ||
293 | |||
294 | #define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK (0x03) | ||
295 | |||
296 | |||
297 | #define sci_ssp_get_sense_data_length(sense_data_length_buffer) \ | ||
298 | SCIC_BUILD_DWORD(sense_data_length_buffer) | ||
299 | |||
300 | #define sci_ssp_get_response_data_length(response_data_length_buffer) \ | ||
301 | SCIC_BUILD_DWORD(response_data_length_buffer) | ||
302 | |||
303 | /** | ||
304 | * struct sci_ssp_response_iu - This structure depicts the contents of the SSP | ||
305 | * RESPONSE INFORMATION UNIT. For specific information on each of these | ||
306 | * individual fields please reference the SAS specification SSP transport | ||
307 | * layer section. | ||
308 | * | ||
309 | * | ||
310 | */ | ||
311 | struct sci_ssp_response_iu { | ||
312 | u8 reserved0[8]; | ||
313 | |||
314 | u8 retry_delay_timer[2]; | ||
315 | u8 data_present; | ||
316 | u8 status; | ||
317 | |||
318 | u8 reserved1[4]; | ||
319 | u8 sense_data_length[4]; | ||
320 | u8 response_data_length[4]; | ||
321 | |||
322 | u32 data[SSP_RESPONSE_IU_MAX_DATA]; | ||
323 | |||
324 | }; | ||
325 | |||
326 | /** | ||
327 | * enum _SCI_SAS_DATA_PRESENT_TYPE - This enumeration depicts the SAS | ||
328 | * specification defined SSP data present types in struct sci_ssp_response_iu. | ||
329 | * | ||
330 | * | ||
331 | */ | ||
332 | enum sci_ssp_response_iu_data_present_type { | ||
333 | SCI_SSP_RESPONSE_IU_NO_DATA = 0x00, | ||
334 | SCI_SSP_RESPONSE_IU_RESPONSE_DATA = 0x01, | ||
335 | SCI_SSP_RESPONSE_IU_SENSE_DATA = 0x02 | ||
336 | }; | ||
337 | |||
338 | /** | ||
339 | * struct sci_ssp_frame_header - This structure depicts the contents of an SSP | ||
340 | * frame header. For specific information on the individual fields please | ||
341 | * reference the SAS specification transport layer SSP frame format. | ||
342 | * | ||
343 | * | ||
344 | */ | ||
345 | struct sci_ssp_frame_header { | ||
346 | /* Word 0 */ | ||
347 | u32 hashed_destination_address:24; | ||
348 | u32 frame_type:8; | ||
349 | |||
350 | /* Word 1 */ | ||
351 | u32 hashed_source_address:24; | ||
352 | u32 reserved1_0:8; | ||
353 | |||
354 | /* Word 2 */ | ||
355 | u32 reserved2_2:6; | ||
356 | u32 fill_bytes:2; | ||
357 | u32 reserved2_1:3; | ||
358 | u32 tlr_control:2; | ||
359 | u32 retry_data_frames:1; | ||
360 | u32 retransmit:1; | ||
361 | u32 changing_data_pointer:1; | ||
362 | u32 reserved2_0:16; | ||
363 | |||
364 | /* Word 3 */ | ||
365 | u32 uiResv4; | ||
366 | |||
367 | /* Word 4 */ | ||
368 | u16 target_port_transfer_tag; | ||
369 | u16 tag; | ||
370 | |||
371 | /* Word 5 */ | ||
372 | u32 data_offset; | ||
373 | |||
374 | }; | ||
375 | |||
376 | /** | ||
377 | * struct smp_request_header - This structure defines the contents of an SMP | ||
378 | * Request header. | ||
379 | * | ||
380 | * For specific information on each of these individual fields please reference | ||
381 | * the SAS specification. | ||
382 | */ | ||
383 | struct smp_request_header { | ||
384 | u8 smp_frame_type; /* byte 0 */ | ||
385 | u8 function; /* byte 1 */ | ||
386 | u8 allocated_response_length; /* byte 2 */ | ||
387 | u8 request_length; /* byte 3 */ | ||
388 | }; | ||
389 | |||
390 | /** | ||
391 | * struct smp_response_header - This structure depicts the contents of the SAS | ||
392 | * SMP DISCOVER RESPONSE frame. For specific information on each of these | ||
393 | * individual fields please reference the SAS specification Link layer | ||
394 | * section on address frames. | ||
395 | * | ||
396 | * | ||
397 | */ | ||
398 | struct smp_response_header { | ||
399 | u8 smp_frame_type; /* byte 0 */ | ||
400 | u8 function; /* byte 1 */ | ||
401 | u8 function_result; /* byte 2 */ | ||
402 | u8 response_length; /* byte 3 */ | ||
403 | }; | ||
404 | |||
405 | /** | ||
406 | * struct smp_request_general - This structure defines the contents of an SMP | ||
407 | * Request that is comprised of the struct smp_request_header and a CRC. | ||
408 | * | ||
409 | * For specific information on each of these individual fields please reference | ||
410 | * the SAS specification. | ||
411 | */ | ||
412 | struct smp_request_general { | ||
413 | u32 crc; /* bytes 4-7 */ | ||
414 | |||
415 | }; | ||
416 | |||
417 | /** | ||
418 | * struct smp_request_phy_identifier - This structure defines the contents of | ||
419 | * an SMP Request that is comprised of the struct smp_request_header and a phy | ||
420 | * identifier. Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA. | ||
421 | * | ||
422 | * For specific information on each of these individual fields please reference | ||
423 | * the SAS specification. | ||
424 | */ | ||
425 | struct smp_request_phy_identifier { | ||
426 | u32 reserved_byte4_7; /* bytes 4-7 */ | ||
427 | |||
428 | u32 ignore_zone_group:1; /* byte 8 */ | ||
429 | u32 reserved_byte8:7; | ||
430 | |||
431 | u32 phy_identifier:8; /* byte 9 */ | ||
432 | u32 reserved_byte10:8; /* byte 10 */ | ||
433 | u32 reserved_byte11:8; /* byte 11 */ | ||
434 | |||
435 | }; | ||
436 | |||
437 | /** | ||
438 | * struct smp_request_configure_route_information - This structure defines the | ||
439 | * contents of an SMP Configure Route Information request. | ||
440 | * | ||
441 | * For specific information on each of these individual fields please reference | ||
442 | * the SAS specification. | ||
443 | */ | ||
444 | struct smp_request_configure_route_information { | ||
445 | u32 expected_expander_change_count:16; /* bytes 4-5 */ | ||
446 | u32 expander_route_index_high:8; | ||
447 | u32 expander_route_index:8; /* bytes 6-7 */ | ||
448 | |||
449 | u32 reserved_byte8:8; /* bytes 8 */ | ||
450 | u32 phy_identifier:8; /* bytes 9 */ | ||
451 | u32 reserved_byte_10_11:16; /* bytes 10-11 */ | ||
452 | |||
453 | u32 reserved_byte_12_bit_0_6:7; | ||
454 | u32 disable_route_entry:1; /* byte 12 */ | ||
455 | u32 reserved_byte_13_15:24; /* bytes 13-15 */ | ||
456 | |||
457 | u32 routed_sas_address[2]; /* bytes 16-23 */ | ||
458 | u8 reserved_byte_24_39[16]; /* bytes 24-39 */ | ||
459 | |||
460 | }; | ||
461 | |||
462 | /** | ||
463 | * struct smp_request_phy_control - This structure defines the contents of an | ||
464 | * SMP Phy Controler request. | ||
465 | * | ||
466 | * For specific information on each of these individual fields please reference | ||
467 | * the SAS specification. | ||
468 | */ | ||
469 | struct smp_request_phy_control { | ||
470 | u16 expected_expander_change_count; /* byte 4-5 */ | ||
471 | |||
472 | u16 reserved_byte_6_7; /* byte 6-7 */ | ||
473 | u8 reserved_byte_8; /* byte 8 */ | ||
474 | |||
475 | u8 phy_identifier; /* byte 9 */ | ||
476 | u8 phy_operation; /* byte 10 */ | ||
477 | |||
478 | u8 update_partial_pathway_timeout_value:1; | ||
479 | u8 reserved_byte_11_bit_1_7:7; /* byte 11 */ | ||
480 | |||
481 | u8 reserved_byte_12_23[12]; /* byte 12-23 */ | ||
482 | |||
483 | u8 attached_device_name[8]; /* byte 24-31 */ | ||
484 | |||
485 | u8 reserved_byte_32_bit_3_0:4; /* byte 32 */ | ||
486 | u8 programmed_minimum_physical_link_rate:4; | ||
487 | |||
488 | u8 reserved_byte_33_bit_3_0:4; /* byte 33 */ | ||
489 | u8 programmed_maximum_physical_link_rate:4; | ||
490 | |||
491 | u16 reserved_byte_34_35; /* byte 34-35 */ | ||
492 | |||
493 | u8 partial_pathway_timeout_value:4; | ||
494 | u8 reserved_byte_36_bit_4_7:4; /* byte 36 */ | ||
495 | |||
496 | u16 reserved_byte_37_38; /* byte 37-38 */ | ||
497 | u8 reserved_byte_39; /* byte 39 */ | ||
498 | |||
499 | }; | ||
500 | |||
501 | /** | ||
502 | * struct smp_request_vendor_specific - This structure depicts the vendor | ||
503 | * specific space for SMP request. | ||
504 | * | ||
505 | * | ||
506 | */ | ||
507 | #define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016 | ||
508 | struct smp_request_vendor_specific { | ||
509 | u8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH]; | ||
510 | }; | ||
511 | |||
512 | /** | ||
513 | * struct smp_request - This structure simply unionizes the existing request | ||
514 | * structures into a common request type. | ||
515 | * | ||
516 | * | ||
517 | */ | ||
518 | struct smp_request { | ||
519 | struct smp_request_header header; | ||
520 | |||
521 | union { /* bytes 4-N */ | ||
522 | struct smp_request_general report_general; | ||
523 | struct smp_request_phy_identifier discover; | ||
524 | struct smp_request_general report_manufacturer_information; | ||
525 | struct smp_request_phy_identifier report_phy_sata; | ||
526 | struct smp_request_phy_control phy_control; | ||
527 | struct smp_request_phy_identifier report_phy_error_log; | ||
528 | struct smp_request_phy_identifier report_route_information; | ||
529 | struct smp_request_configure_route_information configure_route_information; | ||
530 | struct smp_request_vendor_specific vendor_specific_request; | ||
531 | } request; | ||
532 | |||
533 | }; | ||
534 | |||
535 | |||
536 | /** | ||
537 | * struct smp_response_report_general - This structure depicts the SMP Report | ||
538 | * General for expander devices. It adheres to the SAS-2.1 specification. | ||
539 | * | ||
540 | * For specific information on each of these individual fields please reference | ||
541 | * the SAS specification Application layer section on SMP. | ||
542 | */ | ||
543 | struct smp_response_report_general { | ||
544 | u16 expander_change_count; /* byte 4-5 */ | ||
545 | u16 expander_route_indexes; /* byte 6-7 */ | ||
546 | |||
547 | u32 reserved_byte8:7; /* byte 8 bit 0-6 */ | ||
548 | u32 long_response:1; /* byte 8 bit 7 */ | ||
549 | |||
550 | u32 number_of_phys:8; /* byte 9 */ | ||
551 | |||
552 | u32 configurable_route_table:1; /* byte 10 */ | ||
553 | u32 configuring:1; | ||
554 | u32 configures_others:1; | ||
555 | u32 open_reject_retry_supported:1; | ||
556 | u32 stp_continue_awt:1; | ||
557 | u32 self_configuring:1; | ||
558 | u32 zone_configuring:1; | ||
559 | u32 table_to_table_supported:1; | ||
560 | |||
561 | u32 reserved_byte11:8; /* byte 11 */ | ||
562 | |||
563 | u32 enclosure_logical_identifier_high; /* byte 12-15 */ | ||
564 | u32 enclosure_logical_identifier_low; /* byte 16-19 */ | ||
565 | |||
566 | u32 reserved_byte20_23; | ||
567 | u32 reserved_byte24_27; | ||
568 | |||
569 | }; | ||
570 | |||
571 | struct smp_response_report_general_long { | ||
572 | struct smp_response_report_general sas1_1; | ||
573 | |||
574 | struct { | ||
575 | u16 reserved1; | ||
576 | u16 stp_bus_inactivity_time_limit; | ||
577 | u16 stp_max_connect_time_limit; | ||
578 | u16 stp_smp_i_t_nexus_loss_time; | ||
579 | |||
580 | u32 zoning_enabled:1; | ||
581 | u32 zoning_supported:1; | ||
582 | u32 physicaL_presence_asserted:1; | ||
583 | u32 zone_locked:1; | ||
584 | u32 reserved2:1; | ||
585 | u32 num_zone_groups:3; | ||
586 | u32 saving_zoning_enabled_supported:3; | ||
587 | u32 saving_zone_perms_table_supported:1; | ||
588 | u32 saving_zone_phy_info_supported:1; | ||
589 | u32 saving_zone_manager_password_supported:1; | ||
590 | u32 saving:1; | ||
591 | u32 reserved3:1; | ||
592 | u32 max_number_routed_sas_addresses:16; | ||
593 | |||
594 | struct sci_sas_address active_zone_manager_sas_address; | ||
595 | |||
596 | u16 zone_lock_inactivity_time_limit; | ||
597 | u16 reserved4; | ||
598 | |||
599 | u8 reserved5; | ||
600 | u8 first_enclosure_connector_element_index; | ||
601 | u8 number_of_enclosure_connector_element_indices; | ||
602 | u8 reserved6; | ||
603 | |||
604 | u32 reserved7:7; | ||
605 | u32 reduced_functionality:1; | ||
606 | u32 time_to_reduce_functionality:8; | ||
607 | u32 initial_time_to_reduce_functionality:8; | ||
608 | u8 max_reduced_functionality_time; | ||
609 | |||
610 | u16 last_self_config_status_descriptor_index; | ||
611 | u16 max_number_of_stored_self_config_status_descriptors; | ||
612 | |||
613 | u16 last_phy_event_list_descriptor_index; | ||
614 | u16 max_number_of_stored_phy_event_list_descriptors; | ||
615 | } sas2; | ||
616 | |||
617 | }; | ||
618 | |||
619 | /** | ||
620 | * struct smp_response_report_manufacturer_information - This structure depicts | ||
621 | * the SMP report manufacturer information for expander devices. It adheres | ||
622 | * to the SAS-2.1 specification. | ||
623 | * | ||
624 | * For specific information on each of these individual fields please reference | ||
625 | * the SAS specification Application layer section on SMP. | ||
626 | */ | ||
627 | struct smp_response_report_manufacturer_information { | ||
628 | u32 expander_change_count:16; /* bytes 4-5 */ | ||
629 | u32 reserved1:16; | ||
630 | |||
631 | u32 sas1_1_format:1; | ||
632 | u32 reserved2:31; | ||
633 | |||
634 | u8 vendor_id[8]; | ||
635 | u8 product_id[16]; | ||
636 | u8 product_revision_level[4]; | ||
637 | u8 component_vendor_id[8]; | ||
638 | u8 component_id[2]; | ||
639 | u8 component_revision_level; | ||
640 | u8 reserved3; | ||
641 | u8 vendor_specific[8]; | ||
642 | |||
643 | }; | ||
644 | |||
645 | #define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52 | ||
646 | #define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE 116 | ||
647 | |||
648 | /** | ||
649 | * struct smp_discover_response_protocols - This structure depicts the discover | ||
650 | * response where the supported protocols by the remote phy are specified. | ||
651 | * | ||
652 | * For specific information on each of these individual fields please reference | ||
653 | * the SAS specification Link layer section on address frames. | ||
654 | */ | ||
655 | struct smp_discover_response_protocols { | ||
656 | union { | ||
657 | struct { | ||
658 | u16 attached_sata_host:1; | ||
659 | u16 attached_smp_initiator:1; | ||
660 | u16 attached_stp_initiator:1; | ||
661 | u16 attached_ssp_initiator:1; | ||
662 | u16 reserved3:4; | ||
663 | u16 attached_sata_device:1; | ||
664 | u16 attached_smp_target:1; | ||
665 | u16 attached_stp_target:1; | ||
666 | u16 attached_ssp_target:1; | ||
667 | u16 reserved4:3; | ||
668 | u16 attached_sata_port_selector:1; | ||
669 | } bits; | ||
670 | |||
671 | u16 all; | ||
672 | } u; | ||
673 | |||
674 | }; | ||
675 | |||
676 | /** | ||
677 | * struct SMP_RESPONSE_DISCOVER_FORMAT - This structure defines the SMP phy | ||
678 | * discover response format. It handles both SAS1.1 and SAS 2 definitions. | ||
679 | * The unions indicate locations where the SAS specification versions differ | ||
680 | * from one another. | ||
681 | * | ||
682 | * | ||
683 | */ | ||
684 | struct smp_response_discover { | ||
685 | |||
686 | union { | ||
687 | struct { | ||
688 | u8 reserved[2]; | ||
689 | } sas1_1; | ||
690 | |||
691 | struct { | ||
692 | u16 expander_change_count; | ||
693 | } sas2; | ||
694 | |||
695 | } u1; | ||
696 | |||
697 | u8 reserved1[3]; | ||
698 | u8 phy_identifier; | ||
699 | u8 reserved2[2]; | ||
700 | |||
701 | union { | ||
702 | struct { | ||
703 | u16 reserved1:4; | ||
704 | u16 attached_device_type:3; | ||
705 | u16 reserved2:1; | ||
706 | u16 negotiated_physical_link_rate:4; | ||
707 | u16 reserved3:4; | ||
708 | } sas1_1; | ||
709 | |||
710 | struct { | ||
711 | u16 attached_reason:4; | ||
712 | u16 attached_device_type:3; | ||
713 | u16 reserved2:1; | ||
714 | u16 negotiated_logical_link_rate:4; | ||
715 | u16 reserved3:4; | ||
716 | } sas2; | ||
717 | |||
718 | } u2; | ||
719 | |||
720 | struct smp_discover_response_protocols protocols; | ||
721 | struct sci_sas_address sas_address; | ||
722 | struct sci_sas_address attached_sas_address; | ||
723 | |||
724 | u8 attached_phy_identifier; | ||
725 | |||
726 | union { | ||
727 | struct { | ||
728 | u8 reserved; | ||
729 | } sas1_1; | ||
730 | |||
731 | struct { | ||
732 | u8 attached_break_reply_capable:1; | ||
733 | u8 attached_requested_inside_zpsds:1; | ||
734 | u8 attached_inside_zpsds_persistent:1; | ||
735 | u8 reserved1:5; | ||
736 | } sas2; | ||
737 | |||
738 | } u3; | ||
739 | |||
740 | u8 reserved_for_identify[6]; | ||
741 | |||
742 | u32 hardware_min_physical_link_rate:4; | ||
743 | u32 programmed_min_physical_link_rate:4; | ||
744 | u32 hardware_max_physical_link_rate:4; | ||
745 | u32 programmed_max_physical_link_rate:4; | ||
746 | u32 phy_change_count:8; | ||
747 | u32 partial_pathway_timeout_value:4; | ||
748 | u32 reserved5:3; | ||
749 | u32 virtual_phy:1; | ||
750 | |||
751 | u32 routing_attribute:4; | ||
752 | u32 reserved6:4; | ||
753 | u32 connector_type:7; | ||
754 | u32 reserved7:1; | ||
755 | u32 connector_element_index:8; | ||
756 | u32 connector_physical_link:8; | ||
757 | |||
758 | u16 reserved8; | ||
759 | u16 vendor_specific; | ||
760 | |||
761 | union { | ||
762 | struct { | ||
763 | /** | ||
764 | * In the SAS 1.1 specification this structure ends after 52 bytes. | ||
765 | * As a result, the contents of this field should never have a | ||
766 | * real value. It is undefined. | ||
767 | */ | ||
768 | u8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE | ||
769 | - SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE]; | ||
770 | } sas1_1; | ||
771 | |||
772 | struct { | ||
773 | struct sci_sas_address attached_device_name; | ||
774 | |||
775 | u32 zoning_enabled:1; | ||
776 | u32 inside_zpsds:1; | ||
777 | u32 zone_group_persistent:1; | ||
778 | u32 reserved1:1; | ||
779 | u32 requested_inside_zpsds:1; | ||
780 | u32 inside_zpsds_persistent:1; | ||
781 | u32 requested_inside_zpsds_changed_by_expander:1; | ||
782 | u32 reserved2:1; | ||
783 | u32 reserved_for_zoning_fields:16; | ||
784 | u32 zone_group:8; | ||
785 | |||
786 | u8 self_configuration_status; | ||
787 | u8 self_configuration_levels_completed; | ||
788 | u16 reserved_for_self_config_fields; | ||
789 | |||
790 | struct sci_sas_address self_configuration_sas_address; | ||
791 | |||
792 | u32 programmed_phy_capabilities; | ||
793 | u32 current_phy_capabilities; | ||
794 | u32 attached_phy_capabilities; | ||
795 | |||
796 | u32 reserved3; | ||
797 | |||
798 | u32 reserved4:16; | ||
799 | u32 negotiated_physical_link_rate:4; | ||
800 | u32 reason:4; | ||
801 | u32 hardware_muxing_supported:1; | ||
802 | u32 negotiated_ssc:1; | ||
803 | u32 reserved5:6; | ||
804 | |||
805 | u32 default_zoning_enabled:1; | ||
806 | u32 reserved6:1; | ||
807 | u32 default_zone_group_persistent:1; | ||
808 | u32 reserved7:1; | ||
809 | u32 default_requested_inside_zpsds:1; | ||
810 | u32 default_inside_zpsds_persistent:1; | ||
811 | u32 reserved8:2; | ||
812 | u32 reserved9:16; | ||
813 | u32 default_zone_group:8; | ||
814 | |||
815 | u32 saved_zoning_enabled:1; | ||
816 | u32 reserved10:1; | ||
817 | u32 saved_zone_group_persistent:1; | ||
818 | u32 reserved11:1; | ||
819 | u32 saved_requested_inside_zpsds:1; | ||
820 | u32 saved_inside_zpsds_persistent:1; | ||
821 | u32 reserved12:18; | ||
822 | u32 saved_zone_group:8; | ||
823 | |||
824 | u32 reserved14:2; | ||
825 | u32 shadow_zone_group_persistent:1; | ||
826 | u32 reserved15:1; | ||
827 | u32 shadow_requested_inside_zpsds:1; | ||
828 | u32 shadow_inside_zpsds_persistent:1; | ||
829 | u32 reserved16:18; | ||
830 | u32 shadow_zone_group:8; | ||
831 | |||
832 | u8 device_slot_number; | ||
833 | u8 device_slot_group_number; | ||
834 | u8 device_slot_group_output_connector[6]; | ||
835 | } sas2; | ||
836 | |||
837 | } u4; | ||
838 | |||
839 | }; | ||
840 | |||
841 | /** | ||
842 | * struct smp_response_report_phy_sata - This structure depicts the contents of | ||
843 | * the SAS SMP REPORT PHY SATA frame. For specific information on each of | ||
844 | * these individual fields please reference the SAS specification Link layer | ||
845 | * section on address frames. | ||
846 | * | ||
847 | * | ||
848 | */ | ||
849 | struct smp_response_report_phy_sata { | ||
850 | u32 ignored_byte_4_7; /* bytes 4-7 */ | ||
851 | |||
852 | u32 affiliations_valid:1; | ||
853 | u32 affiliations_supported:1; | ||
854 | u32 reserved_byte11:6; /* byte 11 */ | ||
855 | u32 ignored_byte10:8; /* byte 10 */ | ||
856 | u32 phy_identifier:8; /* byte 9 */ | ||
857 | u32 reserved_byte_8:8; /* byte 8 */ | ||
858 | |||
859 | u32 reserved_12_15; | ||
860 | u32 stp_sas_address[2]; | ||
861 | u8 device_to_host_fis[20]; | ||
862 | u32 reserved_44_47; | ||
863 | u32 affiliated_stp_initiator_sas_address[2]; | ||
864 | |||
865 | }; | ||
866 | |||
867 | struct smp_response_vendor_specific { | ||
868 | u8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH]; | ||
869 | }; | ||
870 | |||
871 | union smp_response_body { | ||
872 | struct smp_response_report_general report_general; | ||
873 | struct smp_response_report_manufacturer_information report_manufacturer_information; | ||
874 | struct smp_response_discover discover; | ||
875 | struct smp_response_report_phy_sata report_phy_sata; | ||
876 | struct smp_response_vendor_specific vendor_specific_response; | ||
877 | }; | ||
878 | |||
879 | /** | ||
880 | * struct smp_response - This structure simply unionizes the existing response | ||
881 | * structures into a common response type. | ||
882 | * | ||
883 | * | ||
884 | */ | ||
885 | struct smp_response { | ||
886 | struct smp_response_header header; | ||
887 | |||
888 | union smp_response_body response; | ||
889 | |||
890 | }; | ||
891 | |||
892 | /* SMP Request Functions */ | ||
893 | #define SMP_FUNCTION_REPORT_GENERAL 0x00 | ||
894 | #define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION 0x01 | ||
895 | #define SMP_FUNCTION_DISCOVER 0x10 | ||
896 | #define SMP_FUNCTION_REPORT_PHY_ERROR_LOG 0x11 | ||
897 | #define SMP_FUNCTION_REPORT_PHY_SATA 0x12 | ||
898 | #define SMP_FUNCTION_REPORT_ROUTE_INFORMATION 0X13 | ||
899 | #define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION 0X90 | ||
900 | #define SMP_FUNCTION_PHY_CONTROL 0x91 | ||
901 | #define SMP_FUNCTION_PHY_TEST 0x92 | ||
902 | |||
903 | #define SMP_FRAME_TYPE_REQUEST 0x40 | ||
904 | #define SMP_FRAME_TYPE_RESPONSE 0x41 | ||
905 | |||
906 | #define PHY_OPERATION_NOP 0x00 | ||
907 | #define PHY_OPERATION_LINK_RESET 0x01 | ||
908 | #define PHY_OPERATION_HARD_RESET 0x02 | ||
909 | #define PHY_OPERATION_DISABLE 0x03 | ||
910 | #define PHY_OPERATION_CLEAR_ERROR_LOG 0x05 | ||
911 | #define PHY_OPERATION_CLEAR_AFFILIATION 0x06 | ||
912 | |||
913 | #define NPLR_PHY_ENABLED_UNK_LINK_RATE 0x00 | ||
914 | #define NPLR_PHY_DISABLED 0x01 | ||
915 | #define NPLR_PHY_ENABLED_SPD_NEG_FAILED 0x02 | ||
916 | #define NPLR_PHY_ENABLED_SATA_HOLD 0x03 | ||
917 | #define NPLR_PHY_ENABLED_1_5G 0x08 | ||
918 | #define NPLR_PHY_ENABLED_3_0G 0x09 | ||
919 | |||
920 | /* SMP Function Result values. */ | ||
921 | #define SMP_RESULT_FUNCTION_ACCEPTED 0x00 | ||
922 | #define SMP_RESULT_UNKNOWN_FUNCTION 0x01 | ||
923 | #define SMP_RESULT_FUNCTION_FAILED 0x02 | ||
924 | #define SMP_RESULT_INVALID_REQUEST_FRAME_LEN 0x03 | ||
925 | #define SMP_RESULT_INAVALID_EXPANDER_CHANGE_COUNT 0x04 | ||
926 | #define SMP_RESULT_BUSY 0x05 | ||
927 | #define SMP_RESULT_INCOMPLETE_DESCRIPTOR_LIST 0x06 | ||
928 | #define SMP_RESULT_PHY_DOES_NOT_EXIST 0x10 | ||
929 | #define SMP_RESULT_INDEX_DOES_NOT_EXIST 0x11 | ||
930 | #define SMP_RESULT_PHY_DOES_NOT_SUPPORT_SATA 0x12 | ||
931 | #define SMP_RESULT_UNKNOWN_PHY_OPERATION 0x13 | ||
932 | #define SMP_RESULT_UNKNOWN_PHY_TEST_FUNCTION 0x14 | ||
933 | #define SMP_RESULT_PHY_TEST_IN_PROGRESS 0x15 | ||
934 | #define SMP_RESULT_PHY_VACANT 0x16 | ||
935 | |||
936 | /* Attached Device Types */ | ||
937 | #define SMP_NO_DEVICE_ATTACHED 0 | ||
938 | #define SMP_END_DEVICE_ONLY 1 | ||
939 | #define SMP_EDGE_EXPANDER_DEVICE 2 | ||
940 | #define SMP_FANOUT_EXPANDER_DEVICE 3 | ||
941 | |||
942 | /* Expander phy routine attribute */ | ||
943 | #define DIRECT_ROUTING_ATTRIBUTE 0 | ||
944 | #define SUBTRACTIVE_ROUTING_ATTRIBUTE 1 | ||
945 | #define TABLE_ROUTING_ATTRIBUTE 2 | ||
946 | |||
947 | #endif /* _INTEL_SAS_H_ */ | ||
948 | |||
diff --git a/drivers/scsi/isci/core/intel_sat.h b/drivers/scsi/isci/core/intel_sat.h new file mode 100644 index 000000000000..c4d78ed35cf1 --- /dev/null +++ b/drivers/scsi/isci/core/intel_sat.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SAT_H_ | ||
57 | #define _SAT_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains constants and constructs defined in the SCSI to ATA | ||
61 | * Translation (SAT) T10 standard. For more information please refer to | ||
62 | * www.t10.org. | ||
63 | * | ||
64 | * | ||
65 | */ | ||
66 | |||
67 | /** | ||
68 | * | ||
69 | * | ||
70 | * SAT_PROTOCOLS These constants indicate the various protocol values that can | ||
71 | * be supported in a SAT translator. | ||
72 | */ | ||
73 | #define SAT_PROTOCOL_ATA_HARD_RESET 0 | ||
74 | #define SAT_PROTOCOL_SOFT_RESET 1 | ||
75 | #define SAT_PROTOCOL_NON_DATA 3 | ||
76 | #define SAT_PROTOCOL_PIO_DATA_IN 4 | ||
77 | #define SAT_PROTOCOL_PIO_DATA_OUT 5 | ||
78 | #define SAT_PROTOCOL_DMA 6 | ||
79 | #define SAT_PROTOCOL_DMA_QUEUED 7 | ||
80 | #define SAT_PROTOCOL_DEVICE_DIAGNOSTIC 8 | ||
81 | #define SAT_PROTOCOL_DEVICE_RESET 9 | ||
82 | #define SAT_PROTOCOL_UDMA_DATA_IN 10 | ||
83 | #define SAT_PROTOCOL_UDMA_DATA_OUT 11 | ||
84 | #define SAT_PROTOCOL_FPDMA 12 | ||
85 | #define SAT_PROTOCOL_RETURN_RESPONSE_INFO 15 | ||
86 | |||
87 | #define SAT_PROTOCOL_PACKET 0x10 | ||
88 | #define SAT_PROTOCOL_PACKET_NON_DATA (SAT_PROTOCOL_PACKET | 0x0) | ||
89 | #define SAT_PROTOCOL_PACKET_DMA_DATA_IN (SAT_PROTOCOL_PACKET | 0x1) | ||
90 | #define SAT_PROTOCOL_PACKET_DMA_DATA_OUT (SAT_PROTOCOL_PACKET | 0x2) | ||
91 | #define SAT_PROTOCOL_PACKET_PIO_DATA_IN (SAT_PROTOCOL_PACKET | 0x3) | ||
92 | #define SAT_PROTOCOL_PACKET_PIO_DATA_OUT (SAT_PROTOCOL_PACKET | 0x4) | ||
93 | |||
94 | #endif /* _SAT_H_ */ | ||
95 | |||
diff --git a/drivers/scsi/isci/core/intel_sata.h b/drivers/scsi/isci/core/intel_sata.h new file mode 100644 index 000000000000..47390d54064d --- /dev/null +++ b/drivers/scsi/isci/core/intel_sata.h | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SATA_H_ | ||
57 | #define _SATA_H_ | ||
58 | |||
59 | #include <linux/types.h> | ||
60 | |||
61 | /** | ||
62 | * This file defines all of the SATA releated constants, enumerations, and | ||
63 | * types. Please note that this file does not necessarily contain an | ||
64 | * exhaustive list of all contants and commands. | ||
65 | * | ||
66 | * | ||
67 | */ | ||
68 | |||
69 | /** | ||
70 | * | ||
71 | * | ||
72 | * SATA FIS Types These constants depict the various SATA FIS types devined in | ||
73 | * the serial ATA specification. | ||
74 | */ | ||
75 | #define SATA_FIS_TYPE_REGH2D 0x27 | ||
76 | #define SATA_FIS_TYPE_REGD2H 0x34 | ||
77 | #define SATA_FIS_TYPE_SETDEVBITS 0xA1 | ||
78 | #define SATA_FIS_TYPE_DMA_ACTIVATE 0x39 | ||
79 | #define SATA_FIS_TYPE_DMA_SETUP 0x41 | ||
80 | #define SATA_FIS_TYPE_BIST_ACTIVATE 0x58 | ||
81 | #define SATA_FIS_TYPE_PIO_SETUP 0x5F | ||
82 | #define SATA_FIS_TYPE_DATA 0x46 | ||
83 | |||
84 | #define SATA_REGISTER_FIS_SIZE 0x20 | ||
85 | |||
86 | /** | ||
87 | * struct sata_fis_header - This is the common definition for a SATA FIS Header | ||
88 | * word. A different header word is defined for any FIS type that does not | ||
89 | * use the standard header. | ||
90 | * | ||
91 | * | ||
92 | */ | ||
93 | struct sata_fis_header { | ||
94 | u32 fis_type:8; /* word 0 */ | ||
95 | u32 pm_port:4; | ||
96 | u32 reserved:1; | ||
97 | u32 direction_flag:1; /* direction */ | ||
98 | u32 interrupt_flag:1; | ||
99 | u32 command_flag:1; /* command, auto_activate, or notification */ | ||
100 | u32 status:8; | ||
101 | u32 error:8; | ||
102 | }; | ||
103 | |||
104 | |||
105 | /** | ||
106 | * struct sata_fis_reg_h2d - This is the definition for a SATA Host to Device | ||
107 | * Register FIS. | ||
108 | * | ||
109 | * | ||
110 | */ | ||
111 | struct sata_fis_reg_h2d { | ||
112 | u32 fis_type:8; /* word 0 */ | ||
113 | u32 pm_port:4; | ||
114 | u32 reserved0:3; | ||
115 | u32 command_flag:1; | ||
116 | u32 command:8; | ||
117 | u32 features:8; | ||
118 | u32 lba_low:8; /* word 1 */ | ||
119 | u32 lba_mid:8; | ||
120 | u32 lba_high:8; | ||
121 | u32 device:8; | ||
122 | u32 lba_low_exp:8; /* word 2 */ | ||
123 | u32 lba_mid_exp:8; | ||
124 | u32 lba_high_exp:8; | ||
125 | u32 features_exp:8; | ||
126 | u32 sector_count:8; /* word 3 */ | ||
127 | u32 sector_count_exp:8; | ||
128 | u32 reserved1:8; | ||
129 | u32 control:8; | ||
130 | u32 reserved2; /* word 4 */ | ||
131 | }; | ||
132 | |||
133 | /** | ||
134 | * struct sata_fis_reg_d2h - SATA Device To Host FIS | ||
135 | * | ||
136 | * | ||
137 | */ | ||
138 | struct sata_fis_reg_d2h { | ||
139 | u32 fis_type:8; /* word 0 */ | ||
140 | u32 pm_port:4; | ||
141 | u32 reserved0:2; | ||
142 | u32 irq:1; | ||
143 | u32 reserved1:1; | ||
144 | u32 status:8; | ||
145 | u32 error:8; | ||
146 | u8 lba_low; /* word 1 */ | ||
147 | u8 lba_mid; | ||
148 | u8 lba_high; | ||
149 | u8 device; | ||
150 | u8 lba_low_exp; /* word 2 */ | ||
151 | u8 lba_mid_exp; | ||
152 | u8 lba_high_exp; | ||
153 | u8 reserved; | ||
154 | u8 sector_count; /* word 3 */ | ||
155 | u8 sector_count_exp; | ||
156 | u16 reserved2; | ||
157 | u32 reserved3; | ||
158 | }; | ||
159 | |||
160 | /** | ||
161 | * | ||
162 | * | ||
163 | * Status field bit definitions | ||
164 | */ | ||
165 | #define SATA_FIS_STATUS_DEVBITS_MASK (0x77) | ||
166 | |||
167 | /** | ||
168 | * struct sata_fis_set_dev_bits - SATA Set Device Bits FIS | ||
169 | * | ||
170 | * | ||
171 | */ | ||
172 | struct sata_fis_set_dev_bits { | ||
173 | u32 fis_type:8; /* word 0 */ | ||
174 | u32 pm_port:4; | ||
175 | u32 reserved0:2; | ||
176 | u32 irq:1; | ||
177 | u32 notification:1; | ||
178 | u32 status_low:4; | ||
179 | u32 status_high:4; | ||
180 | u32 error:8; | ||
181 | u32 s_active; /* word 1 */ | ||
182 | }; | ||
183 | |||
184 | /** | ||
185 | * struct sata_fis_dma_activate - SATA DMA Activate FIS | ||
186 | * | ||
187 | * | ||
188 | */ | ||
189 | struct sata_fis_dma_activate { | ||
190 | u32 fis_type:8; /* word 0 */ | ||
191 | u32 pm_port:4; | ||
192 | u32 reserved0:24; | ||
193 | }; | ||
194 | |||
195 | /** | ||
196 | * | ||
197 | * | ||
198 | * The lower 5 bits in the DMA Buffer ID Low field of the DMA Setup are used to | ||
199 | * communicate the command tag. | ||
200 | */ | ||
201 | #define SATA_DMA_SETUP_TAG_ENABLE 0x1F | ||
202 | |||
203 | #define SATA_DMA_SETUP_AUTO_ACT_ENABLE 0x80 | ||
204 | |||
205 | /** | ||
206 | * struct sata_fis_dma_setup - SATA DMA Setup FIS | ||
207 | * | ||
208 | * | ||
209 | */ | ||
210 | struct sata_fis_dma_setup { | ||
211 | u32 fis_type:8; /* word 0 */ | ||
212 | u32 pm_port:4; | ||
213 | u32 reserved_00:1; | ||
214 | u32 direction:1; | ||
215 | u32 irq:1; | ||
216 | u32 auto_activate:1; | ||
217 | u32 reserved_01:16; | ||
218 | u32 dma_buffer_id_low; /* word 1 */ | ||
219 | u32 dma_buffer_id_high; /* word 2 */ | ||
220 | u32 reserved0; /* word 3 */ | ||
221 | u32 dma_buffer_offset; /* word 4 */ | ||
222 | u32 dma_transfer_count; /* word 5 */ | ||
223 | u32 reserved1; /* word 6 */ | ||
224 | }; | ||
225 | |||
226 | /** | ||
227 | * struct sata_fis_bist_activate - SATA BIST Activate FIS | ||
228 | * | ||
229 | * | ||
230 | */ | ||
231 | struct sata_fis_bist_activate { | ||
232 | u32 fis_type:8; /* word 0 */ | ||
233 | u32 reserved0:8; | ||
234 | u32 pattern_definition:8; | ||
235 | u32 reserved1:8; | ||
236 | u32 data1; /* word 1 */ | ||
237 | u32 data2; /* word 1 */ | ||
238 | }; | ||
239 | |||
240 | /* | ||
241 | * SATA PIO Setup FIS | ||
242 | */ | ||
243 | struct sata_fis_pio_setup { | ||
244 | u32 fis_type:8; /* word 0 */ | ||
245 | u32 pm_port:4; | ||
246 | u32 reserved_00:1; | ||
247 | u32 direction:1; | ||
248 | u32 irq:1; | ||
249 | u32 reserved_01:1; | ||
250 | u32 status:8; | ||
251 | u32 error:8; | ||
252 | u32 lba_low:8; /* word 1 */ | ||
253 | u32 lba_mid:8; | ||
254 | u32 lba_high:8; | ||
255 | u32 device:8; | ||
256 | u32 lba_low_exp:8; /* word 2 */ | ||
257 | u32 lba_mid_exp:8; | ||
258 | u32 lba_high_exp:8; | ||
259 | u32 reserved:8; | ||
260 | u32 sector_count:8; /* word 3 */ | ||
261 | u32 sector_count_exp:8; | ||
262 | u32 reserved1:8; | ||
263 | u32 ending_status:8; | ||
264 | u32 transfter_count:16; /* word 4 */ | ||
265 | u32 reserved3:16; | ||
266 | }; | ||
267 | |||
268 | /** | ||
269 | * struct sata_fis_data - SATA Data FIS | ||
270 | * | ||
271 | * | ||
272 | */ | ||
273 | struct sata_fis_data { | ||
274 | u32 fis_type:8; /* word 0 */ | ||
275 | u32 pm_port:4; | ||
276 | u32 reserved0:24; | ||
277 | u8 data[4]; /* word 1 */ | ||
278 | }; | ||
279 | |||
280 | #endif /* _SATA_H_ */ | ||
diff --git a/drivers/scsi/isci/core/intel_scsi.h b/drivers/scsi/isci/core/intel_scsi.h new file mode 100644 index 000000000000..1e45d3c98127 --- /dev/null +++ b/drivers/scsi/isci/core/intel_scsi.h | |||
@@ -0,0 +1,474 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file defines all of the SCSI related constants, enumerations, and | ||
58 | * types. Please note that this file does not necessarily contain an | ||
59 | * exhaustive list of all constants, commands, sub-commands, etc. | ||
60 | * | ||
61 | * | ||
62 | */ | ||
63 | |||
64 | #ifndef _SCSI_H__ | ||
65 | #define _SCSI_H__ | ||
66 | |||
67 | |||
68 | /* | ||
69 | * ****************************************************************************** | ||
70 | * * C O N S T A N T S A N D M A C R O S | ||
71 | * ****************************************************************************** */ | ||
72 | |||
73 | /** | ||
74 | * enum _SCSI_TASK_MGMT_REQUEST_CODES - This enumberation contains the | ||
75 | * constants to be used for SCSI task management request codes. SAM does | ||
76 | * not specify any particular values for these codes so constants used here | ||
77 | * are the same as those specified in SAS. | ||
78 | * | ||
79 | * | ||
80 | */ | ||
81 | enum scsi_task_mgmt_request_codes { | ||
82 | SCSI_TASK_REQUEST_ABORT_TASK = 0x01, | ||
83 | SCSI_TASK_REQUEST_ABORT_TASK_SET = 0x02, | ||
84 | SCSI_TASK_REQUEST_CLEAR_TASK_SET = 0x04, | ||
85 | SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET = 0x08, | ||
86 | SCSI_TASK_REQUEST_I_T_NEXUS_RESET = 0x10, | ||
87 | SCSI_TASK_REQUEST_CLEAR_ACA = 0x40, | ||
88 | SCSI_TASK_REQUEST_QUERY_TASK = 0x80, | ||
89 | SCSI_TASK_REQUEST_QUERY_TASK_SET = 0x81, | ||
90 | SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION = 0x82, | ||
91 | |||
92 | }; | ||
93 | |||
94 | /** | ||
95 | * enum _SCSI_TASK_MGMT_RESPONSE_CODES - This enumeration contains all of the | ||
96 | * SCSI task management response codes. | ||
97 | * | ||
98 | * | ||
99 | */ | ||
100 | enum scsi_task_mgmt_response_codes { | ||
101 | SCSI_TASK_MGMT_FUNC_COMPLETE = 0, | ||
102 | SCSI_INVALID_FRAME = 2, | ||
103 | SCSI_TASK_MGMT_FUNC_NOT_SUPPORTED = 4, | ||
104 | SCSI_TASK_MGMT_FUNC_FAILED = 5, | ||
105 | SCSI_TASK_MGMT_FUNC_SUCCEEDED = 8, | ||
106 | SCSI_INVALID_LUN = 9 | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * enum _SCSI_SENSE_RESPONSE_CODE - this enumeration depicts the types of sense | ||
111 | * data responses as per SPC-3. | ||
112 | * | ||
113 | * | ||
114 | */ | ||
115 | enum scsi_sense_response_code { | ||
116 | SCSI_FIXED_CURRENT_RESPONSE_CODE = 0x70, | ||
117 | SCSI_FIXED_DEFERRED_RESPONSE_CODE = 0x71, | ||
118 | SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE = 0x72, | ||
119 | SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE = 0x73 | ||
120 | |||
121 | }; | ||
122 | |||
123 | /* | ||
124 | * This constant represents the valid bit located in byte 0 of a FIXED | ||
125 | * format sense data. */ | ||
126 | #define SCSI_FIXED_SENSE_DATA_VALID_BIT 0x80 | ||
127 | |||
128 | #define SCSI_FIXED_SENSE_DATA_BASE_LENGTH 18 | ||
129 | |||
130 | /* This value is used in the DATAPRES field of the SCSI Response IU. */ | ||
131 | #define SCSI_RESPONSE_DATA_PRES_SENSE_DATA 0x02 | ||
132 | |||
133 | /** | ||
134 | * | ||
135 | * | ||
136 | * SCSI_SENSE_KEYS These constants delineate all of the SCSI protocol sense key | ||
137 | * constants | ||
138 | */ | ||
139 | #define SCSI_SENSE_NO_SENSE 0x00 | ||
140 | #define SCSI_SENSE_RECOVERED_ERROR 0x01 | ||
141 | #define SCSI_SENSE_NOT_READY 0x02 | ||
142 | #define SCSI_SENSE_MEDIUM_ERROR 0x03 | ||
143 | #define SCSI_SENSE_HARDWARE_ERROR 0x04 | ||
144 | #define SCSI_SENSE_ILLEGAL_REQUEST 0x05 | ||
145 | #define SCSI_SENSE_UNIT_ATTENTION 0x06 | ||
146 | #define SCSI_SENSE_DATA_PROTECT 0x07 | ||
147 | #define SCSI_SENSE_BLANK_CHECK 0x08 | ||
148 | #define SCSI_SENSE_VENDOR_SPECIFIC 0x09 | ||
149 | #define SCSI_SENSE_COPY_ABORTED 0x0A | ||
150 | #define SCSI_SENSE_ABORTED_COMMAND 0x0B | ||
151 | #define SCSI_SENSE_VOLUME_OVERFLOW 0x0D | ||
152 | #define SCSI_SENSE_MISCOMPARE 0x0E | ||
153 | |||
154 | /** | ||
155 | * | ||
156 | * | ||
157 | * SCSI_ADDITIONAL_SENSE_CODES These constants delineate all of the SCSI | ||
158 | * protocol additional sense code constants. | ||
159 | */ | ||
160 | #define SCSI_ASC_NO_ADDITIONAL_SENSE 0x00 | ||
161 | #define SCSI_ASC_INITIALIZING_COMMAND_REQUIRED 0x04 | ||
162 | #define SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS 0x04 | ||
163 | #define SCSI_ASC_LUN_FORMAT_IN_PROGRESS 0x04 | ||
164 | #define SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION 0x05 | ||
165 | #define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11 | ||
166 | #define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 | ||
167 | #define SCSI_ASC_LBA_OUT_OF_RANGE 0x21 | ||
168 | #define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24 | ||
169 | #define SCSI_ASC_INVALID_FIELD_IN_PARM_LIST 0x26 | ||
170 | #define SCSI_ASC_WRITE_PROTECTED 0x27 | ||
171 | #define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28 | ||
172 | #define SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED 0x39 | ||
173 | #define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A | ||
174 | #define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44 | ||
175 | #define SCSI_ASC_IU_CRC_ERROR_DETECTED 0x47 | ||
176 | #define SCSI_ASC_MEDIUM_REMOVAL_REQUEST 0x5A | ||
177 | #define SCSI_ASC_COMMAND_SEQUENCE_ERROR 0x2C | ||
178 | #define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED 0x53 | ||
179 | #define SCSI_ASC_HARDWARE_IMPENDING_FAILURE 0x5D | ||
180 | #define SCSI_ASC_POWER_STATE_CHANGE 0x5E | ||
181 | #define SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT 0x40 | ||
182 | #define SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED 0x67 | ||
183 | |||
184 | /** | ||
185 | * | ||
186 | * | ||
187 | * SCSI_ADDITIONAL_SENSE_CODE_QUALIFIERS This enumeration contains all of the | ||
188 | * used SCSI protocol additional sense code qualifier constants. | ||
189 | */ | ||
190 | #define SCSI_ASCQ_NO_ADDITIONAL_SENSE 0x00 | ||
191 | #define SCSI_ASCQ_INVALID_FIELD_IN_CDB 0x00 | ||
192 | #define SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 0x00 | ||
193 | #define SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION 0x00 | ||
194 | #define SCSI_ASCQ_INTERNAL_TARGET_FAILURE 0x00 | ||
195 | #define SCSI_ASCQ_LBA_OUT_OF_RANGE 0x00 | ||
196 | #define SCSI_ASCQ_MEDIUM_NOT_PRESENT 0x00 | ||
197 | #define SCSI_ASCQ_NOT_READY_TO_READY_CHANGE 0x00 | ||
198 | #define SCSI_ASCQ_WRITE_PROTECTED 0x00 | ||
199 | #define SCSI_ASCQ_UNRECOVERED_READ_ERROR 0x00 | ||
200 | #define SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED 0x00 | ||
201 | #define SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE 0x00 | ||
202 | #define SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST 0x01 | ||
203 | #define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 | ||
204 | #define SCSI_ASCQ_IU_CRC_ERROR_DETECTED 0x03 | ||
205 | #define SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS 0x04 | ||
206 | #define SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS 0x09 | ||
207 | #define SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE 0x10 | ||
208 | #define SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND 0x03 | ||
209 | #define SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND 0x04 | ||
210 | #define SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE 0x42 | ||
211 | #define SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY 0x43 | ||
212 | #define SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED 0x0B | ||
213 | #define SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 0x04 | ||
214 | |||
215 | |||
216 | |||
217 | /** | ||
218 | * | ||
219 | * | ||
220 | * SCSI_STATUS_CODES These constants define all of the used SCSI status values. | ||
221 | */ | ||
222 | #define SCSI_STATUS_GOOD 0x00 | ||
223 | #define SCSI_STATUS_CHECK_CONDITION 0x02 | ||
224 | #define SCSI_STATUS_CONDITION_MET 0x04 | ||
225 | #define SCSI_STATUS_BUSY 0x08 | ||
226 | #define SCSI_STATUS_TASKFULL 0x28 | ||
227 | #define SCSI_STATUS_ACA 0x30 | ||
228 | #define SCSI_STATUS_ABORT 0x40 | ||
229 | |||
230 | /** | ||
231 | * | ||
232 | * | ||
233 | * SCSI_OPERATION_CODES These constants delineate all of the SCSI | ||
234 | * command/operation codes. | ||
235 | */ | ||
236 | #define SCSI_INQUIRY 0x12 | ||
237 | #define SCSI_READ_CAPACITY_10 0x25 | ||
238 | #define SCSI_SERVICE_ACTION_IN_16 0x9E | ||
239 | #define SCSI_TEST_UNIT_READY 0x00 | ||
240 | #define SCSI_START_STOP_UNIT 0x1B | ||
241 | #define SCSI_SYNCHRONIZE_CACHE_10 0x35 | ||
242 | #define SCSI_SYNCHRONIZE_CACHE_16 0x91 | ||
243 | #define SCSI_REQUEST_SENSE 0x03 | ||
244 | #define SCSI_REPORT_LUNS 0xA0 | ||
245 | #define SCSI_REASSIGN_BLOCKS 0x07 | ||
246 | #define SCSI_READ_6 0x08 | ||
247 | #define SCSI_READ_10 0x28 | ||
248 | #define SCSI_READ_12 0xA8 | ||
249 | #define SCSI_READ_16 0x88 | ||
250 | #define SCSI_WRITE_6 0x0A | ||
251 | #define SCSI_WRITE_10 0x2A | ||
252 | #define SCSI_WRITE_12 0xAA | ||
253 | #define SCSI_WRITE_16 0x8A | ||
254 | #define SCSI_VERIFY_10 0x2F | ||
255 | #define SCSI_VERIFY_12 0xAF | ||
256 | #define SCSI_VERIFY_16 0x8F | ||
257 | #define SCSI_SEEK_6 0x01 | ||
258 | #define SCSI_SEEK_10 0x02 | ||
259 | #define SCSI_WRITE_VERIFY 0x2E | ||
260 | #define SCSI_FORMAT_UNIT 0x04 | ||
261 | #define SCSI_READ_BUFFER 0x3C | ||
262 | #define SCSI_WRITE_BUFFER 0x3B | ||
263 | #define SCSI_SEND_DIAGNOSTIC 0x1D | ||
264 | #define SCSI_RECEIVE_DIAGNOSTIC 0x1C | ||
265 | #define SCSI_MODE_SENSE_6 0x1A | ||
266 | #define SCSI_MODE_SENSE_10 0x5A | ||
267 | #define SCSI_MODE_SELECT_6 0x15 | ||
268 | #define SCSI_MODE_SELECT_10 0x55 | ||
269 | #define SCSI_MAINTENANCE_IN 0xA3 | ||
270 | #define SCSI_LOG_SENSE 0x4D | ||
271 | #define SCSI_LOG_SELECT 0x4C | ||
272 | #define SCSI_RESERVE_6 0x16 | ||
273 | #define SCSI_RESERVE_10 0x56 | ||
274 | #define SCSI_RELEASE_6 0x17 | ||
275 | #define SCSI_RELEASE_10 0x57 | ||
276 | #define SCSI_ATA_PASSTHRU_12 0xA1 | ||
277 | #define SCSI_ATA_PASSTHRU_16 0x85 | ||
278 | #define SCSI_WRITE_LONG_10 0x3F | ||
279 | #define SCSI_WRITE_LONG_16 0x9F | ||
280 | #define SCSI_PERSISTENT_RESERVE_IN 0x5E | ||
281 | #define SCSI_PERSISTENT_RESERVE_OUT 0x5F | ||
282 | |||
283 | /** | ||
284 | * | ||
285 | * | ||
286 | * SCSI_SERVICE_ACTION_IN_CODES Service action in operations. | ||
287 | */ | ||
288 | #define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16 0x10 | ||
289 | |||
290 | #define SCSI_SERVICE_ACTION_MASK 0x1f | ||
291 | |||
292 | /** | ||
293 | * | ||
294 | * | ||
295 | * SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES MAINTENANCE IN service action codes. | ||
296 | */ | ||
297 | #define SCSI_REPORT_TASK_MGMT 0x0D | ||
298 | #define SCSI_REPORT_OP_CODES 0x0C | ||
299 | |||
300 | /** | ||
301 | * | ||
302 | * | ||
303 | * SCSI_MODE_PAGE_CONTROLS These constants delineate all of the used SCSI Mode | ||
304 | * Page control values. | ||
305 | */ | ||
306 | #define SCSI_MODE_SENSE_PC_CURRENT 0x0 | ||
307 | #define SCSI_MODE_SENSE_PC_CHANGEABLE 0x1 | ||
308 | #define SCSI_MODE_SENSE_PC_DEFAULT 0x2 | ||
309 | #define SCSI_MODE_SENSE_PC_SAVED 0x3 | ||
310 | |||
311 | #define SCSI_MODE_SENSE_PC_SHIFT 0x06 | ||
312 | #define SCSI_MODE_SENSE_PAGE_CODE_ENABLE 0x3F | ||
313 | #define SCSI_MODE_SENSE_DBD_ENABLE 0x08 | ||
314 | #define SCSI_MODE_SENSE_LLBAA_ENABLE 0x10 | ||
315 | |||
316 | /** | ||
317 | * | ||
318 | * | ||
319 | * SCSI_MODE_PAGE_CODES These constants delineate all of the used SCSI Mode | ||
320 | * Page codes. | ||
321 | */ | ||
322 | #define SCSI_MODE_PAGE_READ_WRITE_ERROR 0x01 | ||
323 | #define SCSI_MODE_PAGE_DISCONNECT_RECONNECT 0x02 | ||
324 | #define SCSI_MODE_PAGE_CACHING 0x08 | ||
325 | #define SCSI_MODE_PAGE_CONTROL 0x0A | ||
326 | #define SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT 0x19 | ||
327 | #define SCSI_MODE_PAGE_POWER_CONDITION 0x1A | ||
328 | #define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL 0x1C | ||
329 | #define SCSI_MODE_PAGE_ALL_PAGES 0x3F | ||
330 | |||
331 | #define SCSI_MODE_SENSE_ALL_SUB_PAGES_CODE 0xFF | ||
332 | #define SCSI_MODE_SENSE_NO_SUB_PAGES_CODE 0x0 | ||
333 | #define SCSI_MODE_SENSE_PROTOCOL_PORT_NUM_SUBPAGES 0x1 | ||
334 | #define SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT 0x04 | ||
335 | #define SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT 0x20 | ||
336 | #define SCSI_MODE_PAGE_DEXCPT_ENABLE 0x08 | ||
337 | #define SCSI_MODE_SENSE_HEADER_FUA_ENABLE 0x10 | ||
338 | #define SCSI_MODE_PAGE_POWER_CONDITION_STANDBY 0x1 | ||
339 | #define SCSI_MODE_PAGE_POWER_CONDITION_IDLE 0x2 | ||
340 | |||
341 | #define SCSI_MODE_SENSE_6_HEADER_LENGTH 4 | ||
342 | #define SCSI_MODE_SENSE_10_HEADER_LENGTH 8 | ||
343 | #define SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH 8 | ||
344 | #define SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH 16 | ||
345 | |||
346 | #define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE 0x08 | ||
347 | #define SCSI_MODE_PAGE_19_SAS_ID 0x6 | ||
348 | #define SCSI_MODE_PAGE_19_SUB1_PAGE_NUM 0x1 | ||
349 | #define SCSI_MODE_PAGE_19_SUB1_PC 0x59 | ||
350 | |||
351 | #define SCSI_MODE_HEADER_MEDIUM_TYPE_SBC 0x00 | ||
352 | |||
353 | /* Mode Select constrains related masks value */ | ||
354 | #define SCSI_MODE_SELECT_PF_BIT 0x1 | ||
355 | #define SCSI_MODE_SELECT_PF_MASK 0x10 | ||
356 | #define SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE 0x6 | ||
357 | #define SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK 0x0F | ||
358 | #define SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK 0x40 | ||
359 | #define SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK 0x80 | ||
360 | #define SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK 0x40 | ||
361 | #define SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK 0x1F | ||
362 | #define SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS 0xC1 | ||
363 | #define SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST 0x84 | ||
364 | #define SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC 0xF1 | ||
365 | #define SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER 0xF0 | ||
366 | #define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP 0x38 | ||
367 | #define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO 0x47 | ||
368 | |||
369 | |||
370 | #define SCSI_CONTROL_BYTE_NACA_BIT_ENABLE 0x04 | ||
371 | #define SCSI_MOVE_FUA_BIT_ENABLE 0x08 | ||
372 | #define SCSI_READ_CAPACITY_PMI_BIT_ENABLE 0x01 | ||
373 | #define SCSI_READ_CAPACITY_10_DATA_LENGTH 8 | ||
374 | #define SCSI_READ_CAPACITY_16_DATA_LENGTH 32 | ||
375 | |||
376 | /* Inquiry constants */ | ||
377 | #define SCSI_INQUIRY_EVPD_ENABLE 0x01 | ||
378 | #define SCSI_INQUIRY_PAGE_CODE_OFFSET 0x02 | ||
379 | #define SCSI_INQUIRY_SUPPORTED_PAGES_PAGE 0x00 | ||
380 | #define SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE 0x80 | ||
381 | #define SCSI_INQUIRY_DEVICE_ID_PAGE 0x83 | ||
382 | #define SCSI_INQUIRY_ATA_INFORMATION_PAGE 0x89 | ||
383 | #define SCSI_INQUIRY_BLOCK_DEVICE_PAGE 0xB1 | ||
384 | #define SCSI_INQUIRY_BLOCK_DEVICE_LENGTH 0x3C | ||
385 | #define SCSI_INQUIRY_STANDARD_ALLOCATION_LENGTH 0x24 /* 36 */ | ||
386 | |||
387 | #define SCSI_REQUEST_SENSE_ALLOCATION_LENGTH 0xFC /* 252 */ | ||
388 | |||
389 | /** Defines the log page codes that are use in gathing Smart data | ||
390 | */ | ||
391 | #define SCSI_LOG_PAGE_SUPPORTED_PAGES 0x00 | ||
392 | #define SCSI_LOG_PAGE_INFORMATION_EXCEPTION 0x2F | ||
393 | #define SCSI_LOG_PAGE_SELF_TEST 0x10 | ||
394 | |||
395 | /** | ||
396 | * | ||
397 | * | ||
398 | * SCSI_INQUIRY_VPD The following are constants used with vital product data | ||
399 | * inquiry pages. Values are already shifted into the proper nibble location. | ||
400 | */ | ||
401 | #define SCSI_PIV_ENABLE 0x80 | ||
402 | #define SCSI_LUN_ASSOCIATION 0x00 | ||
403 | #define SCSI_TARGET_PORT_ASSOCIATION 0x10 | ||
404 | |||
405 | #define SCSI_VEN_UNIQUE_IDENTIFIER_TYPE 0x00 | ||
406 | #define SCSI_NAA_IDENTIFIER_TYPE 0x03 | ||
407 | |||
408 | #define SCSI_T10_IDENTIFIER_TYPE 0x01 | ||
409 | #define SCSI_BINARY_CODE_SET 0x01 | ||
410 | #define SCSI_ASCII_CODE_SET 0x02 | ||
411 | #define SCSI_FC_PROTOCOL_IDENTIFIER 0x00 | ||
412 | #define SCSI_SAS_PROTOCOL_IDENTIFIER 0x60 | ||
413 | |||
414 | #define SCSI_VERIFY_BYTCHK_ENABLED 0x02 | ||
415 | |||
416 | #define SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED 0x02 | ||
417 | /** | ||
418 | * | ||
419 | * | ||
420 | * SCSI_START_STOP_UNIT_POWER_CONDITION_CODES The following are SCSI Start Stop | ||
421 | * Unit command Power Condition codes. | ||
422 | */ | ||
423 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID 0x0 | ||
424 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE 0x1 | ||
425 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE 0x2 | ||
426 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY 0x3 | ||
427 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL 0x7 | ||
428 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL 0xB | ||
429 | |||
430 | #define SCSI_START_STOP_UNIT_IMMED_MASK 0x1 | ||
431 | #define SCSI_START_STOP_UNIT_IMMED_SHIFT 0 | ||
432 | |||
433 | #define SCSI_START_STOP_UNIT_START_BIT_MASK 0x1 | ||
434 | #define SCSI_START_STOP_UNIT_START_BIT_SHIFT 0 | ||
435 | |||
436 | #define SCSI_START_STOP_UNIT_LOEJ_BIT_MASK 0x2 | ||
437 | #define SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT 1 | ||
438 | |||
439 | #define SCSI_START_STOP_UNIT_NO_FLUSH_MASK 0x4 | ||
440 | #define SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT 2 | ||
441 | |||
442 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK 0xF | ||
443 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT 0 | ||
444 | |||
445 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_MASK 0xF0 | ||
446 | #define SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT 4 | ||
447 | |||
448 | #define SCSI_LOG_SENSE_PC_FIELD_MASK 0xC0 | ||
449 | #define SCSI_LOG_SENSE_PC_FIELD_SHIFT 6 | ||
450 | |||
451 | #define SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK 0x3F | ||
452 | #define SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT 0 | ||
453 | |||
454 | /** | ||
455 | * | ||
456 | * | ||
457 | * MRIE - Method of reporting informational exceptions codes | ||
458 | */ | ||
459 | #define NO_REPORTING_INFO_EXCEPTION_CONDITION 0x0 | ||
460 | #define ASYNCHRONOUS_EVENT_REPORTING 0x1 | ||
461 | #define ESTABLISH_UNIT_ATTENTION_CONDITION 0x2 | ||
462 | #define CONDITIONALLY_GENERATE_RECOVERED_ERROR 0x3 | ||
463 | #define UNCONDITIONALLY_GENERATE_RECOVERED_ERROR 0x4 | ||
464 | #define GENERATE_NO_SENSE 0x5 | ||
465 | #define REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6 | ||
466 | |||
467 | #define SCSI_INFORMATION_EXCEPTION_DEXCPT_BIT 0x08 | ||
468 | |||
469 | /* Reassign Blocks masks */ | ||
470 | #define SCSI_REASSIGN_BLOCKS_LONGLBA_BIT 0x02 | ||
471 | #define SCSI_REASSIGN_BLOCKS_LONGLIST_BIT 0x01 | ||
472 | |||
473 | #endif /* _SCSI_H_ */ | ||
474 | |||
diff --git a/drivers/scsi/isci/core/sati_device.h b/drivers/scsi/isci/core/sati_device.h new file mode 100644 index 000000000000..4d1cfde12cae --- /dev/null +++ b/drivers/scsi/isci/core/sati_device.h | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SATI_DEVICE_H_ | ||
57 | #define _SATI_DEVICE_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the defintions for the SATI remote device object. | ||
61 | * Some translations require information to be remembered on a per device | ||
62 | * basis. This information is stored in the object defined in this file. | ||
63 | * | ||
64 | * | ||
65 | */ | ||
66 | |||
67 | #include "sati_types.h" | ||
68 | #include "intel_ata.h" | ||
69 | |||
70 | /** | ||
71 | * enum _SATI_DEVICE_STATE - This enumeration depicts the various states | ||
72 | * possible for the a translation remote device object. | ||
73 | * | ||
74 | * | ||
75 | */ | ||
76 | enum sati_device_state { | ||
77 | SATI_DEVICE_STATE_OPERATIONAL, | ||
78 | SATI_DEVICE_STATE_STOPPED, | ||
79 | SATI_DEVICE_STATE_STANDBY, | ||
80 | SATI_DEVICE_STATE_IDLE, | ||
81 | SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED, | ||
82 | SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS, | ||
83 | SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS, | ||
84 | SATI_DEVICE_STATE_SEQUENCE_INCOMPLETE, | ||
85 | SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION | ||
86 | |||
87 | }; | ||
88 | |||
89 | /** | ||
90 | * | ||
91 | * | ||
92 | * SATI_DEVICE_CAPABILITIES These constants define the various capabilities | ||
93 | * that a remote device may support for which there is an impact on translation. | ||
94 | */ | ||
95 | #define SATI_DEVICE_CAP_UDMA_ENABLE 0x00000001 | ||
96 | #define SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE 0x00000002 | ||
97 | #define SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE 0x00000004 | ||
98 | #define SATI_DEVICE_CAP_48BIT_ENABLE 0x00000008 | ||
99 | #define SATI_DEVICE_CAP_DMA_FUA_ENABLE 0x00000010 | ||
100 | #define SATI_DEVICE_CAP_SMART_SUPPORT 0x00000020 | ||
101 | #define SATI_DEVICE_CAP_REMOVABLE_MEDIA 0x00000040 | ||
102 | #define SATI_DEVICE_CAP_SMART_ENABLE 0x00000080 | ||
103 | #define SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE 0x00000100 | ||
104 | #define SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR 0x00000200 | ||
105 | #define SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT 0x00000400 | ||
106 | |||
107 | |||
108 | /** | ||
109 | * struct sati_device - The SATI_DEVICE structure define the state of the | ||
110 | * remote device with respect to translation. | ||
111 | * | ||
112 | * | ||
113 | */ | ||
114 | struct sati_device { | ||
115 | /** | ||
116 | * This field simply dictates the state of the SATI device. | ||
117 | */ | ||
118 | enum sati_device_state state; | ||
119 | |||
120 | /** | ||
121 | * This field indicates features supported by the remote device that | ||
122 | * impact translation execution. | ||
123 | */ | ||
124 | u16 capabilities; | ||
125 | |||
126 | /** | ||
127 | * This field indicates the depth of the native command queue supported | ||
128 | * by the device. | ||
129 | */ | ||
130 | u8 ncq_depth; | ||
131 | |||
132 | /** | ||
133 | * This field stores the additional sense code for a unit attention | ||
134 | * condition. | ||
135 | */ | ||
136 | u8 unit_attention_asc; | ||
137 | |||
138 | /** | ||
139 | * This field indicates the additional sense code qualifier for a unit | ||
140 | * attention condition. | ||
141 | */ | ||
142 | u8 unit_attention_ascq; | ||
143 | |||
144 | }; | ||
145 | |||
146 | void sati_device_construct( | ||
147 | struct sati_device *device, | ||
148 | bool is_ncq_enabled, | ||
149 | u8 max_ncq_depth); | ||
150 | |||
151 | void sati_device_update_capabilities( | ||
152 | struct sati_device *device, | ||
153 | struct ata_identify_device_data *identify); | ||
154 | |||
155 | #endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */ | ||
156 | |||
diff --git a/drivers/scsi/isci/core/sati_translator_sequence.h b/drivers/scsi/isci/core/sati_translator_sequence.h new file mode 100644 index 000000000000..592570d50ebd --- /dev/null +++ b/drivers/scsi/isci/core/sati_translator_sequence.h | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SATI_TRANSLATOR_SEQUENCE_H_ | ||
57 | #define _SATI_TRANSLATOR_SEQUENCE_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the defintions for the SATI translator sequence. | ||
61 | * A translator sequence is simply a defintion for the various sequences of | ||
62 | * commands that occur in this translator. | ||
63 | * | ||
64 | * | ||
65 | */ | ||
66 | |||
67 | #include "sati_device.h" | ||
68 | |||
69 | /** | ||
70 | * enum _SATI_TRANSLATOR_SEQUENCE_TYPE - This enumeration defines the possible | ||
71 | * sequence types for the translator. | ||
72 | * | ||
73 | * | ||
74 | */ | ||
75 | enum sati_translator_sequence_type { | ||
76 | /* SCSI Primary Command (SPC) sequences. */ | ||
77 | SATI_SEQUENCE_REPORT_LUNS, | ||
78 | SATI_SEQUENCE_TEST_UNIT_READY, | ||
79 | SATI_SEQUENCE_INQUIRY_STANDARD, | ||
80 | SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES, | ||
81 | SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER, | ||
82 | SATI_SEQUENCE_INQUIRY_DEVICE_ID, | ||
83 | SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE, | ||
84 | SATI_SEQUENCE_MODE_SENSE_6_CACHING, | ||
85 | SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL, | ||
86 | SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR, | ||
87 | SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT, | ||
88 | SATI_SEQUENCE_MODE_SENSE_6_CONTROL, | ||
89 | SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES, | ||
90 | SATI_SEQUENCE_MODE_SENSE_10_CACHING, | ||
91 | SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL, | ||
92 | SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR, | ||
93 | SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT, | ||
94 | SATI_SEQUENCE_MODE_SENSE_10_CONTROL, | ||
95 | SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES, | ||
96 | SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING, | ||
97 | SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION, | ||
98 | SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL, | ||
99 | |||
100 | /* Log Sense Sequences */ | ||
101 | SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE, | ||
102 | SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE, | ||
103 | SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE, | ||
104 | SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE, | ||
105 | |||
106 | /* SCSI Block Command (SBC) sequences. */ | ||
107 | |||
108 | SATI_SEQUENCE_READ_6, | ||
109 | SATI_SEQUENCE_READ_10, | ||
110 | SATI_SEQUENCE_READ_12, | ||
111 | SATI_SEQUENCE_READ_16, | ||
112 | |||
113 | SATI_SEQUENCE_READ_CAPACITY_10, | ||
114 | SATI_SEQUENCE_READ_CAPACITY_16, | ||
115 | |||
116 | SATI_SEQUENCE_SYNCHRONIZE_CACHE, | ||
117 | |||
118 | SATI_SEQUENCE_VERIFY_10, | ||
119 | SATI_SEQUENCE_VERIFY_12, | ||
120 | SATI_SEQUENCE_VERIFY_16, | ||
121 | |||
122 | SATI_SEQUENCE_WRITE_6, | ||
123 | SATI_SEQUENCE_WRITE_10, | ||
124 | SATI_SEQUENCE_WRITE_12, | ||
125 | SATI_SEQUENCE_WRITE_16, | ||
126 | |||
127 | SATI_SEQUENCE_START_STOP_UNIT, | ||
128 | |||
129 | SATI_SEQUENCE_REASSIGN_BLOCKS, | ||
130 | |||
131 | /* SCSI Task Requests sequences */ | ||
132 | |||
133 | SATI_SEQUENCE_LUN_RESET, | ||
134 | |||
135 | SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS, | ||
136 | SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE, | ||
137 | |||
138 | SATI_SEQUENCE_WRITE_LONG | ||
139 | |||
140 | }; | ||
141 | |||
142 | #define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6 | ||
143 | #define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16 | ||
144 | |||
145 | /** | ||
146 | * | ||
147 | * | ||
148 | * SATI_SEQUENCE_STATES These constants depict the various state values | ||
149 | * associated with a translation sequence. | ||
150 | */ | ||
151 | #define SATI_SEQUENCE_STATE_INITIAL 0 | ||
152 | #define SATI_SEQUENCE_STATE_TRANSLATE_DATA 1 | ||
153 | #define SATI_SEQUENCE_STATE_AWAIT_RESPONSE 2 | ||
154 | #define SATI_SEQUENCE_STATE_FINAL 3 | ||
155 | #define SATI_SEQUENCE_STATE_INCOMPLETE 4 | ||
156 | |||
157 | /** | ||
158 | * | ||
159 | * | ||
160 | * SATI_DATA_DIRECTIONS These constants depict the various types of data | ||
161 | * directions for a translation sequence. Data can flow in/out (read/write) or | ||
162 | * no data at all. | ||
163 | */ | ||
164 | #define SATI_DATA_DIRECTION_NONE 0 | ||
165 | #define SATI_DATA_DIRECTION_IN 1 | ||
166 | #define SATI_DATA_DIRECTION_OUT 2 | ||
167 | |||
168 | /** | ||
169 | * struct SATI_MODE_SELECT_PROCESSING_STATE - This structure contains all of | ||
170 | * the current processing states for processing mode select 6 and 10 | ||
171 | * commands' parameter fields. | ||
172 | * | ||
173 | * | ||
174 | */ | ||
175 | typedef struct SATI_MODE_SELECT_PROCESSING_STATE { | ||
176 | u8 *mode_pages; | ||
177 | u32 mode_page_offset; | ||
178 | u32 mode_pages_size; | ||
179 | u32 size_of_data_processed; | ||
180 | u32 total_ata_command_sent; | ||
181 | u32 ata_command_sent_for_cmp; /* cmp: current mode page */ | ||
182 | bool current_mode_page_processed; | ||
183 | |||
184 | } SATI_MODE_SELECT_PROCESSING_STATE_T; | ||
185 | |||
186 | |||
187 | enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS { | ||
188 | SATI_REASSIGN_BLOCKS_READY_TO_SEND, | ||
189 | SATI_REASSIGN_BLOCKS_COMMAND_FAIL, | ||
190 | SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS, | ||
191 | }; | ||
192 | |||
193 | /** | ||
194 | * struct sati_reassign_blocks_processing_state - This structure contains all | ||
195 | * of the current processing states for processing reassign block command's | ||
196 | * parameter fields. | ||
197 | * | ||
198 | * | ||
199 | */ | ||
200 | struct sati_reassign_blocks_processing_state { | ||
201 | u32 lba_offset; | ||
202 | u32 block_lists_size; | ||
203 | u8 lba_size; | ||
204 | u32 size_of_data_processed; | ||
205 | u32 ata_command_sent_for_current_lba; | ||
206 | bool current_lba_processed; | ||
207 | enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS ata_command_status; | ||
208 | |||
209 | }; | ||
210 | |||
211 | #define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12 | ||
212 | |||
213 | /** | ||
214 | * struct sati_atapi_data - The SATI_ATAPI_DATA structure is for sati atapi IO | ||
215 | * specific data. | ||
216 | * | ||
217 | * | ||
218 | */ | ||
219 | struct sati_atapi_data { | ||
220 | u8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH]; | ||
221 | }; | ||
222 | |||
223 | /** | ||
224 | * struct sati_translator_sequence - This structure contains all of the | ||
225 | * translation information associated with a particular request. | ||
226 | * | ||
227 | * | ||
228 | */ | ||
229 | struct sati_translator_sequence { | ||
230 | /** | ||
231 | * This field contains the sequence type determined by the SATI. | ||
232 | */ | ||
233 | u8 type; | ||
234 | |||
235 | /** | ||
236 | * This field indicates the current state for the sequence. | ||
237 | */ | ||
238 | u8 state; | ||
239 | |||
240 | /** | ||
241 | * This field indicates the data direction (none, read, or write) for | ||
242 | * the translated request. | ||
243 | */ | ||
244 | u8 data_direction; | ||
245 | |||
246 | /** | ||
247 | * This field contains the SATA/ATA protocol to be utilized during | ||
248 | * the IO transfer. | ||
249 | */ | ||
250 | u8 protocol; | ||
251 | |||
252 | /** | ||
253 | * This field is utilized for sequences requiring data translation. | ||
254 | * It specifies the amount of data requested by the caller from the | ||
255 | * operation. It's necessary, because at times the user requests less | ||
256 | * data than is available. Thus, we need to avoid overrunning the | ||
257 | * buffer. | ||
258 | */ | ||
259 | u32 allocation_length; | ||
260 | |||
261 | /** | ||
262 | * This field specifies the amount of data that will actually be | ||
263 | * transfered across the wire for this ATA request. | ||
264 | */ | ||
265 | u32 ata_transfer_length; | ||
266 | |||
267 | /** | ||
268 | * This field specifies the amount of data bytes that have been | ||
269 | * set in a translation sequence. It will be incremented every time | ||
270 | * a data byte has been set by a sati translation. | ||
271 | */ | ||
272 | u16 number_data_bytes_set; | ||
273 | |||
274 | /** | ||
275 | * This field indicates whether or not the sense response has been set | ||
276 | * by the translation sequence. | ||
277 | */ | ||
278 | bool is_sense_response_set; | ||
279 | |||
280 | /** | ||
281 | * This field specifies the remote device context for which this | ||
282 | * translator sequence is destined. | ||
283 | */ | ||
284 | struct sati_device *device; | ||
285 | |||
286 | /** | ||
287 | * This field is utilized to provide the translator with memory space | ||
288 | * required for translations that utilize multiple requests. | ||
289 | */ | ||
290 | union { | ||
291 | u32 translated_command; | ||
292 | u32 move_sector_count; | ||
293 | u32 scratch; | ||
294 | struct sati_reassign_blocks_processing_state reassign_blocks_process_state; | ||
295 | SATI_MODE_SELECT_PROCESSING_STATE_T process_state; | ||
296 | struct sati_atapi_data sati_atapi_data; | ||
297 | } command_specific_data; | ||
298 | |||
299 | }; | ||
300 | |||
301 | |||
302 | |||
303 | #endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */ | ||
304 | |||
diff --git a/drivers/scsi/isci/core/sati_types.h b/drivers/scsi/isci/core/sati_types.h new file mode 100644 index 000000000000..b6159e06c280 --- /dev/null +++ b/drivers/scsi/isci/core/sati_types.h | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SATI_TYPES_H_ | ||
57 | #define _SATI_TYPES_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains various type definitions to be utilized with SCSI to ATA | ||
61 | * Translation Implementation. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | /** | ||
67 | * enum _SATI_STATUS - This enumeration defines the possible return values from | ||
68 | * the SATI translation methods. | ||
69 | * | ||
70 | * | ||
71 | */ | ||
72 | enum sati_status { | ||
73 | /** | ||
74 | * This indicates that the translation was supported and occurred | ||
75 | * without error. | ||
76 | */ | ||
77 | SATI_SUCCESS, | ||
78 | |||
79 | /** | ||
80 | * This indicates that the translation was supported, occurred without | ||
81 | * error, and no additional translation is necessary. This is done in | ||
82 | * conditions where the SCSI command doesn't require any interaction with | ||
83 | * the remote device. | ||
84 | */ | ||
85 | SATI_COMPLETE, | ||
86 | |||
87 | /** | ||
88 | * This indicated everything SATI_COMPLETE does in addition to the response data | ||
89 | * not using all the memory allocated by the OS. | ||
90 | */ | ||
91 | SATI_COMPLETE_IO_DONE_EARLY, | ||
92 | |||
93 | /** | ||
94 | * This indicates that translator sequence has finished some specific | ||
95 | * command in the sequence, but additional commands are necessary. | ||
96 | */ | ||
97 | SATI_SEQUENCE_INCOMPLETE, | ||
98 | |||
99 | /** | ||
100 | * This indicates a general failure has occurred for which no further | ||
101 | * specification information is available. | ||
102 | */ | ||
103 | SATI_FAILURE, | ||
104 | |||
105 | /** | ||
106 | * This indicates that the result of the IO request indicates a | ||
107 | * failure. The caller should reference the corresponding response | ||
108 | * data for further details. | ||
109 | */ | ||
110 | SATI_FAILURE_CHECK_RESPONSE_DATA, | ||
111 | |||
112 | /** | ||
113 | * This status indicates that the supplied sequence type doesn't map | ||
114 | * to an existing definition. | ||
115 | */ | ||
116 | SATI_FAILURE_INVALID_SEQUENCE_TYPE, | ||
117 | |||
118 | /** | ||
119 | * This status indicates that the supplied sequence state doesn't match | ||
120 | * the operation being requested by the user. | ||
121 | */ | ||
122 | SATI_FAILURE_INVALID_STATE | ||
123 | |||
124 | }; | ||
125 | |||
126 | #if (!defined(DISABLE_SATI_MODE_SENSE) \ | ||
127 | || !defined(DISABLE_SATI_MODE_SELECT) \ | ||
128 | || !defined(DISABLE_SATI_REQUEST_SENSE)) \ | ||
129 | |||
130 | #if !defined(ENABLE_SATI_MODE_PAGES) | ||
131 | /** | ||
132 | * | ||
133 | * | ||
134 | * This macro enables the common mode page data structures and code. Currently, | ||
135 | * MODE SENSE, MODE SELECT, and REQUEST SENSE all make reference to this common | ||
136 | * code. As a result, enable the common mode page code if any of these 3 are | ||
137 | * being translated. | ||
138 | */ | ||
139 | #define ENABLE_SATI_MODE_PAGES | ||
140 | #endif /* !defined(ENABLE_SATI_MODE_PAGES) */ | ||
141 | |||
142 | #endif /* MODE_SENSE/SELECT/REQUEST_SENSE */ | ||
143 | |||
144 | #endif /* _SATI_TYPES_H_ */ | ||
145 | |||
diff --git a/drivers/scsi/isci/core/sci_base_controller.h b/drivers/scsi/isci/core/sci_base_controller.h new file mode 100644 index 000000000000..36c53406ea5a --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_controller.h | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_CONTROLLER_H_ | ||
57 | #define _SCI_BASE_CONTROLLER_H_ | ||
58 | |||
59 | #include "intel_sas.h" | ||
60 | #include "sci_controller_constants.h" | ||
61 | #include "sci_base_state.h" | ||
62 | #include "sci_base_memory_descriptor_list.h" | ||
63 | #include "sci_base_state_machine.h" | ||
64 | #include "sci_object.h" | ||
65 | |||
66 | struct sci_base_memory_descriptor_list; | ||
67 | |||
68 | /** | ||
69 | * enum sci_base_controller_states - This enumeration depicts all the states | ||
70 | * for the common controller state machine. | ||
71 | * | ||
72 | * | ||
73 | */ | ||
74 | enum sci_base_controller_states { | ||
75 | /** | ||
76 | * Simply the initial state for the base controller state machine. | ||
77 | */ | ||
78 | SCI_BASE_CONTROLLER_STATE_INITIAL = 0, | ||
79 | |||
80 | /** | ||
81 | * This state indicates that the controller is reset. The memory for | ||
82 | * the controller is in it's initial state, but the controller requires | ||
83 | * initialization. | ||
84 | * This state is entered from the INITIAL state. | ||
85 | * This state is entered from the RESETTING state. | ||
86 | */ | ||
87 | SCI_BASE_CONTROLLER_STATE_RESET, | ||
88 | |||
89 | /** | ||
90 | * This state is typically an action state that indicates the controller | ||
91 | * is in the process of initialization. In this state no new IO operations | ||
92 | * are permitted. | ||
93 | * This state is entered from the RESET state. | ||
94 | */ | ||
95 | SCI_BASE_CONTROLLER_STATE_INITIALIZING, | ||
96 | |||
97 | /** | ||
98 | * This state indicates that the controller has been successfully | ||
99 | * initialized. In this state no new IO operations are permitted. | ||
100 | * This state is entered from the INITIALIZING state. | ||
101 | */ | ||
102 | SCI_BASE_CONTROLLER_STATE_INITIALIZED, | ||
103 | |||
104 | /** | ||
105 | * This state indicates the the controller is in the process of becoming | ||
106 | * ready (i.e. starting). In this state no new IO operations are permitted. | ||
107 | * This state is entered from the INITIALIZED state. | ||
108 | */ | ||
109 | SCI_BASE_CONTROLLER_STATE_STARTING, | ||
110 | |||
111 | /** | ||
112 | * This state indicates the controller is now ready. Thus, the user | ||
113 | * is able to perform IO operations on the controller. | ||
114 | * This state is entered from the STARTING state. | ||
115 | */ | ||
116 | SCI_BASE_CONTROLLER_STATE_READY, | ||
117 | |||
118 | /** | ||
119 | * This state is typically an action state that indicates the controller | ||
120 | * is in the process of resetting. Thus, the user is unable to perform | ||
121 | * IO operations on the controller. A reset is considered destructive in | ||
122 | * most cases. | ||
123 | * This state is entered from the READY state. | ||
124 | * This state is entered from the FAILED state. | ||
125 | * This state is entered from the STOPPED state. | ||
126 | */ | ||
127 | SCI_BASE_CONTROLLER_STATE_RESETTING, | ||
128 | |||
129 | /** | ||
130 | * This state indicates that the controller is in the process of stopping. | ||
131 | * In this state no new IO operations are permitted, but existing IO | ||
132 | * operations are allowed to complete. | ||
133 | * This state is entered from the READY state. | ||
134 | */ | ||
135 | SCI_BASE_CONTROLLER_STATE_STOPPING, | ||
136 | |||
137 | /** | ||
138 | * This state indicates that the controller has successfully been stopped. | ||
139 | * In this state no new IO operations are permitted. | ||
140 | * This state is entered from the STOPPING state. | ||
141 | */ | ||
142 | SCI_BASE_CONTROLLER_STATE_STOPPED, | ||
143 | |||
144 | /** | ||
145 | * This state indicates that the controller could not successfully be | ||
146 | * initialized. In this state no new IO operations are permitted. | ||
147 | * This state is entered from the INITIALIZING state. | ||
148 | * This state is entered from the STARTING state. | ||
149 | * This state is entered from the STOPPING state. | ||
150 | * This state is entered from the RESETTING state. | ||
151 | */ | ||
152 | SCI_BASE_CONTROLLER_STATE_FAILED, | ||
153 | |||
154 | SCI_BASE_CONTROLLER_MAX_STATES | ||
155 | |||
156 | }; | ||
157 | |||
158 | /** | ||
159 | * struct sci_base_controller - The base controller object abstracts the fields | ||
160 | * common to all SCI controller objects. | ||
161 | * | ||
162 | * | ||
163 | */ | ||
164 | struct sci_base_controller { | ||
165 | /** | ||
166 | * The field specifies that the parent object for the base controller | ||
167 | * is the base object itself. | ||
168 | */ | ||
169 | struct sci_base_object parent; | ||
170 | |||
171 | /** | ||
172 | * This field points to the memory descriptor list associated with this | ||
173 | * controller. The MDL indicates the memory requirements necessary for | ||
174 | * this controller object. | ||
175 | */ | ||
176 | struct sci_base_memory_descriptor_list mdl; | ||
177 | |||
178 | /** | ||
179 | * This field contains the information for the base controller state | ||
180 | * machine. | ||
181 | */ | ||
182 | struct sci_base_state_machine state_machine; | ||
183 | }; | ||
184 | |||
185 | /* Forward declarations */ | ||
186 | struct sci_base_remote_device; | ||
187 | struct sci_base_request; | ||
188 | |||
189 | typedef enum sci_status | ||
190 | (*sci_base_controller_handler_t)(struct sci_base_controller *); | ||
191 | |||
192 | typedef enum sci_status | ||
193 | (*sci_base_controller_timed_handler_t)(struct sci_base_controller *, u32); | ||
194 | |||
195 | typedef enum sci_status | ||
196 | (*sci_base_controller_request_handler_t)(struct sci_base_controller *, | ||
197 | struct sci_base_remote_device *, | ||
198 | struct sci_base_request *); | ||
199 | |||
200 | typedef enum sci_status | ||
201 | (*sci_base_controller_start_request_handler_t)(struct sci_base_controller *, | ||
202 | struct sci_base_remote_device *, | ||
203 | struct sci_base_request *, u16); | ||
204 | |||
205 | /** | ||
206 | * struct sci_base_controller_state_handler - This structure contains all of | ||
207 | * the state handler methods common to base controller state machines. | ||
208 | * Handler methods provide the ability to change the behavior for user | ||
209 | * requests or transitions depending on the state the machine is in. | ||
210 | * | ||
211 | * | ||
212 | */ | ||
213 | struct sci_base_controller_state_handler { | ||
214 | /** | ||
215 | * The start_handler specifies the method invoked when a user attempts to | ||
216 | * start a controller. | ||
217 | */ | ||
218 | sci_base_controller_timed_handler_t start; | ||
219 | |||
220 | /** | ||
221 | * The stop_handler specifies the method invoked when a user attempts to | ||
222 | * stop a controller. | ||
223 | */ | ||
224 | sci_base_controller_timed_handler_t stop; | ||
225 | |||
226 | /** | ||
227 | * The reset_handler specifies the method invoked when a user attempts to | ||
228 | * reset a controller. | ||
229 | */ | ||
230 | sci_base_controller_handler_t reset; | ||
231 | |||
232 | /** | ||
233 | * The initialize_handler specifies the method invoked when a user | ||
234 | * attempts to initialize a controller. | ||
235 | */ | ||
236 | sci_base_controller_handler_t initialize; | ||
237 | |||
238 | /** | ||
239 | * The start_io_handler specifies the method invoked when a user | ||
240 | * attempts to start an IO request for a controller. | ||
241 | */ | ||
242 | sci_base_controller_start_request_handler_t start_io; | ||
243 | |||
244 | /** | ||
245 | * The complete_io_handler specifies the method invoked when a user | ||
246 | * attempts to complete an IO request for a controller. | ||
247 | */ | ||
248 | sci_base_controller_request_handler_t complete_io; | ||
249 | |||
250 | /** | ||
251 | * The continue_io_handler specifies the method invoked when a user | ||
252 | * attempts to continue an IO request for a controller. | ||
253 | */ | ||
254 | sci_base_controller_request_handler_t continue_io; | ||
255 | |||
256 | /** | ||
257 | * The start_task_handler specifies the method invoked when a user | ||
258 | * attempts to start a task management request for a controller. | ||
259 | */ | ||
260 | sci_base_controller_start_request_handler_t start_task; | ||
261 | |||
262 | /** | ||
263 | * The complete_task_handler specifies the method invoked when a user | ||
264 | * attempts to complete a task management request for a controller. | ||
265 | */ | ||
266 | sci_base_controller_request_handler_t complete_task; | ||
267 | |||
268 | }; | ||
269 | |||
270 | /** | ||
271 | * sci_base_controller_construct() - Construct the base controller | ||
272 | * @this_controller: This parameter specifies the base controller to be | ||
273 | * constructed. | ||
274 | * @state_table: This parameter specifies the table of state definitions to be | ||
275 | * utilized for the controller state machine. | ||
276 | * @mde_array: This parameter specifies the array of memory descriptor entries | ||
277 | * to be managed by this list. | ||
278 | * @mde_array_length: This parameter specifies the size of the array of entries. | ||
279 | * @next_mdl: This parameter specifies a subsequent MDL object to be managed by | ||
280 | * this MDL object. | ||
281 | * @oem_parameters: This parameter specifies the original equipment | ||
282 | * manufacturer parameters to be utilized by this controller object. | ||
283 | * | ||
284 | */ | ||
285 | static inline void sci_base_controller_construct( | ||
286 | struct sci_base_controller *scic_base, | ||
287 | const struct sci_base_state *state_table, | ||
288 | struct sci_physical_memory_descriptor *mdes, | ||
289 | u32 mde_count, | ||
290 | struct sci_base_memory_descriptor_list *next_mdl) | ||
291 | { | ||
292 | scic_base->parent.private = NULL; | ||
293 | |||
294 | sci_base_state_machine_construct( | ||
295 | &scic_base->state_machine, | ||
296 | &scic_base->parent, | ||
297 | state_table, | ||
298 | SCI_BASE_CONTROLLER_STATE_INITIAL | ||
299 | ); | ||
300 | |||
301 | sci_base_mdl_construct(&scic_base->mdl, mdes, mde_count, next_mdl); | ||
302 | |||
303 | sci_base_state_machine_start(&scic_base->state_machine); | ||
304 | } | ||
305 | |||
306 | #endif /* _SCI_BASE_CONTROLLER_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c new file mode 100644 index 000000000000..86ae6a855399 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the base implementation for the memory descriptor list. | ||
58 | * This is currently comprised of MDL iterator methods. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #include "sci_environment.h" | ||
64 | #include "sci_base_memory_descriptor_list.h" | ||
65 | |||
66 | /* | ||
67 | * ****************************************************************************** | ||
68 | * * P U B L I C M E T H O D S | ||
69 | * ****************************************************************************** */ | ||
70 | |||
71 | void sci_mdl_first_entry( | ||
72 | struct sci_base_memory_descriptor_list *base_mdl) | ||
73 | { | ||
74 | base_mdl->next_index = 0; | ||
75 | |||
76 | /* | ||
77 | * If this MDL is managing another MDL, then recursively rewind that MDL | ||
78 | * object as well. */ | ||
79 | if (base_mdl->next_mdl != SCI_INVALID_HANDLE) | ||
80 | sci_mdl_first_entry(base_mdl->next_mdl); | ||
81 | } | ||
82 | |||
83 | |||
84 | void sci_mdl_next_entry( | ||
85 | struct sci_base_memory_descriptor_list *base_mdl) | ||
86 | { | ||
87 | /* | ||
88 | * If there is at least one more entry left in the array, then change | ||
89 | * the next pointer to it. */ | ||
90 | if (base_mdl->next_index < base_mdl->length) | ||
91 | base_mdl->next_index++; | ||
92 | else if (base_mdl->next_index == base_mdl->length) { | ||
93 | /* | ||
94 | * This MDL has exhausted it's set of entries. If this MDL is managing | ||
95 | * another MDL, then start iterating through that MDL. */ | ||
96 | if (base_mdl->next_mdl != SCI_INVALID_HANDLE) | ||
97 | sci_mdl_next_entry(base_mdl->next_mdl); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | |||
102 | struct sci_physical_memory_descriptor *sci_mdl_get_current_entry( | ||
103 | struct sci_base_memory_descriptor_list *base_mdl) | ||
104 | { | ||
105 | if (base_mdl->next_index < base_mdl->length) | ||
106 | return &base_mdl->mde_array[base_mdl->next_index]; | ||
107 | else if (base_mdl->next_index == base_mdl->length) { | ||
108 | /* | ||
109 | * This MDL has exhausted it's set of entries. If this MDL is managing | ||
110 | * another MDL, then return it's current entry. */ | ||
111 | if (base_mdl->next_mdl != SCI_INVALID_HANDLE) | ||
112 | return sci_mdl_get_current_entry(base_mdl->next_mdl); | ||
113 | } | ||
114 | |||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * ****************************************************************************** | ||
120 | * * P R O T E C T E D M E T H O D S | ||
121 | * ****************************************************************************** */ | ||
122 | |||
123 | void sci_base_mdl_construct( | ||
124 | struct sci_base_memory_descriptor_list *mdl, | ||
125 | struct sci_physical_memory_descriptor *mde_array, | ||
126 | u32 mde_array_length, | ||
127 | struct sci_base_memory_descriptor_list *next_mdl) | ||
128 | { | ||
129 | mdl->length = mde_array_length; | ||
130 | mdl->mde_array = mde_array; | ||
131 | mdl->next_index = 0; | ||
132 | mdl->next_mdl = next_mdl; | ||
133 | } | ||
134 | |||
135 | /* --------------------------------------------------------------------------- */ | ||
136 | |||
137 | bool sci_base_mde_is_valid( | ||
138 | struct sci_physical_memory_descriptor *mde, | ||
139 | u32 alignment, | ||
140 | u32 size, | ||
141 | u16 attributes) | ||
142 | { | ||
143 | /* Only need the lower 32 bits to ensure alignment is met. */ | ||
144 | u32 physical_address = lower_32_bits(mde->physical_address); | ||
145 | |||
146 | if ( | ||
147 | ((((unsigned long)mde->virtual_address) & (alignment - 1)) != 0) | ||
148 | || ((physical_address & (alignment - 1)) != 0) | ||
149 | || (mde->constant_memory_alignment != alignment) | ||
150 | || (mde->constant_memory_size != size) | ||
151 | || (mde->virtual_address == NULL) | ||
152 | || (mde->constant_memory_attributes != attributes) | ||
153 | ) { | ||
154 | return false; | ||
155 | } | ||
156 | |||
157 | return true; | ||
158 | } | ||
159 | |||
diff --git a/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h new file mode 100644 index 000000000000..257d6e368b4a --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_memory_descriptor_list.h | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ | ||
57 | #define _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the protected interface structures, constants and | ||
61 | * interface methods for the struct sci_base_memory_descriptor_list object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_memory_descriptor_list.h" | ||
69 | |||
70 | |||
71 | /** | ||
72 | * struct sci_base_memory_descriptor_list - This structure contains all of the | ||
73 | * fields necessary to implement a simple stack for managing the list of | ||
74 | * available controller indices. | ||
75 | * | ||
76 | * | ||
77 | */ | ||
78 | struct sci_base_memory_descriptor_list { | ||
79 | /** | ||
80 | * This field indicates the length of the memory descriptor entry array. | ||
81 | */ | ||
82 | u32 length; | ||
83 | |||
84 | /** | ||
85 | * This field is utilized to provide iterator pattern functionality. | ||
86 | * It indicates the index of the next memory descriptor in the iteration. | ||
87 | */ | ||
88 | u32 next_index; | ||
89 | |||
90 | /** | ||
91 | * This field will point to the list of memory descriptors. | ||
92 | */ | ||
93 | struct sci_physical_memory_descriptor *mde_array; | ||
94 | |||
95 | /** | ||
96 | * This field simply allows a user to chain memory descriptor lists | ||
97 | * together if desired. This field will be initialized to | ||
98 | * SCI_INVALID_HANDLE. | ||
99 | */ | ||
100 | struct sci_base_memory_descriptor_list *next_mdl; | ||
101 | |||
102 | }; | ||
103 | |||
104 | /** | ||
105 | * sci_base_mdl_construct() - This method is invoked to construct an memory | ||
106 | * descriptor list. It initializes the fields of the MDL. | ||
107 | * @mdl: This parameter specifies the memory descriptor list to be constructed. | ||
108 | * @mde_array: This parameter specifies the array of memory descriptor entries | ||
109 | * to be managed by this list. | ||
110 | * @mde_array_length: This parameter specifies the size of the array of entries. | ||
111 | * @next_mdl: This parameter specifies a subsequent MDL object to be managed by | ||
112 | * this MDL object. | ||
113 | * | ||
114 | * none. | ||
115 | */ | ||
116 | void sci_base_mdl_construct( | ||
117 | struct sci_base_memory_descriptor_list *mdl, | ||
118 | struct sci_physical_memory_descriptor *mde_array, | ||
119 | u32 mde_array_length, | ||
120 | struct sci_base_memory_descriptor_list *next_mdl); | ||
121 | |||
122 | /** | ||
123 | * sci_base_mde_construct() - | ||
124 | * | ||
125 | * This macro constructs an memory descriptor entry with the given alignment | ||
126 | * and size | ||
127 | */ | ||
128 | #define sci_base_mde_construct(mde, alignment, size, attributes) \ | ||
129 | { \ | ||
130 | (mde)->constant_memory_alignment = (alignment); \ | ||
131 | (mde)->constant_memory_size = (size); \ | ||
132 | (mde)->constant_memory_attributes = (attributes); \ | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * sci_base_mde_is_valid() - This method validates that the memory descriptor | ||
137 | * is correctly filled out by the SCI User | ||
138 | * @mde: This parameter is the mde entry to validate | ||
139 | * @alignment: This parameter specifies the expected alignment of the memory | ||
140 | * for the mde. | ||
141 | * @size: This parameter specifies the memory size expected for the mde its | ||
142 | * value should not have been changed by the SCI User. | ||
143 | * @attributes: This parameter specifies the attributes for the memory | ||
144 | * descriptor provided. | ||
145 | * | ||
146 | * bool This method returns an indication as to whether the supplied MDE is | ||
147 | * valid or not. true The MDE is valid. false The MDE is not valid. | ||
148 | */ | ||
149 | bool sci_base_mde_is_valid( | ||
150 | struct sci_physical_memory_descriptor *mde, | ||
151 | u32 alignment, | ||
152 | u32 size, | ||
153 | u16 attributes); | ||
154 | |||
155 | #endif /* _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_base_phy.h b/drivers/scsi/isci/core/sci_base_phy.h new file mode 100644 index 000000000000..6c0d9bbbc95f --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_phy.h | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_PHY_H_ | ||
57 | #define _SCI_BASE_PHY_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the structures, constants, and methods common to | ||
61 | * all phy object definitions. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_base_state_machine.h" | ||
67 | |||
68 | /** | ||
69 | * enum sci_base_phy_states - This enumeration depicts the standard states | ||
70 | * common to all phy state machine implementations. | ||
71 | * | ||
72 | * | ||
73 | */ | ||
74 | enum sci_base_phy_states { | ||
75 | /** | ||
76 | * Simply the initial state for the base domain state machine. | ||
77 | */ | ||
78 | SCI_BASE_PHY_STATE_INITIAL, | ||
79 | |||
80 | /** | ||
81 | * This state indicates that the phy has successfully been stopped. | ||
82 | * In this state no new IO operations are permitted on this phy. | ||
83 | * This state is entered from the INITIAL state. | ||
84 | * This state is entered from the STARTING state. | ||
85 | * This state is entered from the READY state. | ||
86 | * This state is entered from the RESETTING state. | ||
87 | */ | ||
88 | SCI_BASE_PHY_STATE_STOPPED, | ||
89 | |||
90 | /** | ||
91 | * This state indicates that the phy is in the process of becomming | ||
92 | * ready. In this state no new IO operations are permitted on this phy. | ||
93 | * This state is entered from the STOPPED state. | ||
94 | * This state is entered from the READY state. | ||
95 | * This state is entered from the RESETTING state. | ||
96 | */ | ||
97 | SCI_BASE_PHY_STATE_STARTING, | ||
98 | |||
99 | /** | ||
100 | * This state indicates the the phy is now ready. Thus, the user | ||
101 | * is able to perform IO operations utilizing this phy as long as it | ||
102 | * is currently part of a valid port. | ||
103 | * This state is entered from the STARTING state. | ||
104 | */ | ||
105 | SCI_BASE_PHY_STATE_READY, | ||
106 | |||
107 | /** | ||
108 | * This state indicates that the phy is in the process of being reset. | ||
109 | * In this state no new IO operations are permitted on this phy. | ||
110 | * This state is entered from the READY state. | ||
111 | */ | ||
112 | SCI_BASE_PHY_STATE_RESETTING, | ||
113 | |||
114 | /** | ||
115 | * Simply the final state for the base phy state machine. | ||
116 | */ | ||
117 | SCI_BASE_PHY_STATE_FINAL, | ||
118 | |||
119 | SCI_BASE_PHY_MAX_STATES | ||
120 | |||
121 | }; | ||
122 | |||
123 | /** | ||
124 | * struct sci_base_phy - This structure defines all of the fields common to PHY | ||
125 | * objects. | ||
126 | * | ||
127 | * | ||
128 | */ | ||
129 | struct sci_base_phy { | ||
130 | /** | ||
131 | * This field depicts the parent object (struct sci_base_object) for the phy. | ||
132 | */ | ||
133 | struct sci_base_object parent; | ||
134 | |||
135 | /** | ||
136 | * This field contains the information for the base phy state machine. | ||
137 | */ | ||
138 | struct sci_base_state_machine state_machine; | ||
139 | }; | ||
140 | |||
141 | typedef enum sci_status (*SCI_BASE_PHY_HANDLER_T)( | ||
142 | struct sci_base_phy * | ||
143 | ); | ||
144 | |||
145 | /** | ||
146 | * struct sci_base_phy_state_handler - This structure contains all of the state | ||
147 | * handler methods common to base phy state machines. Handler methods | ||
148 | * provide the ability to change the behavior for user requests or | ||
149 | * transitions depending on the state the machine is in. | ||
150 | * | ||
151 | * | ||
152 | */ | ||
153 | struct sci_base_phy_state_handler { | ||
154 | /** | ||
155 | * The start_handler specifies the method invoked when there is an | ||
156 | * attempt to start a phy. | ||
157 | */ | ||
158 | SCI_BASE_PHY_HANDLER_T start_handler; | ||
159 | |||
160 | /** | ||
161 | * The stop_handler specifies the method invoked when there is an | ||
162 | * attempt to stop a phy. | ||
163 | */ | ||
164 | SCI_BASE_PHY_HANDLER_T stop_handler; | ||
165 | |||
166 | /** | ||
167 | * The reset_handler specifies the method invoked when there is an | ||
168 | * attempt to reset a phy. | ||
169 | */ | ||
170 | SCI_BASE_PHY_HANDLER_T reset_handler; | ||
171 | |||
172 | /** | ||
173 | * The destruct_handler specifies the method invoked when attempting to | ||
174 | * destruct a phy. | ||
175 | */ | ||
176 | SCI_BASE_PHY_HANDLER_T destruct_handler; | ||
177 | |||
178 | }; | ||
179 | |||
180 | /** | ||
181 | * sci_base_phy_construct() - Construct the base phy | ||
182 | * @this_phy: This parameter specifies the base phy to be constructed. | ||
183 | * @state_table: This parameter specifies the table of state definitions to be | ||
184 | * utilized for the phy state machine. | ||
185 | * | ||
186 | */ | ||
187 | static inline void sci_base_phy_construct( | ||
188 | struct sci_base_phy *base_phy, | ||
189 | const struct sci_base_state *state_table) | ||
190 | { | ||
191 | base_phy->parent.private = NULL; | ||
192 | sci_base_state_machine_construct( | ||
193 | &base_phy->state_machine, | ||
194 | &base_phy->parent, | ||
195 | state_table, | ||
196 | SCI_BASE_PHY_STATE_INITIAL | ||
197 | ); | ||
198 | |||
199 | sci_base_state_machine_start( | ||
200 | &base_phy->state_machine | ||
201 | ); | ||
202 | } | ||
203 | |||
204 | |||
205 | #endif /* _SCI_BASE_PHY_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_base_port.h b/drivers/scsi/isci/core/sci_base_port.h new file mode 100644 index 000000000000..4e2031d195f0 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_port.h | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_PORT_H_ | ||
57 | #define _SCI_BASE_PORT_H_ | ||
58 | |||
59 | #include "sci_base_state_machine.h" | ||
60 | #include "sci_object.h" | ||
61 | |||
62 | /** | ||
63 | * enum sci_base_port_states - This enumeration depicts all the states for the | ||
64 | * common port state machine. | ||
65 | * | ||
66 | * | ||
67 | */ | ||
68 | enum sci_base_port_states { | ||
69 | /** | ||
70 | * This state indicates that the port has successfully been stopped. | ||
71 | * In this state no new IO operations are permitted. | ||
72 | * This state is entered from the STOPPING state. | ||
73 | */ | ||
74 | SCI_BASE_PORT_STATE_STOPPED, | ||
75 | |||
76 | /** | ||
77 | * This state indicates that the port is in the process of stopping. | ||
78 | * In this state no new IO operations are permitted, but existing IO | ||
79 | * operations are allowed to complete. | ||
80 | * This state is entered from the READY state. | ||
81 | */ | ||
82 | SCI_BASE_PORT_STATE_STOPPING, | ||
83 | |||
84 | /** | ||
85 | * This state indicates the port is now ready. Thus, the user is | ||
86 | * able to perform IO operations on this port. | ||
87 | * This state is entered from the STARTING state. | ||
88 | */ | ||
89 | SCI_BASE_PORT_STATE_READY, | ||
90 | |||
91 | /** | ||
92 | * This state indicates the port is in the process of performing a hard | ||
93 | * reset. Thus, the user is unable to perform IO operations on this | ||
94 | * port. | ||
95 | * This state is entered from the READY state. | ||
96 | */ | ||
97 | SCI_BASE_PORT_STATE_RESETTING, | ||
98 | |||
99 | /** | ||
100 | * This state indicates the port has failed a reset request. This state | ||
101 | * is entered when a port reset request times out. | ||
102 | * This state is entered from the RESETTING state. | ||
103 | */ | ||
104 | SCI_BASE_PORT_STATE_FAILED, | ||
105 | |||
106 | SCI_BASE_PORT_MAX_STATES | ||
107 | |||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * struct sci_base_port - The base port object abstracts the fields common to | ||
112 | * all SCI port objects. | ||
113 | * | ||
114 | * | ||
115 | */ | ||
116 | struct sci_base_port { | ||
117 | /** | ||
118 | * The field specifies that the parent object for the base controller | ||
119 | * is the base object itself. | ||
120 | */ | ||
121 | struct sci_base_object parent; | ||
122 | |||
123 | /** | ||
124 | * This field contains the information for the base port state machine. | ||
125 | */ | ||
126 | struct sci_base_state_machine state_machine; | ||
127 | }; | ||
128 | |||
129 | struct sci_base_phy; | ||
130 | |||
131 | typedef enum sci_status (*SCI_BASE_PORT_HANDLER_T)( | ||
132 | struct sci_base_port * | ||
133 | ); | ||
134 | |||
135 | typedef enum sci_status (*SCI_BASE_PORT_PHY_HANDLER_T)( | ||
136 | struct sci_base_port *, | ||
137 | struct sci_base_phy * | ||
138 | ); | ||
139 | |||
140 | typedef enum sci_status (*SCI_BASE_PORT_RESET_HANDLER_T)( | ||
141 | struct sci_base_port *, | ||
142 | u32 timeout | ||
143 | ); | ||
144 | |||
145 | /** | ||
146 | * struct sci_base_port_state_handler - This structure contains all of the | ||
147 | * state handler methods common to base port state machines. Handler | ||
148 | * methods provide the ability to change the behavior for user requests or | ||
149 | * transitions depending on the state the machine is in. | ||
150 | * | ||
151 | * | ||
152 | */ | ||
153 | struct sci_base_port_state_handler { | ||
154 | /** | ||
155 | * The start_handler specifies the method invoked when a user attempts to | ||
156 | * start a port. | ||
157 | */ | ||
158 | SCI_BASE_PORT_HANDLER_T start_handler; | ||
159 | |||
160 | /** | ||
161 | * The stop_handler specifies the method invoked when a user attempts to | ||
162 | * stop a port. | ||
163 | */ | ||
164 | SCI_BASE_PORT_HANDLER_T stop_handler; | ||
165 | |||
166 | /** | ||
167 | * The destruct_handler specifies the method invoked when attempting to | ||
168 | * destruct a port. | ||
169 | */ | ||
170 | SCI_BASE_PORT_HANDLER_T destruct_handler; | ||
171 | |||
172 | /** | ||
173 | * The reset_handler specifies the method invoked when a user attempts to | ||
174 | * hard reset a port. | ||
175 | */ | ||
176 | SCI_BASE_PORT_RESET_HANDLER_T reset_handler; | ||
177 | |||
178 | /** | ||
179 | * The add_phy_handler specifies the method invoked when a user attempts to | ||
180 | * add another phy into the port. | ||
181 | */ | ||
182 | SCI_BASE_PORT_PHY_HANDLER_T add_phy_handler; | ||
183 | |||
184 | /** | ||
185 | * The remove_phy_handler specifies the method invoked when a user | ||
186 | * attempts to remove a phy from the port. | ||
187 | */ | ||
188 | SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler; | ||
189 | |||
190 | }; | ||
191 | |||
192 | /** | ||
193 | * sci_base_port_construct() - Construct the base port object | ||
194 | * @this_port: This parameter specifies the base port to be constructed. | ||
195 | * @state_table: This parameter specifies the table of state definitions to be | ||
196 | * utilized for the domain state machine. | ||
197 | * | ||
198 | */ | ||
199 | void sci_base_port_construct( | ||
200 | struct sci_base_port *this_port, | ||
201 | const struct sci_base_state *state_table); | ||
202 | |||
203 | #endif /* _SCI_BASE_PORT_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_base_remote_device.h b/drivers/scsi/isci/core/sci_base_remote_device.h new file mode 100644 index 000000000000..fe6614b8ef5b --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_remote_device.h | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_REMOTE_DEVICE_H_ | ||
57 | #define _SCI_BASE_REMOTE_DEVICE_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the structures, constants, and methods common to | ||
61 | * all remote device object definitions. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_base_state_machine.h" | ||
67 | |||
68 | struct sci_base_request; | ||
69 | |||
70 | /** | ||
71 | * enum sci_base_remote_device_states - This enumeration depicts all the states | ||
72 | * for the common remote device state machine. | ||
73 | * | ||
74 | * | ||
75 | */ | ||
76 | enum sci_base_remote_device_states { | ||
77 | /** | ||
78 | * Simply the initial state for the base remote device state machine. | ||
79 | */ | ||
80 | SCI_BASE_REMOTE_DEVICE_STATE_INITIAL, | ||
81 | |||
82 | /** | ||
83 | * This state indicates that the remote device has successfully been | ||
84 | * stopped. In this state no new IO operations are permitted. | ||
85 | * This state is entered from the INITIAL state. | ||
86 | * This state is entered from the STOPPING state. | ||
87 | */ | ||
88 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPED, | ||
89 | |||
90 | /** | ||
91 | * This state indicates the the remote device is in the process of | ||
92 | * becoming ready (i.e. starting). In this state no new IO operations | ||
93 | * are permitted. | ||
94 | * This state is entered from the STOPPED state. | ||
95 | */ | ||
96 | SCI_BASE_REMOTE_DEVICE_STATE_STARTING, | ||
97 | |||
98 | /** | ||
99 | * This state indicates the remote device is now ready. Thus, the user | ||
100 | * is able to perform IO operations on the remote device. | ||
101 | * This state is entered from the STARTING state. | ||
102 | */ | ||
103 | SCI_BASE_REMOTE_DEVICE_STATE_READY, | ||
104 | |||
105 | /** | ||
106 | * This state indicates that the remote device is in the process of | ||
107 | * stopping. In this state no new IO operations are permitted, but | ||
108 | * existing IO operations are allowed to complete. | ||
109 | * This state is entered from the READY state. | ||
110 | * This state is entered from the FAILED state. | ||
111 | */ | ||
112 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING, | ||
113 | |||
114 | /** | ||
115 | * This state indicates that the remote device has failed. | ||
116 | * In this state no new IO operations are permitted. | ||
117 | * This state is entered from the INITIALIZING state. | ||
118 | * This state is entered from the READY state. | ||
119 | */ | ||
120 | SCI_BASE_REMOTE_DEVICE_STATE_FAILED, | ||
121 | |||
122 | /** | ||
123 | * This state indicates the device is being reset. | ||
124 | * In this state no new IO operations are permitted. | ||
125 | * This state is entered from the READY state. | ||
126 | */ | ||
127 | SCI_BASE_REMOTE_DEVICE_STATE_RESETTING, | ||
128 | |||
129 | /** | ||
130 | * Simply the final state for the base remote device state machine. | ||
131 | */ | ||
132 | SCI_BASE_REMOTE_DEVICE_STATE_FINAL, | ||
133 | |||
134 | SCI_BASE_REMOTE_DEVICE_MAX_STATES | ||
135 | |||
136 | }; | ||
137 | |||
138 | /** | ||
139 | * struct sci_base_remote_device - The base remote device object abstracts the | ||
140 | * fields common to all SCI remote device objects. | ||
141 | * | ||
142 | * | ||
143 | */ | ||
144 | struct sci_base_remote_device { | ||
145 | /** | ||
146 | * The field specifies that the parent object for the base remote | ||
147 | * device is the base object itself. | ||
148 | */ | ||
149 | struct sci_base_object parent; | ||
150 | |||
151 | /** | ||
152 | * This field contains the information for the base remote device state | ||
153 | * machine. | ||
154 | */ | ||
155 | struct sci_base_state_machine state_machine; | ||
156 | }; | ||
157 | |||
158 | |||
159 | typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HANDLER_T)( | ||
160 | struct sci_base_remote_device * | ||
161 | ); | ||
162 | |||
163 | typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T)( | ||
164 | struct sci_base_remote_device *, | ||
165 | struct sci_base_request * | ||
166 | ); | ||
167 | |||
168 | typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T)( | ||
169 | struct sci_base_remote_device *, | ||
170 | struct sci_base_request *, | ||
171 | void *, | ||
172 | enum sci_io_status | ||
173 | ); | ||
174 | |||
175 | /** | ||
176 | * struct sci_base_remote_device_state_handler - This structure contains all of | ||
177 | * the state handler methods common to base remote device state machines. | ||
178 | * Handler methods provide the ability to change the behavior for user | ||
179 | * requests or transitions depending on the state the machine is in. | ||
180 | * | ||
181 | * | ||
182 | */ | ||
183 | struct sci_base_remote_device_state_handler { | ||
184 | /** | ||
185 | * The start_handler specifies the method invoked when a user attempts to | ||
186 | * start a remote device. | ||
187 | */ | ||
188 | SCI_BASE_REMOTE_DEVICE_HANDLER_T start_handler; | ||
189 | |||
190 | /** | ||
191 | * The stop_handler specifies the method invoked when a user attempts to | ||
192 | * stop a remote device. | ||
193 | */ | ||
194 | SCI_BASE_REMOTE_DEVICE_HANDLER_T stop_handler; | ||
195 | |||
196 | /** | ||
197 | * The fail_handler specifies the method invoked when a remote device | ||
198 | * failure has occurred. A failure may be due to an inability to | ||
199 | * initialize/configure the device. | ||
200 | */ | ||
201 | SCI_BASE_REMOTE_DEVICE_HANDLER_T fail_handler; | ||
202 | |||
203 | /** | ||
204 | * The destruct_handler specifies the method invoked when attempting to | ||
205 | * destruct a remote device. | ||
206 | */ | ||
207 | SCI_BASE_REMOTE_DEVICE_HANDLER_T destruct_handler; | ||
208 | |||
209 | /** | ||
210 | * The reset handler specifies the method invloked when requesting to reset a | ||
211 | * remote device. | ||
212 | */ | ||
213 | SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_handler; | ||
214 | |||
215 | /** | ||
216 | * The reset complete handler specifies the method invloked when reporting | ||
217 | * that a reset has completed to the remote device. | ||
218 | */ | ||
219 | SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_complete_handler; | ||
220 | |||
221 | /** | ||
222 | * The start_io_handler specifies the method invoked when a user | ||
223 | * attempts to start an IO request for a remote device. | ||
224 | */ | ||
225 | SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_io_handler; | ||
226 | |||
227 | /** | ||
228 | * The complete_io_handler specifies the method invoked when a user | ||
229 | * attempts to complete an IO request for a remote device. | ||
230 | */ | ||
231 | SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_io_handler; | ||
232 | |||
233 | /** | ||
234 | * The continue_io_handler specifies the method invoked when a user | ||
235 | * attempts to continue an IO request for a remote device. | ||
236 | */ | ||
237 | SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T continue_io_handler; | ||
238 | |||
239 | /** | ||
240 | * The start_task_handler specifies the method invoked when a user | ||
241 | * attempts to start a task management request for a remote device. | ||
242 | */ | ||
243 | SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_task_handler; | ||
244 | |||
245 | /** | ||
246 | * The complete_task_handler specifies the method invoked when a user | ||
247 | * attempts to complete a task management request for a remote device. | ||
248 | */ | ||
249 | SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_task_handler; | ||
250 | |||
251 | }; | ||
252 | |||
253 | /** | ||
254 | * sci_base_remote_device_construct() - Construct the base remote device | ||
255 | * @this_remote_device: This parameter specifies the base remote device to be | ||
256 | * constructed. | ||
257 | * @state_table: This parameter specifies the table of state definitions to be | ||
258 | * utilized for the remote device state machine. | ||
259 | * | ||
260 | */ | ||
261 | static inline void sci_base_remote_device_construct( | ||
262 | struct sci_base_remote_device *base_dev, | ||
263 | const struct sci_base_state *state_table) | ||
264 | { | ||
265 | base_dev->parent.private = NULL; | ||
266 | sci_base_state_machine_construct( | ||
267 | &base_dev->state_machine, | ||
268 | &base_dev->parent, | ||
269 | state_table, | ||
270 | SCI_BASE_REMOTE_DEVICE_STATE_INITIAL | ||
271 | ); | ||
272 | |||
273 | sci_base_state_machine_start( | ||
274 | &base_dev->state_machine | ||
275 | ); | ||
276 | } | ||
277 | #endif /* _SCI_BASE_REMOTE_DEVICE_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_base_request.h b/drivers/scsi/isci/core/sci_base_request.h new file mode 100644 index 000000000000..d1b2195b228a --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_request.h | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_REQUST_H_ | ||
57 | #define _SCI_BASE_REQUST_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the constants, types, and method declarations for | ||
61 | * the SCI base IO and task request objects. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_base_state_machine.h" | ||
67 | |||
68 | /** | ||
69 | * enum sci_base_request_states - This enumeration depicts all the states for | ||
70 | * the common request state machine. | ||
71 | * | ||
72 | * | ||
73 | */ | ||
74 | enum sci_base_request_states { | ||
75 | /** | ||
76 | * Simply the initial state for the base request state machine. | ||
77 | */ | ||
78 | SCI_BASE_REQUEST_STATE_INITIAL, | ||
79 | |||
80 | /** | ||
81 | * This state indicates that the request has been constructed. This state | ||
82 | * is entered from the INITIAL state. | ||
83 | */ | ||
84 | SCI_BASE_REQUEST_STATE_CONSTRUCTED, | ||
85 | |||
86 | /** | ||
87 | * This state indicates that the request has been started. This state is | ||
88 | * entered from the CONSTRUCTED state. | ||
89 | */ | ||
90 | SCI_BASE_REQUEST_STATE_STARTED, | ||
91 | |||
92 | /** | ||
93 | * This state indicates that the request has completed. | ||
94 | * This state is entered from the STARTED state. This state is entered from | ||
95 | * the ABORTING state. | ||
96 | */ | ||
97 | SCI_BASE_REQUEST_STATE_COMPLETED, | ||
98 | |||
99 | /** | ||
100 | * This state indicates that the request is in the process of being | ||
101 | * terminated/aborted. | ||
102 | * This state is entered from the CONSTRUCTED state. | ||
103 | * This state is entered from the STARTED state. | ||
104 | */ | ||
105 | SCI_BASE_REQUEST_STATE_ABORTING, | ||
106 | |||
107 | /** | ||
108 | * Simply the final state for the base request state machine. | ||
109 | */ | ||
110 | SCI_BASE_REQUEST_STATE_FINAL, | ||
111 | }; | ||
112 | |||
113 | /** | ||
114 | * struct sci_base_request - The base request object abstracts the fields | ||
115 | * common to all SCI IO and task request objects. | ||
116 | * | ||
117 | * | ||
118 | */ | ||
119 | struct sci_base_request { | ||
120 | /** | ||
121 | * The field specifies that the parent object for the base request is the | ||
122 | * base object itself. | ||
123 | */ | ||
124 | struct sci_base_object parent; | ||
125 | |||
126 | /** | ||
127 | * This field contains the information for the base request state machine. | ||
128 | */ | ||
129 | struct sci_base_state_machine state_machine; | ||
130 | }; | ||
131 | |||
132 | typedef enum sci_status (*SCI_BASE_REQUEST_HANDLER_T)( | ||
133 | struct sci_base_request *this_request | ||
134 | ); | ||
135 | |||
136 | /** | ||
137 | * struct sci_base_request_state_handler - This structure contains all of the | ||
138 | * state handler methods common to base IO and task request state machines. | ||
139 | * Handler methods provide the ability to change the behavior for user | ||
140 | * requests or transitions depending on the state the machine is in. | ||
141 | * | ||
142 | * | ||
143 | */ | ||
144 | struct sci_base_request_state_handler { | ||
145 | /** | ||
146 | * The start_handler specifies the method invoked when a user attempts to | ||
147 | * start a request. | ||
148 | */ | ||
149 | SCI_BASE_REQUEST_HANDLER_T start_handler; | ||
150 | |||
151 | /** | ||
152 | * The abort_handler specifies the method invoked when a user attempts to | ||
153 | * abort a request. | ||
154 | */ | ||
155 | SCI_BASE_REQUEST_HANDLER_T abort_handler; | ||
156 | |||
157 | /** | ||
158 | * The complete_handler specifies the method invoked when a user attempts to | ||
159 | * complete a request. | ||
160 | */ | ||
161 | SCI_BASE_REQUEST_HANDLER_T complete_handler; | ||
162 | |||
163 | /** | ||
164 | * The destruct_handler specifies the method invoked when a user attempts to | ||
165 | * destruct a request. | ||
166 | */ | ||
167 | SCI_BASE_REQUEST_HANDLER_T destruct_handler; | ||
168 | |||
169 | }; | ||
170 | |||
171 | /** | ||
172 | * sci_base_request_construct() - Construct the base request. | ||
173 | * @this_request: This parameter specifies the base request to be constructed. | ||
174 | * @state_table: This parameter specifies the table of state definitions to be | ||
175 | * utilized for the request state machine. | ||
176 | * | ||
177 | */ | ||
178 | static inline void sci_base_request_construct( | ||
179 | struct sci_base_request *base_req, | ||
180 | const struct sci_base_state *my_state_table) | ||
181 | { | ||
182 | base_req->parent.private = NULL; | ||
183 | sci_base_state_machine_construct( | ||
184 | &base_req->state_machine, | ||
185 | &base_req->parent, | ||
186 | my_state_table, | ||
187 | SCI_BASE_REQUEST_STATE_INITIAL | ||
188 | ); | ||
189 | |||
190 | sci_base_state_machine_start( | ||
191 | &base_req->state_machine | ||
192 | ); | ||
193 | } | ||
194 | |||
195 | #endif /* _SCI_BASE_REQUST_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_base_state.h b/drivers/scsi/isci/core/sci_base_state.h new file mode 100644 index 000000000000..d6b9c1a951b1 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_state.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_STATE_H_ | ||
57 | #define _SCI_BASE_STATE_H_ | ||
58 | |||
59 | #include "sci_object.h" | ||
60 | |||
61 | typedef void (*SCI_BASE_STATE_HANDLER_T)( | ||
62 | void | ||
63 | ); | ||
64 | |||
65 | typedef void (*SCI_STATE_TRANSITION_T)( | ||
66 | struct sci_base_object *base_object | ||
67 | ); | ||
68 | |||
69 | /** | ||
70 | * struct sci_base_state - The base state object abstracts the fields common to | ||
71 | * all state objects defined in SCI. | ||
72 | * | ||
73 | * | ||
74 | */ | ||
75 | struct sci_base_state { | ||
76 | /** | ||
77 | * This field is a function pointer that defines the method to be | ||
78 | * invoked when the state is entered. | ||
79 | */ | ||
80 | SCI_STATE_TRANSITION_T enter_state; | ||
81 | |||
82 | /** | ||
83 | * This field is a function pointer that defines the method to be | ||
84 | * invoked when the state is exited. | ||
85 | */ | ||
86 | SCI_STATE_TRANSITION_T exit_state; | ||
87 | |||
88 | }; | ||
89 | |||
90 | #endif /* _SCI_BASE_STATE_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_base_state_machine.c b/drivers/scsi/isci/core/sci_base_state_machine.c new file mode 100644 index 000000000000..5b1e8da55fe6 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_state_machine.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains all of the functionality common to all state machine | ||
58 | * object implementations. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #include "sci_base_state_machine.h" | ||
64 | |||
65 | static void sci_state_machine_exit_state(struct sci_base_state_machine *sm) | ||
66 | { | ||
67 | u32 state = sm->current_state_id; | ||
68 | SCI_STATE_TRANSITION_T exit = sm->state_table[state].exit_state; | ||
69 | |||
70 | if (exit) | ||
71 | exit(sm->state_machine_owner); | ||
72 | } | ||
73 | |||
74 | static void sci_state_machine_enter_state(struct sci_base_state_machine *sm) | ||
75 | { | ||
76 | u32 state = sm->current_state_id; | ||
77 | SCI_STATE_TRANSITION_T enter = sm->state_table[state].enter_state; | ||
78 | |||
79 | if (enter) | ||
80 | enter(sm->state_machine_owner); | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * ****************************************************************************** | ||
85 | * * P R O T E C T E D M E T H O D S | ||
86 | * ****************************************************************************** */ | ||
87 | |||
88 | /** | ||
89 | * This method will set the initial state and state table for the state | ||
90 | * machine. The caller should follow this request with the initialize | ||
91 | * request to cause the state machine to start. | ||
92 | * @sm: This parameter provides the state machine object to be | ||
93 | * constructed. | ||
94 | * @state_machine_owner: This parameter indicates the object that is owns the | ||
95 | * state machine being constructed. | ||
96 | * @state_table: This parameter specifies the table of state objects that is | ||
97 | * managed by this state machine. | ||
98 | * @initial_state: This parameter specifies the value of the initial state for | ||
99 | * this state machine. | ||
100 | * | ||
101 | */ | ||
102 | void sci_base_state_machine_construct(struct sci_base_state_machine *sm, | ||
103 | struct sci_base_object *owner, | ||
104 | const struct sci_base_state *state_table, | ||
105 | u32 initial_state) | ||
106 | { | ||
107 | sm->state_machine_owner = owner; | ||
108 | sm->initial_state_id = initial_state; | ||
109 | sm->previous_state_id = initial_state; | ||
110 | sm->current_state_id = initial_state; | ||
111 | sm->state_table = state_table; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * This method will cause the state machine to enter the initial state. | ||
116 | * @sm: This parameter specifies the state machine that is to | ||
117 | * be started. | ||
118 | * | ||
119 | * sci_base_state_machine_construct() for how to set the initial state none | ||
120 | */ | ||
121 | void sci_base_state_machine_start(struct sci_base_state_machine *sm) | ||
122 | { | ||
123 | sm->current_state_id = sm->initial_state_id; | ||
124 | #if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) | ||
125 | sci_base_subject_notify(&sm->parent); | ||
126 | #endif | ||
127 | sci_state_machine_enter_state(sm); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * This method will cause the state machine to exit it's current state only. | ||
132 | * @sm: This parameter specifies the state machine that is to | ||
133 | * be stopped. | ||
134 | * | ||
135 | */ | ||
136 | void sci_base_state_machine_stop( | ||
137 | struct sci_base_state_machine *sm) | ||
138 | { | ||
139 | sci_state_machine_exit_state(sm); | ||
140 | #if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) | ||
141 | sci_base_subject_notify(&sm->parent); | ||
142 | #endif | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * This method performs an update to the current state of the state machine. | ||
147 | * @sm: This parameter specifies the state machine for which | ||
148 | * the caller wishes to perform a state change. | ||
149 | * @next_state: This parameter specifies the new state for the state machine. | ||
150 | * | ||
151 | */ | ||
152 | void sci_base_state_machine_change_state( | ||
153 | struct sci_base_state_machine *sm, | ||
154 | u32 next_state) | ||
155 | { | ||
156 | sci_state_machine_exit_state(sm); | ||
157 | |||
158 | sm->previous_state_id = sm->current_state_id; | ||
159 | sm->current_state_id = next_state; | ||
160 | |||
161 | #if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION) | ||
162 | /* Notify of the state change prior to entering the state. */ | ||
163 | sci_base_subject_notify(&sm->parent); | ||
164 | #endif | ||
165 | |||
166 | sci_state_machine_enter_state(sm); | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * This method simply returns the current state of the state machine to the | ||
171 | * caller. | ||
172 | * @sm: This parameter specifies the state machine for which to | ||
173 | * retrieve the current state. | ||
174 | * | ||
175 | * This method returns a u32 value indicating the current state for the | ||
176 | * supplied state machine. | ||
177 | */ | ||
178 | u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm) | ||
179 | { | ||
180 | return sm->current_state_id; | ||
181 | } | ||
182 | |||
diff --git a/drivers/scsi/isci/core/sci_base_state_machine.h b/drivers/scsi/isci/core/sci_base_state_machine.h new file mode 100644 index 000000000000..cee38bd3d127 --- /dev/null +++ b/drivers/scsi/isci/core/sci_base_state_machine.h | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_BASE_STATE_MACHINE_H_ | ||
57 | #define _SCI_BASE_STATE_MACHINE_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all structures, constants, or method declarations common | ||
61 | * to all state machines defined in SCI. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_base_state.h" | ||
68 | |||
69 | |||
70 | /** | ||
71 | * SET_STATE_HANDLER() - | ||
72 | * | ||
73 | * This macro simply provides simplified retrieval of an objects state handler. | ||
74 | */ | ||
75 | #define SET_STATE_HANDLER(object, table, state) \ | ||
76 | (object)->state_handlers = &(table)[(state)] | ||
77 | |||
78 | /** | ||
79 | * struct sci_base_state_machine - This structure defines the fields common to | ||
80 | * all state machines. | ||
81 | * | ||
82 | * | ||
83 | */ | ||
84 | struct sci_base_state_machine { | ||
85 | /** | ||
86 | * This field points to the start of the state machine's state table. | ||
87 | */ | ||
88 | const struct sci_base_state *state_table; | ||
89 | |||
90 | /** | ||
91 | * This field points to the object to which this state machine is | ||
92 | * associated. It serves as a cookie to be provided to the state | ||
93 | * enter/exit methods. | ||
94 | */ | ||
95 | struct sci_base_object *state_machine_owner; | ||
96 | |||
97 | /** | ||
98 | * This field simply indicates the state value for the state machine's | ||
99 | * initial state. | ||
100 | */ | ||
101 | u32 initial_state_id; | ||
102 | |||
103 | /** | ||
104 | * This field indicates the current state of the state machine. | ||
105 | */ | ||
106 | u32 current_state_id; | ||
107 | |||
108 | /** | ||
109 | * This field indicates the previous state of the state machine. | ||
110 | */ | ||
111 | u32 previous_state_id; | ||
112 | |||
113 | }; | ||
114 | |||
115 | /* | ||
116 | * ****************************************************************************** | ||
117 | * * P R O T E C T E D M E T H O D S | ||
118 | * ****************************************************************************** */ | ||
119 | |||
120 | void sci_base_state_machine_construct( | ||
121 | struct sci_base_state_machine *this_state_machine, | ||
122 | struct sci_base_object *state_machine_owner, | ||
123 | const struct sci_base_state *state_table, | ||
124 | u32 initial_state); | ||
125 | |||
126 | void sci_base_state_machine_start( | ||
127 | struct sci_base_state_machine *this_state_machine); | ||
128 | |||
129 | void sci_base_state_machine_stop( | ||
130 | struct sci_base_state_machine *this_state_machine); | ||
131 | |||
132 | void sci_base_state_machine_change_state( | ||
133 | struct sci_base_state_machine *this_state_machine, | ||
134 | u32 next_state); | ||
135 | |||
136 | u32 sci_base_state_machine_get_state( | ||
137 | struct sci_base_state_machine *this_state_machine); | ||
138 | |||
139 | #endif /* _SCI_BASE_STATE_MACHINE_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_controller.h b/drivers/scsi/isci/core/sci_controller.h new file mode 100644 index 000000000000..26c3548cbf7a --- /dev/null +++ b/drivers/scsi/isci/core/sci_controller.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_CONTROLLER_H_ | ||
57 | #define _SCI_CONTROLLER_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the interface methods that can be called by an SCI | ||
61 | * user on all SCI controller objects. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | |||
69 | struct sci_base_memory_descriptor_list; | ||
70 | struct scic_sds_controller; | ||
71 | |||
72 | #define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF | ||
73 | |||
74 | /** | ||
75 | * sci_controller_get_memory_descriptor_list_handle() - This method simply | ||
76 | * returns a handle for the memory descriptor list associated with the | ||
77 | * supplied controller. The descriptor list provides DMA safe/capable | ||
78 | * memory requirements for this controller. | ||
79 | * @controller: This parameter specifies the controller for which to retrieve | ||
80 | * the DMA safe memory descriptor list. | ||
81 | * | ||
82 | * The user must adhere to the alignment requirements specified in memory | ||
83 | * descriptor. In situations where the operating environment does not offer | ||
84 | * memory allocation utilities supporting alignment, then it is the | ||
85 | * responsibility of the user to manually align the memory buffer for SCI. | ||
86 | * Thus, the user may have to allocate a larger buffer to meet the alignment. | ||
87 | * Additionally, the user will need to remember the actual memory allocation | ||
88 | * addresses in order to ensure the memory can be properly freed when necessary | ||
89 | * to do so. This method will return a valid handle, but the MDL may not be | ||
90 | * accurate until after the user has invoked the associated | ||
91 | * sci_controller_initialize() routine. A pointer to a physical memory | ||
92 | * descriptor array. | ||
93 | */ | ||
94 | struct sci_base_memory_descriptor_list * | ||
95 | sci_controller_get_memory_descriptor_list_handle( | ||
96 | struct scic_sds_controller *controller); | ||
97 | |||
98 | |||
99 | #endif /* _SCI_CONTROLLER_H_ */ | ||
100 | |||
diff --git a/drivers/scsi/isci/core/sci_controller_constants.h b/drivers/scsi/isci/core/sci_controller_constants.h new file mode 100644 index 000000000000..06c34c7bdd5f --- /dev/null +++ b/drivers/scsi/isci/core/sci_controller_constants.h | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_CONTROLLER_CONSTANTS_H_ | ||
57 | #define _SCI_CONTROLLER_CONSTANTS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains constant values that change based on the type of core or | ||
61 | * framework being managed. These constants are exported in order to | ||
62 | * provide the user with information as to the bounds (i.e. how many) of | ||
63 | * specific objects. | ||
64 | * | ||
65 | * | ||
66 | */ | ||
67 | |||
68 | |||
69 | #ifdef SCIC_SDS_4_ENABLED | ||
70 | |||
71 | #ifndef SCI_MAX_PHYS | ||
72 | /** | ||
73 | * | ||
74 | * | ||
75 | * This constant defines the maximum number of phy objects that can be | ||
76 | * supported for the SCU Driver Standard (SDS) library. This is tied directly | ||
77 | * to silicon capabilities. | ||
78 | */ | ||
79 | #define SCI_MAX_PHYS (4) | ||
80 | #endif | ||
81 | |||
82 | #ifndef SCI_MAX_PORTS | ||
83 | /** | ||
84 | * | ||
85 | * | ||
86 | * This constant defines the maximum number of port objects that can be | ||
87 | * supported for the SCU Driver Standard (SDS) library. This is tied directly | ||
88 | * to silicon capabilities. | ||
89 | */ | ||
90 | #define SCI_MAX_PORTS SCI_MAX_PHYS | ||
91 | #endif | ||
92 | |||
93 | #ifndef SCI_MIN_SMP_PHYS | ||
94 | /** | ||
95 | * | ||
96 | * | ||
97 | * This constant defines the minimum number of SMP phy objects that can be | ||
98 | * supported for a single expander level. This was determined by using 36 | ||
99 | * physical phys and room for 2 virtual phys. | ||
100 | */ | ||
101 | #define SCI_MIN_SMP_PHYS (38) | ||
102 | #endif | ||
103 | |||
104 | #ifndef SCI_MAX_SMP_PHYS | ||
105 | /** | ||
106 | * | ||
107 | * | ||
108 | * This constant defines the maximum number of SMP phy objects that can be | ||
109 | * supported for the SCU Driver Standard (SDS) library. This number can be | ||
110 | * increased if required. | ||
111 | */ | ||
112 | #define SCI_MAX_SMP_PHYS (384) | ||
113 | #endif | ||
114 | |||
115 | #ifndef SCI_MAX_REMOTE_DEVICES | ||
116 | /** | ||
117 | * | ||
118 | * | ||
119 | * This constant defines the maximum number of remote device objects that can | ||
120 | * be supported for the SCU Driver Standard (SDS) library. This is tied | ||
121 | * directly to silicon capabilities. | ||
122 | */ | ||
123 | #define SCI_MAX_REMOTE_DEVICES (256) | ||
124 | #endif | ||
125 | |||
126 | #ifndef SCI_MIN_REMOTE_DEVICES | ||
127 | /** | ||
128 | * | ||
129 | * | ||
130 | * This constant defines the minimum number of remote device objects that can | ||
131 | * be supported for the SCU Driver Standard (SDS) library. This # can be | ||
132 | * configured for minimum memory environments to any value less than | ||
133 | * SCI_MAX_REMOTE_DEVICES | ||
134 | */ | ||
135 | #define SCI_MIN_REMOTE_DEVICES (16) | ||
136 | #endif | ||
137 | |||
138 | #ifndef SCI_MAX_IO_REQUESTS | ||
139 | /** | ||
140 | * | ||
141 | * | ||
142 | * This constant defines the maximum number of IO request objects that can be | ||
143 | * supported for the SCU Driver Standard (SDS) library. This is tied directly | ||
144 | * to silicon capabilities. | ||
145 | */ | ||
146 | #define SCI_MAX_IO_REQUESTS (256) | ||
147 | #endif | ||
148 | |||
149 | #ifndef SCI_MIN_IO_REQUESTS | ||
150 | /** | ||
151 | * | ||
152 | * | ||
153 | * This constant defines the minimum number of IO request objects that can be | ||
154 | * supported for the SCU Driver Standard (SDS) library. This # can be | ||
155 | * configured for minimum memory environments to any value less than | ||
156 | * SCI_MAX_IO_REQUESTS. | ||
157 | */ | ||
158 | #define SCI_MIN_IO_REQUESTS (1) | ||
159 | #endif | ||
160 | |||
161 | #ifndef SCI_MAX_MSIX_MESSAGES | ||
162 | /** | ||
163 | * | ||
164 | * | ||
165 | * This constant defines the maximum number of MSI-X interrupt vectors/messages | ||
166 | * supported for an SCU hardware controller instance. | ||
167 | */ | ||
168 | #define SCI_MAX_MSIX_MESSAGES (2) | ||
169 | #endif | ||
170 | |||
171 | #ifndef SCI_MAX_SCATTER_GATHER_ELEMENTS | ||
172 | /** | ||
173 | * | ||
174 | * | ||
175 | * This constant defines the maximum number of Scatter-Gather Elements to be | ||
176 | * used by any SCI component. | ||
177 | */ | ||
178 | #define SCI_MAX_SCATTER_GATHER_ELEMENTS 130 | ||
179 | #endif | ||
180 | |||
181 | #ifndef SCI_MIN_SCATTER_GATHER_ELEMENTS | ||
182 | /** | ||
183 | * | ||
184 | * | ||
185 | * This constant defines the minimum number of Scatter-Gather Elements to be | ||
186 | * used by any SCI component. | ||
187 | */ | ||
188 | #define SCI_MIN_SCATTER_GATHER_ELEMENTS 1 | ||
189 | #endif | ||
190 | |||
191 | #else /* SCIC_SDS_4_ENABLED */ | ||
192 | |||
193 | #error "SCI Core configuration left unspecified (e.g. SCIC_SDS_4_ENABLED)" | ||
194 | |||
195 | #endif /* SCIC_SDS_4_ENABLED */ | ||
196 | |||
197 | /** | ||
198 | * | ||
199 | * | ||
200 | * This constant defines the maximum number of controllers that can occur in a | ||
201 | * single silicon package. | ||
202 | */ | ||
203 | #define SCI_MAX_CONTROLLERS 2 | ||
204 | |||
205 | /** | ||
206 | * | ||
207 | * | ||
208 | * The maximum number of supported domain objects is currently tied to the | ||
209 | * maximum number of support port objects. | ||
210 | */ | ||
211 | #define SCI_MAX_DOMAINS SCI_MAX_PORTS | ||
212 | |||
213 | |||
214 | #endif /* _SCI_CONTROLLER_CONSTANTS_H_ */ | ||
215 | |||
diff --git a/drivers/scsi/isci/core/sci_memory_descriptor_list.h b/drivers/scsi/isci/core/sci_memory_descriptor_list.h new file mode 100644 index 000000000000..44de1c18d2c8 --- /dev/null +++ b/drivers/scsi/isci/core/sci_memory_descriptor_list.h | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_MEMORY_DESCRIPTOR_LIST_H_ | ||
57 | #define _SCI_MEMORY_DESCRIPTOR_LIST_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the basic data types utilized by an SCI user or | ||
61 | * implementor. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | |||
69 | struct sci_base_memory_descriptor_list; | ||
70 | |||
71 | /** | ||
72 | * | ||
73 | * | ||
74 | * SCI_MDE_ATTRIBUTES These constants depict memory attributes for the Memory | ||
75 | * Descriptor Entries (MDEs) contained in the MDL. | ||
76 | */ | ||
77 | #define SCI_MDE_ATTRIBUTE_CACHEABLE 0x0001 | ||
78 | #define SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS 0x0002 | ||
79 | |||
80 | /** | ||
81 | * struct sci_physical_memory_descriptor - This structure defines a description | ||
82 | * of a memory location for the SCI implementation. | ||
83 | * | ||
84 | * | ||
85 | */ | ||
86 | struct sci_physical_memory_descriptor { | ||
87 | /** | ||
88 | * This field contains the virtual address associated with this descriptor | ||
89 | * element. This field shall be zero when the descriptor is retrieved from | ||
90 | * the SCI implementation. The user shall set this field prior | ||
91 | * sci_controller_start() | ||
92 | */ | ||
93 | void *virtual_address; | ||
94 | |||
95 | /** | ||
96 | * This field contains the physical address associated with this desciptor | ||
97 | * element. This field shall be zero when the descriptor is retrieved from | ||
98 | * the SCI implementation. The user shall set this field prior | ||
99 | * sci_controller_start() | ||
100 | */ | ||
101 | dma_addr_t physical_address; | ||
102 | |||
103 | /** | ||
104 | * This field contains the size requirement for this memory descriptor. | ||
105 | * A value of zero for this field indicates the end of the descriptor | ||
106 | * list. The value should be treated as read only for an SCI user. | ||
107 | */ | ||
108 | u32 constant_memory_size; | ||
109 | |||
110 | /** | ||
111 | * This field contains the alignment requirement for this memory | ||
112 | * descriptor. A value of zero for this field indicates the end of the | ||
113 | * descriptor list. All other values indicate the number of bytes to | ||
114 | * achieve the necessary alignment. The value should be treated as | ||
115 | * read only for an SCI user. | ||
116 | */ | ||
117 | u32 constant_memory_alignment; | ||
118 | |||
119 | /** | ||
120 | * This field contains an indication regarding the desired memory | ||
121 | * attributes for this memory descriptor entry. | ||
122 | * Notes: | ||
123 | * - If the cacheable attribute is set, the user can allocate | ||
124 | * memory that is backed by cache for better performance. It | ||
125 | * is not required that the memory be backed by cache. | ||
126 | * - If the physically contiguous attribute is set, then the | ||
127 | * entire memory must be physically contiguous across all | ||
128 | * page boundaries. | ||
129 | */ | ||
130 | u16 constant_memory_attributes; | ||
131 | |||
132 | }; | ||
133 | |||
134 | /** | ||
135 | * sci_mdl_first_entry() - This method simply rewinds the MDL iterator back to | ||
136 | * the first memory descriptor entry in the list. | ||
137 | * @mdl: This parameter specifies the memory descriptor list that is to be | ||
138 | * rewound. | ||
139 | * | ||
140 | */ | ||
141 | void sci_mdl_first_entry( | ||
142 | struct sci_base_memory_descriptor_list *mdl); | ||
143 | |||
144 | /** | ||
145 | * sci_mdl_next_entry() - This method simply updates the "current" pointer to | ||
146 | * the next sequential memory descriptor. | ||
147 | * @mdl: This parameter specifies the memory descriptor list for which to | ||
148 | * return the next memory descriptor entry in the list. | ||
149 | * | ||
150 | * none. | ||
151 | */ | ||
152 | void sci_mdl_next_entry( | ||
153 | struct sci_base_memory_descriptor_list *mdl); | ||
154 | |||
155 | /** | ||
156 | * sci_mdl_get_current_entry() - This method simply returns the current memory | ||
157 | * descriptor entry. | ||
158 | * @mdl: This parameter specifies the memory descriptor list for which to | ||
159 | * return the current memory descriptor entry. | ||
160 | * | ||
161 | * This method returns a pointer to the current physical memory descriptor in | ||
162 | * the MDL. NULL This value is returned if there are no descriptors in the list. | ||
163 | */ | ||
164 | struct sci_physical_memory_descriptor *sci_mdl_get_current_entry( | ||
165 | struct sci_base_memory_descriptor_list *mdl); | ||
166 | |||
167 | |||
168 | #endif /* _SCI_MEMORY_DESCRIPTOR_LIST_H_ */ | ||
169 | |||
diff --git a/drivers/scsi/isci/core/sci_object.h b/drivers/scsi/isci/core/sci_object.h new file mode 100644 index 000000000000..930694264f1a --- /dev/null +++ b/drivers/scsi/isci/core/sci_object.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_OBJECT_H_ | ||
57 | #define _SCI_OBJECT_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the method and constants associated with the SCI | ||
61 | * base object. The SCI base object is the class from which all other | ||
62 | * objects derive in the Storage Controller Interface. | ||
63 | * | ||
64 | * | ||
65 | */ | ||
66 | |||
67 | |||
68 | #include "sci_types.h" | ||
69 | #include "sci_status.h" | ||
70 | |||
71 | /** | ||
72 | * struct sci_base_object - all core objects must include this as their | ||
73 | * first member to permit the casting below | ||
74 | * | ||
75 | * TODO: unwind this assumption, convert these routines and callers to pass a struct | ||
76 | * sci_base_object pointer without casting, or convert 'private' to the | ||
77 | * expected type per-object | ||
78 | * | ||
79 | */ | ||
80 | struct sci_base_object { | ||
81 | void *private; | ||
82 | }; | ||
83 | |||
84 | static inline void *sci_object_get_association(void *obj) | ||
85 | { | ||
86 | struct sci_base_object *base = obj; | ||
87 | |||
88 | return base->private; | ||
89 | } | ||
90 | |||
91 | static inline void sci_object_set_association(void *obj, void *private) | ||
92 | { | ||
93 | struct sci_base_object *base = obj; | ||
94 | |||
95 | base->private = private; | ||
96 | } | ||
97 | |||
98 | #endif /* _SCI_OBJECT_H_ */ | ||
99 | |||
diff --git a/drivers/scsi/isci/core/sci_pool.h b/drivers/scsi/isci/core/sci_pool.h new file mode 100644 index 000000000000..c0d2ea32529b --- /dev/null +++ b/drivers/scsi/isci/core/sci_pool.h | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the interface to the pool class. This class allows two | ||
58 | * different two different priority tasks to insert and remove items from | ||
59 | * the free pool. The user of the pool is expected to evaluate the pool | ||
60 | * condition empty before a get operation and pool condition full before a | ||
61 | * put operation. Methods Provided: - sci_pool_create() - | ||
62 | * sci_pool_initialize() - sci_pool_empty() - sci_pool_full() - | ||
63 | * sci_pool_get() - sci_pool_put() | ||
64 | * | ||
65 | * | ||
66 | */ | ||
67 | |||
68 | #ifndef _SCI_POOL_H_ | ||
69 | #define _SCI_POOL_H_ | ||
70 | |||
71 | /** | ||
72 | * SCI_POOL_INCREMENT() - | ||
73 | * | ||
74 | * Private operation for the pool | ||
75 | */ | ||
76 | #define SCI_POOL_INCREMENT(this_pool, index) \ | ||
77 | (((index) + 1) == (this_pool).size ? 0 : (index) + 1) | ||
78 | |||
79 | /** | ||
80 | * SCI_POOL_CREATE() - | ||
81 | * | ||
82 | * This creates a pool structure of pool_name. The members in the pool are of | ||
83 | * type with number of elements equal to size. | ||
84 | */ | ||
85 | #define SCI_POOL_CREATE(pool_name, type, pool_size) \ | ||
86 | struct \ | ||
87 | { \ | ||
88 | u32 size; \ | ||
89 | u32 get; \ | ||
90 | u32 put; \ | ||
91 | type array[(pool_size) + 1]; \ | ||
92 | } pool_name | ||
93 | |||
94 | |||
95 | /** | ||
96 | * sci_pool_empty() - | ||
97 | * | ||
98 | * This macro evaluates the pool and returns true if the pool is empty. If the | ||
99 | * pool is empty the user should not perform any get operation on the pool. | ||
100 | */ | ||
101 | #define sci_pool_empty(this_pool) \ | ||
102 | ((this_pool).get == (this_pool).put) | ||
103 | |||
104 | /** | ||
105 | * sci_pool_full() - | ||
106 | * | ||
107 | * This macro evaluates the pool and returns true if the pool is full. If the | ||
108 | * pool is full the user should not perform any put operation. | ||
109 | */ | ||
110 | #define sci_pool_full(this_pool) \ | ||
111 | (SCI_POOL_INCREMENT(this_pool, (this_pool).put) == (this_pool).get) | ||
112 | |||
113 | /** | ||
114 | * sci_pool_size() - | ||
115 | * | ||
116 | * This macro returns the size of the pool created. The internal size of the | ||
117 | * pool is actually 1 larger then necessary in order to ensure get and put | ||
118 | * pointers can be written simultaneously by different users. As a result, | ||
119 | * this macro subtracts 1 from the internal size | ||
120 | */ | ||
121 | #define sci_pool_size(this_pool) \ | ||
122 | ((this_pool).size - 1) | ||
123 | |||
124 | /** | ||
125 | * sci_pool_count() - | ||
126 | * | ||
127 | * This macro indicates the number of elements currently contained in the pool. | ||
128 | */ | ||
129 | #define sci_pool_count(this_pool) \ | ||
130 | (\ | ||
131 | sci_pool_empty((this_pool)) \ | ||
132 | ? 0 \ | ||
133 | : (\ | ||
134 | sci_pool_full((this_pool)) \ | ||
135 | ? sci_pool_size((this_pool)) \ | ||
136 | : (\ | ||
137 | (this_pool).get > (this_pool).put \ | ||
138 | ? ((this_pool).size - (this_pool).get + (this_pool).put) \ | ||
139 | : ((this_pool).put - (this_pool).get) \ | ||
140 | ) \ | ||
141 | ) \ | ||
142 | ) | ||
143 | |||
144 | /** | ||
145 | * sci_pool_initialize() - | ||
146 | * | ||
147 | * This macro initializes the pool to an empty condition. | ||
148 | */ | ||
149 | #define sci_pool_initialize(this_pool) \ | ||
150 | { \ | ||
151 | (this_pool).size = (sizeof((this_pool).array) / sizeof((this_pool).array[0])); \ | ||
152 | (this_pool).get = 0; \ | ||
153 | (this_pool).put = 0; \ | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * sci_pool_get() - | ||
158 | * | ||
159 | * This macro will get the next free element from the pool. This should only be | ||
160 | * called if the pool is not empty. | ||
161 | */ | ||
162 | #define sci_pool_get(this_pool, my_value) \ | ||
163 | { \ | ||
164 | (my_value) = (this_pool).array[(this_pool).get]; \ | ||
165 | (this_pool).get = SCI_POOL_INCREMENT((this_pool), (this_pool).get); \ | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * sci_pool_put() - | ||
170 | * | ||
171 | * This macro will put the value into the pool. This should only be called if | ||
172 | * the pool is not full. | ||
173 | */ | ||
174 | #define sci_pool_put(this_pool, the_value) \ | ||
175 | { \ | ||
176 | (this_pool).array[(this_pool).put] = (the_value); \ | ||
177 | (this_pool).put = SCI_POOL_INCREMENT((this_pool), (this_pool).put); \ | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * sci_pool_erase() - | ||
182 | * | ||
183 | * This macro will search the pool and remove any elements in the pool matching | ||
184 | * the supplied value. This method can only be utilized on pools | ||
185 | */ | ||
186 | #define sci_pool_erase(this_pool, type, the_value) \ | ||
187 | { \ | ||
188 | type tmp_value; \ | ||
189 | u32 index; \ | ||
190 | u32 element_count = sci_pool_count((this_pool)); \ | ||
191 | \ | ||
192 | for (index = 0; index < element_count; index++) { \ | ||
193 | sci_pool_get((this_pool), tmp_value); \ | ||
194 | if (tmp_value != (the_value)) \ | ||
195 | sci_pool_put((this_pool), tmp_value); \ | ||
196 | } \ | ||
197 | } | ||
198 | |||
199 | #endif /* _SCI_POOL_H_ */ | ||
diff --git a/drivers/scsi/isci/core/sci_status.h b/drivers/scsi/isci/core/sci_status.h new file mode 100644 index 000000000000..72b61081c28d --- /dev/null +++ b/drivers/scsi/isci/core/sci_status.h | |||
@@ -0,0 +1,409 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_STATUS_H_ | ||
57 | #define _SCI_STATUS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the return status codes utilized across the | ||
61 | * various sub-components in SCI. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | /** | ||
68 | * enum _SCI_STATUS - This is the general return status enumeration for non-IO, | ||
69 | * non-task management related SCI interface methods. | ||
70 | * | ||
71 | * | ||
72 | */ | ||
73 | enum sci_status { | ||
74 | /** | ||
75 | * This member indicates successful completion. | ||
76 | */ | ||
77 | SCI_SUCCESS = 0, | ||
78 | |||
79 | /** | ||
80 | * This value indicates that the calling method completed successfully, | ||
81 | * but that the IO may have completed before having it's start method | ||
82 | * invoked. This occurs during SAT translation for requests that do | ||
83 | * not require an IO to the target or for any other requests that may | ||
84 | * be completed without having to submit IO. | ||
85 | */ | ||
86 | SCI_SUCCESS_IO_COMPLETE_BEFORE_START, | ||
87 | |||
88 | /** | ||
89 | * This Value indicates that the SCU hardware returned an early response | ||
90 | * because the io request specified more data than is returned by the | ||
91 | * target device (mode pages, inquiry data, etc.). The completion routine | ||
92 | * will handle this case to get the actual number of bytes transferred. | ||
93 | */ | ||
94 | SCI_SUCCESS_IO_DONE_EARLY, | ||
95 | |||
96 | /** | ||
97 | * This member indicates that the object for which a state change is | ||
98 | * being requested is already in said state. | ||
99 | */ | ||
100 | SCI_WARNING_ALREADY_IN_STATE, | ||
101 | |||
102 | /** | ||
103 | * This member indicates interrupt coalescence timer may cause SAS | ||
104 | * specification compliance issues (i.e. SMP target mode response | ||
105 | * frames must be returned within 1.9 milliseconds). | ||
106 | */ | ||
107 | SCI_WARNING_TIMER_CONFLICT, | ||
108 | |||
109 | /** | ||
110 | * This field indicates a sequence of action is not completed yet. Mostly, | ||
111 | * this status is used when multiple ATA commands are needed in a SATI translation. | ||
112 | */ | ||
113 | SCI_WARNING_SEQUENCE_INCOMPLETE, | ||
114 | |||
115 | /** | ||
116 | * This member indicates that there was a general failure. | ||
117 | */ | ||
118 | SCI_FAILURE, | ||
119 | |||
120 | /** | ||
121 | * This member indicates that the SCI implementation is unable to complete | ||
122 | * an operation due to a critical flaw the prevents any further operation | ||
123 | * (i.e. an invalid pointer). | ||
124 | */ | ||
125 | SCI_FATAL_ERROR, | ||
126 | |||
127 | /** | ||
128 | * This member indicates the calling function failed, because the state | ||
129 | * of the controller is in a state that prevents successful completion. | ||
130 | */ | ||
131 | SCI_FAILURE_INVALID_STATE, | ||
132 | |||
133 | /** | ||
134 | * This member indicates the calling function failed, because there is | ||
135 | * insufficient resources/memory to complete the request. | ||
136 | */ | ||
137 | SCI_FAILURE_INSUFFICIENT_RESOURCES, | ||
138 | |||
139 | /** | ||
140 | * This member indicates the calling function failed, because the | ||
141 | * controller object required for the operation can't be located. | ||
142 | */ | ||
143 | SCI_FAILURE_CONTROLLER_NOT_FOUND, | ||
144 | |||
145 | /** | ||
146 | * This member indicates the calling function failed, because the | ||
147 | * discovered controller type is not supported by the library. | ||
148 | */ | ||
149 | SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE, | ||
150 | |||
151 | /** | ||
152 | * This member indicates the calling function failed, because the | ||
153 | * requested initialization data version isn't supported. | ||
154 | */ | ||
155 | SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION, | ||
156 | |||
157 | /** | ||
158 | * This member indicates the calling function failed, because the | ||
159 | * requested configuration of SAS Phys into SAS Ports is not supported. | ||
160 | */ | ||
161 | SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION, | ||
162 | |||
163 | /** | ||
164 | * This member indicates the calling function failed, because the | ||
165 | * requested protocol is not supported by the remote device, port, | ||
166 | * or controller. | ||
167 | */ | ||
168 | SCI_FAILURE_UNSUPPORTED_PROTOCOL, | ||
169 | |||
170 | /** | ||
171 | * This member indicates the calling function failed, because the | ||
172 | * requested information type is not supported by the SCI implementation. | ||
173 | */ | ||
174 | SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE, | ||
175 | |||
176 | /** | ||
177 | * This member indicates the calling function failed, because the | ||
178 | * device already exists. | ||
179 | */ | ||
180 | SCI_FAILURE_DEVICE_EXISTS, | ||
181 | |||
182 | /** | ||
183 | * This member indicates the calling function failed, because adding | ||
184 | * a phy to the object is not possible. | ||
185 | */ | ||
186 | SCI_FAILURE_ADDING_PHY_UNSUPPORTED, | ||
187 | |||
188 | /** | ||
189 | * This member indicates the calling function failed, because the | ||
190 | * requested information type is not supported by the SCI implementation. | ||
191 | */ | ||
192 | SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD, | ||
193 | |||
194 | /** | ||
195 | * This member indicates the calling function failed, because the SCI | ||
196 | * implementation does not support the supplied time limit. | ||
197 | */ | ||
198 | SCI_FAILURE_UNSUPPORTED_TIME_LIMIT, | ||
199 | |||
200 | /** | ||
201 | * This member indicates the calling method failed, because the SCI | ||
202 | * implementation does not contain the specified Phy. | ||
203 | */ | ||
204 | SCI_FAILURE_INVALID_PHY, | ||
205 | |||
206 | /** | ||
207 | * This member indicates the calling method failed, because the SCI | ||
208 | * implementation does not contain the specified Port. | ||
209 | */ | ||
210 | SCI_FAILURE_INVALID_PORT, | ||
211 | |||
212 | /** | ||
213 | * This member indicates the calling method was partly successful | ||
214 | * The port was reset but not all phys in port are operational | ||
215 | */ | ||
216 | SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS, | ||
217 | |||
218 | /** | ||
219 | * This member indicates that calling method failed | ||
220 | * The port reset did not complete because none of the phys are operational | ||
221 | */ | ||
222 | SCI_FAILURE_RESET_PORT_FAILURE, | ||
223 | |||
224 | /** | ||
225 | * This member indicates the calling method failed, because the SCI | ||
226 | * implementation does not contain the specified remote device. | ||
227 | */ | ||
228 | SCI_FAILURE_INVALID_REMOTE_DEVICE, | ||
229 | |||
230 | /** | ||
231 | * This member indicates the calling method failed, because the remote | ||
232 | * device is in a bad state and requires a reset. | ||
233 | */ | ||
234 | SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, | ||
235 | |||
236 | /** | ||
237 | * This member indicates the calling method failed, because the SCI | ||
238 | * implementation does not contain or support the specified IO tag. | ||
239 | */ | ||
240 | SCI_FAILURE_INVALID_IO_TAG, | ||
241 | |||
242 | /** | ||
243 | * This member indicates that the operation failed and the user should | ||
244 | * check the response data associated with the IO. | ||
245 | */ | ||
246 | SCI_FAILURE_IO_RESPONSE_VALID, | ||
247 | |||
248 | /** | ||
249 | * This member indicates that the operation failed, the failure is | ||
250 | * controller implementation specific, and the response data associated | ||
251 | * with the request is not valid. You can query for the controller | ||
252 | * specific error information via scic_controller_get_request_status() | ||
253 | */ | ||
254 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, | ||
255 | |||
256 | /** | ||
257 | * This member indicated that the operation failed because the | ||
258 | * user requested this IO to be terminated. | ||
259 | */ | ||
260 | SCI_FAILURE_IO_TERMINATED, | ||
261 | |||
262 | /** | ||
263 | * This member indicates that the operation failed and the associated | ||
264 | * request requires a SCSI abort task to be sent to the target. | ||
265 | */ | ||
266 | SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, | ||
267 | |||
268 | /** | ||
269 | * This member indicates that the operation failed because the supplied | ||
270 | * device could not be located. | ||
271 | */ | ||
272 | SCI_FAILURE_DEVICE_NOT_FOUND, | ||
273 | |||
274 | /** | ||
275 | * This member indicates that the operation failed because the | ||
276 | * objects association is required and is not correctly set. | ||
277 | */ | ||
278 | SCI_FAILURE_INVALID_ASSOCIATION, | ||
279 | |||
280 | /** | ||
281 | * This member indicates that the operation failed, because a timeout | ||
282 | * occurred. | ||
283 | */ | ||
284 | SCI_FAILURE_TIMEOUT, | ||
285 | |||
286 | /** | ||
287 | * This member indicates that the operation failed, because the user | ||
288 | * specified a value that is either invalid or not supported. | ||
289 | */ | ||
290 | SCI_FAILURE_INVALID_PARAMETER_VALUE, | ||
291 | |||
292 | /** | ||
293 | * This value indicates that the operation failed, because the number | ||
294 | * of messages (MSI-X) is not supported. | ||
295 | */ | ||
296 | SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT, | ||
297 | |||
298 | /** | ||
299 | * This value indicates that the method failed due to a lack of | ||
300 | * available NCQ tags. | ||
301 | */ | ||
302 | SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, | ||
303 | |||
304 | /** | ||
305 | * This value indicates that a protocol violation has occurred on the | ||
306 | * link. | ||
307 | */ | ||
308 | SCI_FAILURE_PROTOCOL_VIOLATION, | ||
309 | |||
310 | /** | ||
311 | * This value indicates a failure condition that retry may help to clear. | ||
312 | */ | ||
313 | SCI_FAILURE_RETRY_REQUIRED, | ||
314 | |||
315 | /** | ||
316 | * This field indicates the retry limit was reached when a retry is attempted | ||
317 | */ | ||
318 | SCI_FAILURE_RETRY_LIMIT_REACHED, | ||
319 | |||
320 | /** | ||
321 | * This member indicates the calling method was partly successful. | ||
322 | * Mostly, this status is used when a LUN_RESET issued to an expander attached | ||
323 | * STP device in READY NCQ substate needs to have RNC suspended/resumed | ||
324 | * before posting TC. | ||
325 | */ | ||
326 | SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS, | ||
327 | |||
328 | /** | ||
329 | * This field indicates an illegal phy connection based on the routing attribute | ||
330 | * of both expander phy attached to each other. | ||
331 | */ | ||
332 | SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION, | ||
333 | |||
334 | /** | ||
335 | * This field indicates a CONFIG ROUTE INFO command has a response with function result | ||
336 | * INDEX DOES NOT EXIST, usually means exceeding max route index. | ||
337 | */ | ||
338 | SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX, | ||
339 | |||
340 | /** | ||
341 | * This value indicates that an unsupported PCI device ID has been | ||
342 | * specified. This indicates that attempts to invoke | ||
343 | * scic_library_allocate_controller() will fail. | ||
344 | */ | ||
345 | SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID | ||
346 | |||
347 | }; | ||
348 | |||
349 | /** | ||
350 | * enum _SCI_IO_STATUS - This enumeration depicts all of the possible IO | ||
351 | * completion status values. Each value in this enumeration maps directly | ||
352 | * to a value in the enum sci_status enumeration. Please refer to that | ||
353 | * enumeration for detailed comments concerning what the status represents. | ||
354 | * | ||
355 | * Add the API to retrieve the SCU status from the core. Check to see that the | ||
356 | * following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL | ||
357 | * - SCI_IO_FAILURE_INVALID_IO_TAG | ||
358 | */ | ||
359 | enum sci_io_status { | ||
360 | SCI_IO_SUCCESS = SCI_SUCCESS, | ||
361 | SCI_IO_FAILURE = SCI_FAILURE, | ||
362 | SCI_IO_SUCCESS_COMPLETE_BEFORE_START = SCI_SUCCESS_IO_COMPLETE_BEFORE_START, | ||
363 | SCI_IO_SUCCESS_IO_DONE_EARLY = SCI_SUCCESS_IO_DONE_EARLY, | ||
364 | SCI_IO_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, | ||
365 | SCI_IO_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, | ||
366 | SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, | ||
367 | SCI_IO_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, | ||
368 | SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, | ||
369 | SCI_IO_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, | ||
370 | SCI_IO_FAILURE_REQUIRES_SCSI_ABORT = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT, | ||
371 | SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, | ||
372 | SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE, | ||
373 | SCI_IO_FAILURE_PROTOCOL_VIOLATION = SCI_FAILURE_PROTOCOL_VIOLATION, | ||
374 | |||
375 | SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, | ||
376 | |||
377 | SCI_IO_FAILURE_RETRY_REQUIRED = SCI_FAILURE_RETRY_REQUIRED, | ||
378 | SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED, | ||
379 | SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE | ||
380 | }; | ||
381 | |||
382 | /** | ||
383 | * enum _SCI_TASK_STATUS - This enumeration depicts all of the possible task | ||
384 | * completion status values. Each value in this enumeration maps directly | ||
385 | * to a value in the enum sci_status enumeration. Please refer to that | ||
386 | * enumeration for detailed comments concerning what the status represents. | ||
387 | * | ||
388 | * Check to see that the following status are properly handled: | ||
389 | */ | ||
390 | enum sci_task_status { | ||
391 | SCI_TASK_SUCCESS = SCI_SUCCESS, | ||
392 | SCI_TASK_FAILURE = SCI_FAILURE, | ||
393 | SCI_TASK_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE, | ||
394 | SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES, | ||
395 | SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL, | ||
396 | SCI_TASK_FAILURE_INVALID_TAG = SCI_FAILURE_INVALID_IO_TAG, | ||
397 | SCI_TASK_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID, | ||
398 | SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR, | ||
399 | SCI_TASK_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED, | ||
400 | SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE, | ||
401 | |||
402 | SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED, | ||
403 | SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS | ||
404 | |||
405 | }; | ||
406 | |||
407 | |||
408 | #endif /* _SCI_STATUS_H_ */ | ||
409 | |||
diff --git a/drivers/scsi/isci/core/sci_types.h b/drivers/scsi/isci/core/sci_types.h new file mode 100644 index 000000000000..431735d1a589 --- /dev/null +++ b/drivers/scsi/isci/core/sci_types.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_TYPES_H_ | ||
57 | #define _SCI_TYPES_H_ | ||
58 | |||
59 | #include <linux/string.h> | ||
60 | |||
61 | #define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \ | ||
62 | ((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32) | ||
63 | |||
64 | #define SCI_INVALID_HANDLE 0x0 | ||
65 | |||
66 | /** | ||
67 | * The SCI_LIBRARY_HANDLE_T will be utilized by SCI users as an opaque handle | ||
68 | * for the SCI Library object. | ||
69 | * | ||
70 | * SCI_LIBRARY_HANDLE_T | ||
71 | */ | ||
72 | typedef void *SCI_LIBRARY_HANDLE_T; | ||
73 | |||
74 | |||
75 | typedef enum { | ||
76 | SCI_IO_REQUEST_DATA_IN = 0, /* Read operation */ | ||
77 | SCI_IO_REQUEST_DATA_OUT, /* Write operation */ | ||
78 | SCI_IO_REQUEST_NO_DATA | ||
79 | } SCI_IO_REQUEST_DATA_DIRECTION; | ||
80 | |||
81 | |||
82 | enum sci_controller_mode { | ||
83 | SCI_MODE_SPEED, /* Optimized for performance */ | ||
84 | SCI_MODE_SIZE /* Optimized for memory use */ | ||
85 | }; | ||
86 | |||
87 | #endif /* _SCI_TYPES_H_ */ | ||
88 | |||
diff --git a/drivers/scsi/isci/core/sci_util.c b/drivers/scsi/isci/core/sci_util.c new file mode 100644 index 000000000000..5cdd96f29a9e --- /dev/null +++ b/drivers/scsi/isci/core/sci_util.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "sci_util.h" | ||
57 | |||
58 | void scic_word_copy_with_swap( | ||
59 | u32 *destination, | ||
60 | u32 *source, | ||
61 | u32 word_count) | ||
62 | { | ||
63 | while (word_count--) { | ||
64 | *destination = SCIC_SWAP_DWORD(*source); | ||
65 | |||
66 | source++; | ||
67 | destination++; | ||
68 | } | ||
69 | } | ||
70 | |||
diff --git a/drivers/scsi/isci/core/sci_util.h b/drivers/scsi/isci/core/sci_util.h new file mode 100644 index 000000000000..67e2badf8ea8 --- /dev/null +++ b/drivers/scsi/isci/core/sci_util.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_UTIL_H_ | ||
57 | #define _SCI_UTIL_H_ | ||
58 | |||
59 | #include "sci_types.h" | ||
60 | |||
61 | /** | ||
62 | * SCIC_SWAP_DWORD() - | ||
63 | * | ||
64 | * Normal byte swap macro | ||
65 | */ | ||
66 | #define SCIC_SWAP_DWORD(x) \ | ||
67 | (\ | ||
68 | (((x) >> 24) & 0x000000FF) \ | ||
69 | | (((x) >> 8) & 0x0000FF00) \ | ||
70 | | (((x) << 8) & 0x00FF0000) \ | ||
71 | | (((x) << 24) & 0xFF000000) \ | ||
72 | ) | ||
73 | |||
74 | #define SCIC_BUILD_DWORD(char_buffer) \ | ||
75 | (\ | ||
76 | ((char_buffer)[0] << 24) \ | ||
77 | | ((char_buffer)[1] << 16) \ | ||
78 | | ((char_buffer)[2] << 8) \ | ||
79 | | ((char_buffer)[3]) \ | ||
80 | ) | ||
81 | |||
82 | #define SCI_FIELD_OFFSET(type, field) ((unsigned long)&(((type *)0)->field)) | ||
83 | |||
84 | /** | ||
85 | * sci_physical_address_add() - | ||
86 | * | ||
87 | * This macro simply performs addition on an dma_addr_t type. The | ||
88 | * lower u32 value is "clipped" or "wrapped" back through 0. When this occurs | ||
89 | * the upper 32-bits are incremented by 1. | ||
90 | */ | ||
91 | #define sci_physical_address_add(physical_address, value) \ | ||
92 | { \ | ||
93 | u32 lower = lower_32_bits((physical_address)); \ | ||
94 | u32 upper = upper_32_bits((physical_address)); \ | ||
95 | \ | ||
96 | if (lower + (value) < lower) \ | ||
97 | upper += 1; \ | ||
98 | \ | ||
99 | lower += (value); \ | ||
100 | sci_cb_make_physical_address(physical_address, upper, lower); \ | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * sci_physical_address_subtract() - | ||
105 | * | ||
106 | * This macro simply performs subtraction on an dma_addr_t type. The | ||
107 | * lower u32 value is "clipped" or "wrapped" back through 0. When this occurs | ||
108 | * the upper 32-bits are decremented by 1. | ||
109 | */ | ||
110 | #define sci_physical_address_subtract(physical_address, value) \ | ||
111 | { \ | ||
112 | u32 lower = lower_32_bits((physical_address)); \ | ||
113 | u32 upper = upper_32_bits((physical_address)); \ | ||
114 | \ | ||
115 | if (lower - (value) > lower) \ | ||
116 | upper -= 1; \ | ||
117 | \ | ||
118 | lower -= (value); \ | ||
119 | sci_cb_make_physical_address(physical_address, upper, lower); \ | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * scic_word_copy_with_swap() - Copy the data from source to destination and | ||
124 | * swap the bytes during the copy. | ||
125 | * @destination: This parameter specifies the destination address to which the | ||
126 | * data is to be copied. | ||
127 | * @source: This parameter specifies the source address from which data is to | ||
128 | * be copied. | ||
129 | * @word_count: This parameter specifies the number of 32-bit words to copy and | ||
130 | * byte swap. | ||
131 | * | ||
132 | */ | ||
133 | void scic_word_copy_with_swap( | ||
134 | u32 *destination, | ||
135 | u32 *source, | ||
136 | u32 word_count); | ||
137 | |||
138 | #endif /* _SCI_UTIL_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_config_parameters.h b/drivers/scsi/isci/core/scic_config_parameters.h new file mode 100644 index 000000000000..4c16a50a0658 --- /dev/null +++ b/drivers/scsi/isci/core/scic_config_parameters.h | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_USER_PARAMETERS_H_ | ||
57 | #define _SCIC_SDS_USER_PARAMETERS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the structure definitions and interface methods | ||
61 | * that can be called by a SCIC user on the SCU Driver Standard | ||
62 | * (struct scic_sds_user_parameters) user parameter block. | ||
63 | * | ||
64 | * | ||
65 | */ | ||
66 | |||
67 | |||
68 | #include "sci_types.h" | ||
69 | #include "sci_status.h" | ||
70 | #include "intel_sas.h" | ||
71 | #include "sci_controller_constants.h" | ||
72 | |||
73 | struct scic_sds_controller; | ||
74 | |||
75 | /** | ||
76 | * | ||
77 | * | ||
78 | * SCIC_SDS_PARM_PHY_SPEED These constants define the speeds utilized for a | ||
79 | * phy/port. | ||
80 | */ | ||
81 | #define SCIC_SDS_PARM_NO_SPEED 0 | ||
82 | |||
83 | /** | ||
84 | * | ||
85 | * | ||
86 | * This value of 1 indicates generation 1 (i.e. 1.5 Gb/s). | ||
87 | */ | ||
88 | #define SCIC_SDS_PARM_GEN1_SPEED 1 | ||
89 | |||
90 | /** | ||
91 | * | ||
92 | * | ||
93 | * This value of 2 indicates generation 2 (i.e. 3.0 Gb/s). | ||
94 | */ | ||
95 | #define SCIC_SDS_PARM_GEN2_SPEED 2 | ||
96 | |||
97 | /** | ||
98 | * | ||
99 | * | ||
100 | * This value of 3 indicates generation 3 (i.e. 6.0 Gb/s). | ||
101 | */ | ||
102 | #define SCIC_SDS_PARM_GEN3_SPEED 3 | ||
103 | |||
104 | /** | ||
105 | * | ||
106 | * | ||
107 | * For range checks, the max speed generation | ||
108 | */ | ||
109 | #define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED | ||
110 | |||
111 | /** | ||
112 | * struct scic_sds_user_parameters - This structure delineates the various user | ||
113 | * parameters that can be changed by the core user. | ||
114 | * | ||
115 | * | ||
116 | */ | ||
117 | struct scic_sds_user_parameters { | ||
118 | struct { | ||
119 | /** | ||
120 | * This field specifies the NOTIFY (ENABLE SPIN UP) primitive | ||
121 | * insertion frequency for this phy index. | ||
122 | */ | ||
123 | u32 notify_enable_spin_up_insertion_frequency; | ||
124 | |||
125 | /** | ||
126 | * This method specifies the number of transmitted DWORDs within which | ||
127 | * to transmit a single ALIGN primitive. This value applies regardless | ||
128 | * of what type of device is attached or connection state. A value of | ||
129 | * 0 indicates that no ALIGN primitives will be inserted. | ||
130 | */ | ||
131 | u16 align_insertion_frequency; | ||
132 | |||
133 | /** | ||
134 | * This method specifies the number of transmitted DWORDs within which | ||
135 | * to transmit 2 ALIGN primitives. This applies for SAS connections | ||
136 | * only. A minimum value of 3 is required for this field. | ||
137 | */ | ||
138 | u16 in_connection_align_insertion_frequency; | ||
139 | |||
140 | /** | ||
141 | * This field indicates the maximum speed generation to be utilized | ||
142 | * by phys in the supplied port. | ||
143 | * - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s). | ||
144 | * - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s). | ||
145 | * - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s). | ||
146 | */ | ||
147 | u8 max_speed_generation; | ||
148 | |||
149 | } phys[SCI_MAX_PHYS]; | ||
150 | |||
151 | /** | ||
152 | * This field specifies the maximum number of direct attached devices | ||
153 | * that can have power supplied to them simultaneously. | ||
154 | */ | ||
155 | u8 max_number_concurrent_device_spin_up; | ||
156 | |||
157 | /** | ||
158 | * This field specifies the number of seconds to allow a phy to consume | ||
159 | * power before yielding to another phy. | ||
160 | * | ||
161 | */ | ||
162 | u8 phy_spin_up_delay_interval; | ||
163 | |||
164 | /** | ||
165 | * These timer values specifies how long a link will remain open with no | ||
166 | * activity in increments of a microsecond, it can be in increments of | ||
167 | * 100 microseconds if the upper most bit is set. | ||
168 | * | ||
169 | */ | ||
170 | u16 stp_inactivity_timeout; | ||
171 | u16 ssp_inactivity_timeout; | ||
172 | |||
173 | /** | ||
174 | * These timer values specifies how long a link will remain open in increments | ||
175 | * of 100 microseconds. | ||
176 | * | ||
177 | */ | ||
178 | u16 stp_max_occupancy_timeout; | ||
179 | u16 ssp_max_occupancy_timeout; | ||
180 | |||
181 | /** | ||
182 | * This timer value specifies how long a link will remain open with no | ||
183 | * outbound traffic in increments of a microsecond. | ||
184 | * | ||
185 | */ | ||
186 | u8 no_outbound_task_timeout; | ||
187 | |||
188 | }; | ||
189 | |||
190 | /** | ||
191 | * This structure/union specifies the various different user parameter sets | ||
192 | * available. Each type is specific to a hardware controller version. | ||
193 | * | ||
194 | * union scic_user_parameters | ||
195 | */ | ||
196 | union scic_user_parameters { | ||
197 | /** | ||
198 | * This field specifies the user parameters specific to the | ||
199 | * Storage Controller Unit (SCU) Driver Standard (SDS) version | ||
200 | * 1. | ||
201 | */ | ||
202 | struct scic_sds_user_parameters sds1; | ||
203 | |||
204 | }; | ||
205 | |||
206 | |||
207 | /** | ||
208 | * | ||
209 | * | ||
210 | * SCIC_SDS_OEM_PHY_MASK These constants define the valid values for phy_mask | ||
211 | */ | ||
212 | |||
213 | /** | ||
214 | * | ||
215 | * | ||
216 | * This is the min value assignable to a port's phy mask | ||
217 | */ | ||
218 | #define SCIC_SDS_PARM_PHY_MASK_MIN 0x0 | ||
219 | |||
220 | /** | ||
221 | * | ||
222 | * | ||
223 | * This is the max value assignable to a port's phy mask | ||
224 | */ | ||
225 | #define SCIC_SDS_PARM_PHY_MASK_MAX 0xF | ||
226 | |||
227 | /** | ||
228 | * struct scic_sds_oem_parameters - This structure delineates the various OEM | ||
229 | * parameters that must be set the core user. | ||
230 | * | ||
231 | * | ||
232 | */ | ||
233 | struct scic_sds_oem_parameters { | ||
234 | struct { | ||
235 | /** | ||
236 | * This field indicates whether Spread Spectrum Clocking (SSC) | ||
237 | * should be enabled or disabled. | ||
238 | */ | ||
239 | bool do_enable_ssc; | ||
240 | |||
241 | } controller; | ||
242 | |||
243 | struct { | ||
244 | /** | ||
245 | * This field specifies the phys to be contained inside a port. | ||
246 | * The bit position in the mask specifies the index of the phy | ||
247 | * to be contained in the port. Multiple bits (i.e. phys) | ||
248 | * can be contained in a single port. | ||
249 | */ | ||
250 | u8 phy_mask; | ||
251 | |||
252 | } ports[SCI_MAX_PORTS]; | ||
253 | |||
254 | struct { | ||
255 | /** | ||
256 | * This field specifies the SAS address to be transmitted on | ||
257 | * for this phy index. | ||
258 | */ | ||
259 | struct sci_sas_address sas_address; | ||
260 | |||
261 | } phys[SCI_MAX_PHYS]; | ||
262 | |||
263 | }; | ||
264 | |||
265 | /** | ||
266 | * This structure/union specifies the various different OEM parameter sets | ||
267 | * available. Each type is specific to a hardware controller version. | ||
268 | * | ||
269 | * union scic_oem_parameters | ||
270 | */ | ||
271 | union scic_oem_parameters { | ||
272 | /** | ||
273 | * This field specifies the OEM parameters specific to the | ||
274 | * Storage Controller Unit (SCU) Driver Standard (SDS) version | ||
275 | * 1. | ||
276 | */ | ||
277 | struct scic_sds_oem_parameters sds1; | ||
278 | |||
279 | }; | ||
280 | |||
281 | /** | ||
282 | * scic_user_parameters_set() - This method allows the user to attempt to | ||
283 | * change the user parameters utilized by the controller. | ||
284 | * @controller: This parameter specifies the controller on which to set the | ||
285 | * user parameters. | ||
286 | * @user_parameters: This parameter specifies the USER_PARAMETERS object | ||
287 | * containing the potential new values. | ||
288 | * | ||
289 | * Indicate if the update of the user parameters was successful. SCI_SUCCESS | ||
290 | * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE | ||
291 | * This value is returned if the attempt to change the user parameter failed, | ||
292 | * because changing one of the parameters is not currently allowed. | ||
293 | * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user | ||
294 | * supplied an invalid interrupt coalescence time, spin up delay interval, etc. | ||
295 | */ | ||
296 | enum sci_status scic_user_parameters_set( | ||
297 | struct scic_sds_controller *controller, | ||
298 | union scic_user_parameters *user_parameters); | ||
299 | |||
300 | /** | ||
301 | * scic_user_parameters_get() - This method allows the user to retrieve the | ||
302 | * user parameters utilized by the controller. | ||
303 | * @controller: This parameter specifies the controller on which to set the | ||
304 | * user parameters. | ||
305 | * @user_parameters: This parameter specifies the USER_PARAMETERS object into | ||
306 | * which the framework shall save it's parameters. | ||
307 | * | ||
308 | */ | ||
309 | void scic_user_parameters_get( | ||
310 | struct scic_sds_controller *controller, | ||
311 | union scic_user_parameters *user_parameters); | ||
312 | |||
313 | /** | ||
314 | * scic_oem_parameters_set() - This method allows the user to attempt to change | ||
315 | * the OEM parameters utilized by the controller. | ||
316 | * @controller: This parameter specifies the controller on which to set the | ||
317 | * user parameters. | ||
318 | * @oem_parameters: This parameter specifies the OEM parameters object | ||
319 | * containing the potential new values. | ||
320 | * | ||
321 | * Indicate if the update of the user parameters was successful. SCI_SUCCESS | ||
322 | * This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE | ||
323 | * This value is returned if the attempt to change the user parameter failed, | ||
324 | * because changing one of the parameters is not currently allowed. | ||
325 | * SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user | ||
326 | * supplied an unsupported value for one of the OEM parameters. | ||
327 | */ | ||
328 | enum sci_status scic_oem_parameters_set( | ||
329 | struct scic_sds_controller *controller, | ||
330 | union scic_oem_parameters *oem_parameters); | ||
331 | |||
332 | /** | ||
333 | * scic_oem_parameters_get() - This method allows the user to retreive the OEM | ||
334 | * parameters utilized by the controller. | ||
335 | * @controller: This parameter specifies the controller on which to set the | ||
336 | * user parameters. | ||
337 | * @oem_parameters: This parameter specifies the OEM parameters object in which | ||
338 | * to write the core's OEM parameters. | ||
339 | * | ||
340 | */ | ||
341 | void scic_oem_parameters_get( | ||
342 | struct scic_sds_controller *controller, | ||
343 | union scic_oem_parameters *oem_parameters); | ||
344 | |||
345 | |||
346 | #endif /* _SCIC_SDS_USER_PARAMETERS_H_ */ | ||
347 | |||
diff --git a/drivers/scsi/isci/core/scic_controller.h b/drivers/scsi/isci/core/scic_controller.h new file mode 100644 index 000000000000..756b14fcd9a4 --- /dev/null +++ b/drivers/scsi/isci/core/scic_controller.h | |||
@@ -0,0 +1,586 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_CONTROLLER_H_ | ||
57 | #define _SCIC_CONTROLLER_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the interface methods that can be called by an | ||
61 | * SCIC user on a controller object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_status.h" | ||
69 | #include "sci_controller.h" | ||
70 | #include "scic_config_parameters.h" | ||
71 | |||
72 | struct scic_sds_request; | ||
73 | struct scic_sds_phy; | ||
74 | struct scic_sds_port; | ||
75 | struct scic_sds_remote_device; | ||
76 | |||
77 | /** | ||
78 | * enum _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of | ||
79 | * interrupts that are potentially supported by a SCI Core implementation. | ||
80 | * | ||
81 | * | ||
82 | */ | ||
83 | enum scic_interrupt_type { | ||
84 | SCIC_LEGACY_LINE_INTERRUPT_TYPE, | ||
85 | SCIC_MSIX_INTERRUPT_TYPE, | ||
86 | |||
87 | /** | ||
88 | * This enumeration value indicates the use of polling. | ||
89 | */ | ||
90 | SCIC_NO_INTERRUPTS | ||
91 | |||
92 | }; | ||
93 | |||
94 | /** | ||
95 | * This method is called by the SCI user in order to have the SCI | ||
96 | * implementation handle the interrupt. This method performs minimal | ||
97 | * processing to allow for streamlined interrupt time usage. | ||
98 | * | ||
99 | * SCIC_CONTROLLER_INTERRUPT_HANDLER true: returned if there is an interrupt to | ||
100 | * process and it was processed. false: returned if no interrupt was processed. | ||
101 | */ | ||
102 | typedef bool (*SCIC_CONTROLLER_INTERRUPT_HANDLER)( | ||
103 | struct scic_sds_controller *controller | ||
104 | ); | ||
105 | |||
106 | /** | ||
107 | * This method is called by the SCI user to process completions generated as a | ||
108 | * result of a previously handled interrupt. This method will result in the | ||
109 | * completion of IO requests and handling of other controller generated | ||
110 | * events. This method should be called some time after the interrupt | ||
111 | * handler. | ||
112 | * | ||
113 | * Most, if not all, of the user callback APIs are invoked from within this | ||
114 | * API. As a result, the user should be cognizent of the operating level at | ||
115 | * which they invoke this API. | ||
116 | */ | ||
117 | typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)( | ||
118 | struct scic_sds_controller *controller | ||
119 | ); | ||
120 | |||
121 | /** | ||
122 | * struct scic_controller_handler_methods - This structure contains an | ||
123 | * interrupt handler and completion handler function pointers. | ||
124 | * | ||
125 | * | ||
126 | */ | ||
127 | struct scic_controller_handler_methods { | ||
128 | SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler; | ||
129 | SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler; | ||
130 | |||
131 | }; | ||
132 | |||
133 | /** | ||
134 | * scic_controller_construct() - This method will attempt to construct a | ||
135 | * controller object utilizing the supplied parameter information. | ||
136 | * @c: This parameter specifies the controller to be constructed. | ||
137 | * @scu_base: mapped base address of the scu registers | ||
138 | * @smu_base: mapped base address of the smu registers | ||
139 | * | ||
140 | * Indicate if the controller was successfully constructed or if it failed in | ||
141 | * some way. SCI_SUCCESS This value is returned if the controller was | ||
142 | * successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned | ||
143 | * if the interrupt coalescence timer may cause SAS compliance issues for SMP | ||
144 | * Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE | ||
145 | * This value is returned if the controller does not support the supplied type. | ||
146 | * SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the | ||
147 | * controller does not support the supplied initialization data version. | ||
148 | */ | ||
149 | enum sci_status scic_controller_construct(struct scic_sds_controller *c, | ||
150 | void __iomem *scu_base, | ||
151 | void __iomem *smu_base); | ||
152 | |||
153 | /** | ||
154 | * scic_controller_enable_interrupts() - This method will enable all controller | ||
155 | * interrupts. | ||
156 | * @controller: This parameter specifies the controller for which to enable | ||
157 | * interrupts. | ||
158 | * | ||
159 | */ | ||
160 | void scic_controller_enable_interrupts( | ||
161 | struct scic_sds_controller *controller); | ||
162 | |||
163 | /** | ||
164 | * scic_controller_disable_interrupts() - This method will disable all | ||
165 | * controller interrupts. | ||
166 | * @controller: This parameter specifies the controller for which to disable | ||
167 | * interrupts. | ||
168 | * | ||
169 | */ | ||
170 | void scic_controller_disable_interrupts( | ||
171 | struct scic_sds_controller *controller); | ||
172 | |||
173 | /** | ||
174 | * scic_controller_get_handler_methods() - This method will return provide | ||
175 | * function pointers for the interrupt handler and completion handler. The | ||
176 | * interrupt handler is expected to be invoked at interrupt time. The | ||
177 | * completion handler is scheduled to run as a result of the interrupt | ||
178 | * handler. The completion handler performs the bulk work for processing | ||
179 | * silicon events. | ||
180 | * @interrupt_type: This parameter informs the core which type of | ||
181 | * interrupt/completion methods are being requested. These are the types: | ||
182 | * SCIC_LEGACY_LINE_INTERRUPT_TYPE, SCIC_MSIX_INTERRUPT_TYPE, | ||
183 | * SCIC_NO_INTERRUPTS (POLLING) | ||
184 | * @message_count: This parameter informs the core the number of MSI-X messages | ||
185 | * to be utilized. This parameter must be 0 when requesting legacy line | ||
186 | * based handlers. | ||
187 | * @handler_methods: The caller provides a pointer to a buffer of type | ||
188 | * struct scic_controller_handler_methods. The size depends on the combination of | ||
189 | * the interrupt_type and message_count input parameters: | ||
190 | * SCIC_LEGACY_LINE_INTERRUPT_TYPE: - size = | ||
191 | * sizeof(struct scic_controller_handler_methods) SCIC_MSIX_INTERRUPT_TYPE: | ||
192 | * sizeof(struct scic_controller_handler_methods) | ||
193 | * @handler_methods: SCIC fills out the caller's buffer with the appropriate | ||
194 | * interrupt and completion handlers based on the info provided in the | ||
195 | * interrupt_type and message_count input parameters. For | ||
196 | * SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer receives a single | ||
197 | * struct scic_controller_handler_methods element regardless that the | ||
198 | * message_count parameter is zero. For SCIC_MSIX_INTERRUPT_TYPE, the buffer | ||
199 | * receives an array of elements of type struct scic_controller_handler_methods | ||
200 | * where the array size is equivalent to the message_count parameter. The | ||
201 | * array is zero-relative where entry zero corresponds to message-vector | ||
202 | * zero, entry one corresponds to message-vector one, and so forth. | ||
203 | * | ||
204 | * Indicate if the handler retrieval operation was successful. SCI_SUCCESS This | ||
205 | * value is returned if retrieval succeeded. | ||
206 | * SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned if the user | ||
207 | * supplied an unsupported number of MSI-X messages. For legacy line interrupts | ||
208 | * the only valid value is 0. | ||
209 | */ | ||
210 | enum sci_status scic_controller_get_handler_methods( | ||
211 | enum scic_interrupt_type interrupt_type, | ||
212 | u16 message_count, | ||
213 | struct scic_controller_handler_methods *handler_methods); | ||
214 | |||
215 | /** | ||
216 | * scic_controller_initialize() - This method will initialize the controller | ||
217 | * hardware managed by the supplied core controller object. This method | ||
218 | * will bring the physical controller hardware out of reset and enable the | ||
219 | * core to determine the capabilities of the hardware being managed. Thus, | ||
220 | * the core controller can determine it's exact physical (DMA capable) | ||
221 | * memory requirements. | ||
222 | * @controller: This parameter specifies the controller to be initialized. | ||
223 | * | ||
224 | * The SCI Core user must have called scic_controller_construct() on the | ||
225 | * supplied controller object previously. Indicate if the controller was | ||
226 | * successfully initialized or if it failed in some way. SCI_SUCCESS This value | ||
227 | * is returned if the controller hardware was successfully initialized. | ||
228 | */ | ||
229 | enum sci_status scic_controller_initialize( | ||
230 | struct scic_sds_controller *controller); | ||
231 | |||
232 | /** | ||
233 | * scic_controller_get_suggested_start_timeout() - This method returns the | ||
234 | * suggested scic_controller_start() timeout amount. The user is free to | ||
235 | * use any timeout value, but this method provides the suggested minimum | ||
236 | * start timeout value. The returned value is based upon empirical | ||
237 | * information determined as a result of interoperability testing. | ||
238 | * @controller: the handle to the controller object for which to return the | ||
239 | * suggested start timeout. | ||
240 | * | ||
241 | * This method returns the number of milliseconds for the suggested start | ||
242 | * operation timeout. | ||
243 | */ | ||
244 | u32 scic_controller_get_suggested_start_timeout( | ||
245 | struct scic_sds_controller *controller); | ||
246 | |||
247 | /** | ||
248 | * scic_controller_start() - This method will start the supplied core | ||
249 | * controller. This method will start the staggered spin up operation. The | ||
250 | * SCI User completion callback is called when the following conditions are | ||
251 | * met: -# the return status of this method is SCI_SUCCESS. -# after all of | ||
252 | * the phys have successfully started or been given the opportunity to start. | ||
253 | * @controller: the handle to the controller object to start. | ||
254 | * @timeout: This parameter specifies the number of milliseconds in which the | ||
255 | * start operation should complete. | ||
256 | * | ||
257 | * The SCI Core user must have filled in the physical memory descriptor | ||
258 | * structure via the sci_controller_get_memory_descriptor_list() method. The | ||
259 | * SCI Core user must have invoked the scic_controller_initialize() method | ||
260 | * prior to invoking this method. The controller must be in the INITIALIZED or | ||
261 | * STARTED state. Indicate if the controller start method succeeded or failed | ||
262 | * in some way. SCI_SUCCESS if the start operation succeeded. | ||
263 | * SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED | ||
264 | * state. SCI_FAILURE_INVALID_STATE if the controller is not either in the | ||
265 | * INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if | ||
266 | * there are inconsistent or invalid values in the supplied | ||
267 | * struct sci_physical_memory_descriptor array. | ||
268 | */ | ||
269 | enum sci_status scic_controller_start( | ||
270 | struct scic_sds_controller *controller, | ||
271 | u32 timeout); | ||
272 | |||
273 | /** | ||
274 | * scic_controller_stop() - This method will stop an individual controller | ||
275 | * object.This method will invoke the associated user callback upon | ||
276 | * completion. The completion callback is called when the following | ||
277 | * conditions are met: -# the method return status is SCI_SUCCESS. -# the | ||
278 | * controller has been quiesced. This method will ensure that all IO | ||
279 | * requests are quiesced, phys are stopped, and all additional operation by | ||
280 | * the hardware is halted. | ||
281 | * @controller: the handle to the controller object to stop. | ||
282 | * @timeout: This parameter specifies the number of milliseconds in which the | ||
283 | * stop operation should complete. | ||
284 | * | ||
285 | * The controller must be in the STARTED or STOPPED state. Indicate if the | ||
286 | * controller stop method succeeded or failed in some way. SCI_SUCCESS if the | ||
287 | * stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the | ||
288 | * controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the | ||
289 | * controller is not either in the STARTED or STOPPED states. | ||
290 | */ | ||
291 | enum sci_status scic_controller_stop( | ||
292 | struct scic_sds_controller *controller, | ||
293 | u32 timeout); | ||
294 | |||
295 | /** | ||
296 | * scic_controller_reset() - This method will reset the supplied core | ||
297 | * controller regardless of the state of said controller. This operation is | ||
298 | * considered destructive. In other words, all current operations are wiped | ||
299 | * out. No IO completions for outstanding devices occur. Outstanding IO | ||
300 | * requests are not aborted or completed at the actual remote device. | ||
301 | * @controller: the handle to the controller object to reset. | ||
302 | * | ||
303 | * Indicate if the controller reset method succeeded or failed in some way. | ||
304 | * SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if | ||
305 | * the controller reset operation is unable to complete. | ||
306 | */ | ||
307 | enum sci_status scic_controller_reset( | ||
308 | struct scic_sds_controller *controller); | ||
309 | |||
310 | /** | ||
311 | * scic_controller_start_io() - This method is called by the SCI user to | ||
312 | * send/start an IO request. If the method invocation is successful, then | ||
313 | * the IO request has been queued to the hardware for processing. | ||
314 | * @controller: the handle to the controller object for which to start an IO | ||
315 | * request. | ||
316 | * @remote_device: the handle to the remote device object for which to start an | ||
317 | * IO request. | ||
318 | * @io_request: the handle to the io request object to start. | ||
319 | * @io_tag: This parameter specifies a previously allocated IO tag that the | ||
320 | * user desires to be utilized for this request. This parameter is optional. | ||
321 | * The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value | ||
322 | * for this parameter. | ||
323 | * | ||
324 | * - IO tags are a protected resource. It is incumbent upon the SCI Core user | ||
325 | * to ensure that each of the methods that may allocate or free available IO | ||
326 | * tags are handled in a mutually exclusive manner. This method is one of said | ||
327 | * methods requiring proper critical code section protection (e.g. semaphore, | ||
328 | * spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a | ||
329 | * result, it is expected the user will have set the NCQ tag field in the host | ||
330 | * to device register FIS prior to calling this method. There is also a | ||
331 | * requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking | ||
332 | * the scic_controller_start_io() method. scic_controller_allocate_tag() for | ||
333 | * more information on allocating a tag. Indicate if the controller | ||
334 | * successfully started the IO request. SCI_IO_SUCCESS if the IO request was | ||
335 | * successfully started. Determine the failure situations and return values. | ||
336 | */ | ||
337 | enum sci_io_status scic_controller_start_io( | ||
338 | struct scic_sds_controller *controller, | ||
339 | struct scic_sds_remote_device *remote_device, | ||
340 | struct scic_sds_request *io_request, | ||
341 | u16 io_tag); | ||
342 | |||
343 | |||
344 | /** | ||
345 | * scic_controller_start_task() - This method is called by the SCIC user to | ||
346 | * send/start a framework task management request. | ||
347 | * @controller: the handle to the controller object for which to start the task | ||
348 | * management request. | ||
349 | * @remote_device: the handle to the remote device object for which to start | ||
350 | * the task management request. | ||
351 | * @task_request: the handle to the task request object to start. | ||
352 | * @io_tag: This parameter specifies a previously allocated IO tag that the | ||
353 | * user desires to be utilized for this request. Note this not the io_tag | ||
354 | * of the request being managed. It is to be utilized for the task request | ||
355 | * itself. This parameter is optional. The user is allowed to supply | ||
356 | * SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter. | ||
357 | * | ||
358 | * - IO tags are a protected resource. It is incumbent upon the SCI Core user | ||
359 | * to ensure that each of the methods that may allocate or free available IO | ||
360 | * tags are handled in a mutually exclusive manner. This method is one of said | ||
361 | * methods requiring proper critical code section protection (e.g. semaphore, | ||
362 | * spin-lock, etc.). - The user must synchronize this task with completion | ||
363 | * queue processing. If they are not synchronized then it is possible for the | ||
364 | * io requests that are being managed by the task request can complete before | ||
365 | * starting the task request. scic_controller_allocate_tag() for more | ||
366 | * information on allocating a tag. Indicate if the controller successfully | ||
367 | * started the IO request. SCI_TASK_SUCCESS if the task request was | ||
368 | * successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is | ||
369 | * returned if there is/are task(s) outstanding that require termination or | ||
370 | * completion before this request can succeed. | ||
371 | */ | ||
372 | enum sci_task_status scic_controller_start_task( | ||
373 | struct scic_sds_controller *controller, | ||
374 | struct scic_sds_remote_device *remote_device, | ||
375 | struct scic_sds_request *task_request, | ||
376 | u16 io_tag); | ||
377 | |||
378 | /** | ||
379 | * scic_controller_complete_task() - This method will perform core specific | ||
380 | * completion operations for task management request. After this method is | ||
381 | * invoked, the user should consider the task request as invalid until it is | ||
382 | * properly reused (i.e. re-constructed). | ||
383 | * @controller: The handle to the controller object for which to complete the | ||
384 | * task management request. | ||
385 | * @remote_device: The handle to the remote device object for which to complete | ||
386 | * the task management request. | ||
387 | * @task_request: the handle to the task management request object to complete. | ||
388 | * | ||
389 | * Indicate if the controller successfully completed the task management | ||
390 | * request. SCI_SUCCESS if the completion process was successful. | ||
391 | */ | ||
392 | enum sci_status scic_controller_complete_task( | ||
393 | struct scic_sds_controller *controller, | ||
394 | struct scic_sds_remote_device *remote_device, | ||
395 | struct scic_sds_request *task_request); | ||
396 | |||
397 | |||
398 | /** | ||
399 | * scic_controller_terminate_request() - This method is called by the SCI Core | ||
400 | * user to terminate an ongoing (i.e. started) core IO request. This does | ||
401 | * not abort the IO request at the target, but rather removes the IO request | ||
402 | * from the host controller. | ||
403 | * @controller: the handle to the controller object for which to terminate a | ||
404 | * request. | ||
405 | * @remote_device: the handle to the remote device object for which to | ||
406 | * terminate a request. | ||
407 | * @request: the handle to the io or task management request object to | ||
408 | * terminate. | ||
409 | * | ||
410 | * Indicate if the controller successfully began the terminate process for the | ||
411 | * IO request. SCI_SUCCESS if the terminate process was successfully started | ||
412 | * for the request. Determine the failure situations and return values. | ||
413 | */ | ||
414 | enum sci_status scic_controller_terminate_request( | ||
415 | struct scic_sds_controller *controller, | ||
416 | struct scic_sds_remote_device *remote_device, | ||
417 | struct scic_sds_request *request); | ||
418 | |||
419 | /** | ||
420 | * scic_controller_complete_io() - This method will perform core specific | ||
421 | * completion operations for an IO request. After this method is invoked, | ||
422 | * the user should consider the IO request as invalid until it is properly | ||
423 | * reused (i.e. re-constructed). | ||
424 | * @controller: The handle to the controller object for which to complete the | ||
425 | * IO request. | ||
426 | * @remote_device: The handle to the remote device object for which to complete | ||
427 | * the IO request. | ||
428 | * @io_request: the handle to the io request object to complete. | ||
429 | * | ||
430 | * - IO tags are a protected resource. It is incumbent upon the SCI Core user | ||
431 | * to ensure that each of the methods that may allocate or free available IO | ||
432 | * tags are handled in a mutually exclusive manner. This method is one of said | ||
433 | * methods requiring proper critical code section protection (e.g. semaphore, | ||
434 | * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI | ||
435 | * Core user, using the scic_controller_allocate_io_tag() method, then it is | ||
436 | * the responsibility of the caller to invoke the scic_controller_free_io_tag() | ||
437 | * method to free the tag (i.e. this method will not free the IO tag). Indicate | ||
438 | * if the controller successfully completed the IO request. SCI_SUCCESS if the | ||
439 | * completion process was successful. | ||
440 | */ | ||
441 | enum sci_status scic_controller_complete_io( | ||
442 | struct scic_sds_controller *controller, | ||
443 | struct scic_sds_remote_device *remote_device, | ||
444 | struct scic_sds_request *io_request); | ||
445 | |||
446 | |||
447 | /** | ||
448 | * scic_controller_get_port_handle() - This method simply provides the user | ||
449 | * with a unique handle for a given SAS/SATA core port index. | ||
450 | * @controller: This parameter represents the handle to the controller object | ||
451 | * from which to retrieve a port (SAS or SATA) handle. | ||
452 | * @port_index: This parameter specifies the port index in the controller for | ||
453 | * which to retrieve the port handle. 0 <= port_index < maximum number of | ||
454 | * phys. | ||
455 | * @port_handle: This parameter specifies the retrieved port handle to be | ||
456 | * provided to the caller. | ||
457 | * | ||
458 | * Indicate if the retrieval of the port handle was successful. SCI_SUCCESS | ||
459 | * This value is returned if the retrieval was successful. | ||
460 | * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is | ||
461 | * not in the supported range. | ||
462 | */ | ||
463 | enum sci_status scic_controller_get_port_handle( | ||
464 | struct scic_sds_controller *controller, | ||
465 | u8 port_index, | ||
466 | struct scic_sds_port **port_handle); | ||
467 | |||
468 | /** | ||
469 | * scic_controller_get_phy_handle() - This method simply provides the user with | ||
470 | * a unique handle for a given SAS/SATA phy index/identifier. | ||
471 | * @controller: This parameter represents the handle to the controller object | ||
472 | * from which to retrieve a phy (SAS or SATA) handle. | ||
473 | * @phy_index: This parameter specifies the phy index in the controller for | ||
474 | * which to retrieve the phy handle. 0 <= phy_index < maximum number of phys. | ||
475 | * @phy_handle: This parameter specifies the retrieved phy handle to be | ||
476 | * provided to the caller. | ||
477 | * | ||
478 | * Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This | ||
479 | * value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY | ||
480 | * This value is returned if the supplied phy id is not in the supported range. | ||
481 | */ | ||
482 | enum sci_status scic_controller_get_phy_handle( | ||
483 | struct scic_sds_controller *controller, | ||
484 | u8 phy_index, | ||
485 | struct scic_sds_phy **phy_handle); | ||
486 | |||
487 | /** | ||
488 | * scic_controller_allocate_io_tag() - This method will allocate a tag from the | ||
489 | * pool of free IO tags. Direct allocation of IO tags by the SCI Core user | ||
490 | * is optional. The scic_controller_start_io() method will allocate an IO | ||
491 | * tag if this method is not utilized and the tag is not supplied to the IO | ||
492 | * construct routine. Direct allocation of IO tags may provide additional | ||
493 | * performance improvements in environments capable of supporting this usage | ||
494 | * model. Additionally, direct allocation of IO tags also provides | ||
495 | * additional flexibility to the SCI Core user. Specifically, the user may | ||
496 | * retain IO tags across the lives of multiple IO requests. | ||
497 | * @controller: the handle to the controller object for which to allocate the | ||
498 | * tag. | ||
499 | * | ||
500 | * IO tags are a protected resource. It is incumbent upon the SCI Core user to | ||
501 | * ensure that each of the methods that may allocate or free available IO tags | ||
502 | * are handled in a mutually exclusive manner. This method is one of said | ||
503 | * methods requiring proper critical code section protection (e.g. semaphore, | ||
504 | * spin-lock, etc.). An unsigned integer representing an available IO tag. | ||
505 | * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no | ||
506 | * currently available tags to be allocated. All return other values indicate a | ||
507 | * legitimate tag. | ||
508 | */ | ||
509 | u16 scic_controller_allocate_io_tag( | ||
510 | struct scic_sds_controller *controller); | ||
511 | |||
512 | /** | ||
513 | * scic_controller_free_io_tag() - This method will free an IO tag to the pool | ||
514 | * of free IO tags. This method provides the SCI Core user more flexibility | ||
515 | * with regards to IO tags. The user may desire to keep an IO tag after an | ||
516 | * IO request has completed, because they plan on re-using the tag for a | ||
517 | * subsequent IO request. This method is only legal if the tag was | ||
518 | * allocated via scic_controller_allocate_io_tag(). | ||
519 | * @controller: This parameter specifies the handle to the controller object | ||
520 | * for which to free/return the tag. | ||
521 | * @io_tag: This parameter represents the tag to be freed to the pool of | ||
522 | * available tags. | ||
523 | * | ||
524 | * - IO tags are a protected resource. It is incumbent upon the SCI Core user | ||
525 | * to ensure that each of the methods that may allocate or free available IO | ||
526 | * tags are handled in a mutually exclusive manner. This method is one of said | ||
527 | * methods requiring proper critical code section protection (e.g. semaphore, | ||
528 | * spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI | ||
529 | * Core user, using the scic_controller_allocate_io_tag() method, then it is | ||
530 | * the responsibility of the caller to invoke this method to free the tag. This | ||
531 | * method returns an indication of whether the tag was successfully put back | ||
532 | * (freed) to the pool of available tags. SCI_SUCCESS This return value | ||
533 | * indicates the tag was successfully placed into the pool of available IO | ||
534 | * tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag | ||
535 | * is not a valid IO tag value. | ||
536 | */ | ||
537 | enum sci_status scic_controller_free_io_tag( | ||
538 | struct scic_sds_controller *controller, | ||
539 | u16 io_tag); | ||
540 | |||
541 | |||
542 | |||
543 | |||
544 | /** | ||
545 | * scic_controller_set_mode() - This method allows the user to configure the | ||
546 | * SCI core into either a performance mode or a memory savings mode. | ||
547 | * @controller: This parameter represents the handle to the controller object | ||
548 | * for which to update the operating mode. | ||
549 | * @mode: This parameter specifies the new mode for the controller. | ||
550 | * | ||
551 | * Indicate if the user successfully change the operating mode of the | ||
552 | * controller. SCI_SUCCESS The user successfully updated the mode. | ||
553 | */ | ||
554 | enum sci_status scic_controller_set_mode( | ||
555 | struct scic_sds_controller *controller, | ||
556 | enum sci_controller_mode mode); | ||
557 | |||
558 | |||
559 | /** | ||
560 | * scic_controller_set_interrupt_coalescence() - This method allows the user to | ||
561 | * configure the interrupt coalescence. | ||
562 | * @controller: This parameter represents the handle to the controller object | ||
563 | * for which its interrupt coalesce register is overridden. | ||
564 | * @coalesce_number: Used to control the number of entries in the Completion | ||
565 | * Queue before an interrupt is generated. If the number of entries exceed | ||
566 | * this number, an interrupt will be generated. The valid range of the input | ||
567 | * is [0, 256]. A setting of 0 results in coalescing being disabled. | ||
568 | * @coalesce_timeout: Timeout value in microseconds. The valid range of the | ||
569 | * input is [0, 2700000] . A setting of 0 is allowed and results in no | ||
570 | * interrupt coalescing timeout. | ||
571 | * | ||
572 | * Indicate if the user successfully set the interrupt coalesce parameters. | ||
573 | * SCI_SUCCESS The user successfully updated the interrutp coalescence. | ||
574 | * SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range. | ||
575 | */ | ||
576 | enum sci_status scic_controller_set_interrupt_coalescence( | ||
577 | struct scic_sds_controller *controller, | ||
578 | u32 coalesce_number, | ||
579 | u32 coalesce_timeout); | ||
580 | |||
581 | struct device; | ||
582 | struct scic_sds_controller *scic_controller_alloc(struct device *dev); | ||
583 | |||
584 | |||
585 | #endif /* _SCIC_CONTROLLER_H_ */ | ||
586 | |||
diff --git a/drivers/scsi/isci/core/scic_io_request.h b/drivers/scsi/isci/core/scic_io_request.h new file mode 100644 index 000000000000..7378f335066c --- /dev/null +++ b/drivers/scsi/isci/core/scic_io_request.h | |||
@@ -0,0 +1,512 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_IO_REQUEST_H_ | ||
57 | #define _SCIC_IO_REQUEST_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures and interface methods that can be | ||
61 | * referenced and used by the SCI user for the SCI IO request object. | ||
62 | * | ||
63 | * Determine the failure situations and return values. | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_status.h" | ||
69 | #include "intel_sas.h" | ||
70 | |||
71 | struct scic_sds_request; | ||
72 | struct scic_sds_remote_device; | ||
73 | struct scic_sds_controller; | ||
74 | |||
75 | /** | ||
76 | * struct scic_io_parameters - This structure contains additional optional | ||
77 | * parameters for SSP IO requests. These parameters are utilized with the | ||
78 | * scic_io_request_construct_advanced_ssp() method. | ||
79 | * | ||
80 | * Add Block-guard/DIF, TLR | ||
81 | */ | ||
82 | struct scic_io_parameters { | ||
83 | /** | ||
84 | * This sub-structure contains SCSI specific features (for use with SSP | ||
85 | * IO requests). | ||
86 | */ | ||
87 | struct { | ||
88 | /** | ||
89 | * Data Integrity Format (DIF) is also known as protection information | ||
90 | * or block-guard. This sub-structure contains DIF specific feature | ||
91 | * information for SSP IO requests. | ||
92 | */ | ||
93 | struct { | ||
94 | void *placeholder; | ||
95 | } dif; | ||
96 | |||
97 | /** | ||
98 | * Transport Layer Retries (TLR) is an SSP protocol specific feature. | ||
99 | * This sub-structure contains Transport Layer Retries (TLR) specific | ||
100 | * feature information for SSP IO requests. | ||
101 | */ | ||
102 | struct { | ||
103 | void *placeholder; | ||
104 | } tlr; | ||
105 | |||
106 | } scsi; | ||
107 | |||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * struct scic_passthru_request_callbacks - This structure contains the pointer | ||
112 | * to the callback functions for constructing the passthrough request common | ||
113 | * to SSP, SMP and STP. This structure must be set by the win sci layer | ||
114 | * before the passthrough build is called | ||
115 | * | ||
116 | * | ||
117 | */ | ||
118 | struct scic_passthru_request_callbacks { | ||
119 | /** | ||
120 | * Function pointer to get the phy identifier for passthrough request. | ||
121 | */ | ||
122 | u32 (*scic_cb_passthru_get_phy_identifier)(void *, u8 *); | ||
123 | /** | ||
124 | * Function pointer to get the port identifier for passthrough request. | ||
125 | */ | ||
126 | u32 (*scic_cb_passthru_get_port_identifier)(void *, u8 *); | ||
127 | /** | ||
128 | * Function pointer to get the connection rate for passthrough request. | ||
129 | */ | ||
130 | u32 (*scic_cb_passthru_get_connection_rate)(void *, void *); | ||
131 | /** | ||
132 | * Function pointer to get the destination sas address for passthrough request. | ||
133 | */ | ||
134 | void (*scic_cb_passthru_get_destination_sas_address)(void *, u8 **); | ||
135 | /** | ||
136 | * Function pointer to get the transfer length for passthrough request. | ||
137 | */ | ||
138 | u32 (*scic_cb_passthru_get_transfer_length)(void *); | ||
139 | /** | ||
140 | * Function pointer to get the data direction for passthrough request. | ||
141 | */ | ||
142 | u32 (*scic_cb_passthru_get_data_direction)(void *); | ||
143 | |||
144 | }; | ||
145 | |||
146 | /** | ||
147 | * struct scic_ssp_passthru_request_callbacks - This structure contains the | ||
148 | * pointer to the callback functions for constructing the passthrough | ||
149 | * request specific to SSP. This structure must be set by the win sci layer | ||
150 | * before the passthrough build is called | ||
151 | * | ||
152 | * | ||
153 | */ | ||
154 | struct scic_ssp_passthru_request_callbacks { | ||
155 | /** | ||
156 | * Common callbacks for all Passthru requests | ||
157 | */ | ||
158 | struct scic_passthru_request_callbacks common_callbacks; | ||
159 | /** | ||
160 | * Function pointer to get the lun for passthrough request. | ||
161 | */ | ||
162 | void (*scic_cb_ssp_passthru_get_lun)(void *, u8 **); | ||
163 | /** | ||
164 | * Function pointer to get the cdb | ||
165 | */ | ||
166 | void (*scic_cb_ssp_passthru_get_cdb)(void *, u32 *, u8 **, u32 *, u8 **); | ||
167 | /** | ||
168 | * Function pointer to get the task attribute for passthrough request. | ||
169 | */ | ||
170 | u32 (*scic_cb_ssp_passthru_get_task_attribute)(void *); | ||
171 | }; | ||
172 | |||
173 | /** | ||
174 | * struct scic_stp_passthru_request_callbacks - This structure contains the | ||
175 | * pointer to the callback functions for constructing the passthrough | ||
176 | * request specific to STP. This structure must be set by the win sci layer | ||
177 | * before the passthrough build is called | ||
178 | * | ||
179 | * | ||
180 | */ | ||
181 | struct scic_stp_passthru_request_callbacks { | ||
182 | /** | ||
183 | * Common callbacks for all Passthru requests | ||
184 | */ | ||
185 | struct scic_passthru_request_callbacks common_callbacks; | ||
186 | /** | ||
187 | * Function pointer to get the protocol for passthrough request. | ||
188 | */ | ||
189 | u8 (*scic_cb_stp_passthru_get_protocol)(void *); | ||
190 | /** | ||
191 | * Function pointer to get the resgister fis | ||
192 | */ | ||
193 | void (*scic_cb_stp_passthru_get_register_fis)(void *, u8 **); | ||
194 | /** | ||
195 | * Function pointer to get the MULTIPLE_COUNT (bits 5,6,7 in Byte 1 in the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) | ||
196 | */ | ||
197 | u8 (*scic_cb_stp_passthru_get_multiplecount)(void *); | ||
198 | /** | ||
199 | * Function pointer to get the EXTEND (bit 0 in Byte 1 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) | ||
200 | */ | ||
201 | u8 (*scic_cb_stp_passthru_get_extend)(void *); | ||
202 | /** | ||
203 | * Function pointer to get the CK_COND (bit 5 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) | ||
204 | */ | ||
205 | u8 (*scic_cb_stp_passthru_get_ckcond)(void *); | ||
206 | /** | ||
207 | * Function pointer to get the T_DIR (bit 3 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) | ||
208 | */ | ||
209 | u8 (*scic_cb_stp_passthru_get_tdir)(void *); | ||
210 | /** | ||
211 | * Function pointer to get the BYTE_BLOCK (bit 2 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) | ||
212 | */ | ||
213 | u8 (*scic_cb_stp_passthru_get_byteblock)(void *); | ||
214 | /** | ||
215 | * Function pointer to get the T_LENGTH (bits 0,1 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85)) | ||
216 | */ | ||
217 | u8 (*scic_cb_stp_passthru_get_tlength)(void *); | ||
218 | |||
219 | }; | ||
220 | |||
221 | /** | ||
222 | * struct scic_smp_passthru_request_callbacks - This structure contains the | ||
223 | * pointer to the callback functions for constructing the passthrough | ||
224 | * request specific to SMP. This structure must be set by the win sci layer | ||
225 | * before the passthrough build is called | ||
226 | * | ||
227 | * | ||
228 | */ | ||
229 | struct scic_smp_passthru_request_callbacks { | ||
230 | /** | ||
231 | * Common callbacks for all Passthru requests | ||
232 | */ | ||
233 | struct scic_passthru_request_callbacks common_callbacks; | ||
234 | |||
235 | /** | ||
236 | * Function pointer to get the length of the smp request and its length | ||
237 | */ | ||
238 | u32 (*scic_cb_smp_passthru_get_request)(void *, u8 **); | ||
239 | /** | ||
240 | * Function pointer to get the frame type of the smp request | ||
241 | */ | ||
242 | u8 (*scic_cb_smp_passthru_get_frame_type)(void *); | ||
243 | /** | ||
244 | * Function pointer to get the function in the the smp request | ||
245 | */ | ||
246 | u8 (*scic_cb_smp_passthru_get_function)(void *); | ||
247 | |||
248 | /** | ||
249 | * Function pointer to get the "allocated response length" in the the smp request | ||
250 | */ | ||
251 | u8 (*scic_cb_smp_passthru_get_allocated_response_length)(void *); | ||
252 | |||
253 | }; | ||
254 | |||
255 | /** | ||
256 | * This enumeration specifies the transport protocol utilized for the request. | ||
257 | * | ||
258 | * | ||
259 | */ | ||
260 | typedef enum { | ||
261 | /** | ||
262 | * This enumeration constant indicates that no protocol has yet been | ||
263 | * set. | ||
264 | */ | ||
265 | SCIC_NO_PROTOCOL, | ||
266 | |||
267 | /** | ||
268 | * This enumeration constant indicates that the protocol utilized | ||
269 | * is the Serial Management Protocol. | ||
270 | */ | ||
271 | SCIC_SMP_PROTOCOL, | ||
272 | |||
273 | /** | ||
274 | * This enumeration constant indicates that the protocol utilized | ||
275 | * is the Serial SCSI Protocol. | ||
276 | */ | ||
277 | SCIC_SSP_PROTOCOL, | ||
278 | |||
279 | /** | ||
280 | * This enumeration constant indicates that the protocol utilized | ||
281 | * is the Serial-ATA Tunneling Protocol. | ||
282 | */ | ||
283 | SCIC_STP_PROTOCOL | ||
284 | |||
285 | } SCIC_TRANSPORT_PROTOCOL; | ||
286 | |||
287 | |||
288 | /** | ||
289 | * scic_io_request_get_object_size() - This method simply returns the size | ||
290 | * required to build an SCI based IO request object. | ||
291 | * | ||
292 | * Return the size of the SCI IO request object. | ||
293 | */ | ||
294 | u32 scic_io_request_get_object_size( | ||
295 | void); | ||
296 | |||
297 | /** | ||
298 | * scic_io_request_construct() - This method is called by the SCI user to | ||
299 | * construct all SCI Core IO requests. Memory initialization and | ||
300 | * functionality common to all IO request types is performed in this method. | ||
301 | * @scic_controller: the handle to the core controller object for which to | ||
302 | * build an IO request. | ||
303 | * @scic_remote_device: the handle to the core remote device object for which | ||
304 | * to build an IO request. | ||
305 | * @io_tag: This parameter specifies the IO tag to be associated with this | ||
306 | * request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the | ||
307 | * request is built internally. The request will be copied into the actual | ||
308 | * controller request memory when the IO tag is allocated internally during | ||
309 | * the scic_controller_start_io() method. | ||
310 | * @user_io_request_object: This parameter specifies the user IO request to be | ||
311 | * utilized during IO construction. This IO pointer will become the | ||
312 | * associated object for the core IO request object. | ||
313 | * @scic_io_request_memory: This parameter specifies the memory location to be | ||
314 | * utilized when building the core request. | ||
315 | * @new_scic_io_request_handle: This parameter specifies a pointer to the | ||
316 | * handle the core will expect in further interactions with the core IO | ||
317 | * request object. | ||
318 | * | ||
319 | * The SCI core implementation will create an association between the user IO | ||
320 | * request object and the core IO request object. Indicate if the controller | ||
321 | * successfully built the IO request. SCI_SUCCESS This value is returned if the | ||
322 | * IO request was successfully built. | ||
323 | */ | ||
324 | enum sci_status scic_io_request_construct( | ||
325 | struct scic_sds_controller *scic_controller, | ||
326 | struct scic_sds_remote_device *scic_remote_device, | ||
327 | u16 io_tag, | ||
328 | void *user_io_request_object, | ||
329 | void *scic_io_request_memory, | ||
330 | struct scic_sds_request **new_scic_io_request_handle); | ||
331 | |||
332 | /** | ||
333 | * scic_io_request_construct_basic_ssp() - This method is called by the SCI | ||
334 | * user to build an SSP IO request. | ||
335 | * @scic_io_request: This parameter specifies the handle to the io request | ||
336 | * object to be built. | ||
337 | * | ||
338 | * - The user must have previously called scic_io_request_construct() on the | ||
339 | * supplied IO request. Indicate if the controller successfully built the IO | ||
340 | * request. SCI_SUCCESS This value is returned if the IO request was | ||
341 | * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned | ||
342 | * if the remote_device does not support the SSP protocol. | ||
343 | * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not | ||
344 | * properly set the association between the SCIC IO request and the user's IO | ||
345 | * request. Please refer to the sci_object_set_association() routine for more | ||
346 | * information. | ||
347 | */ | ||
348 | enum sci_status scic_io_request_construct_basic_ssp( | ||
349 | struct scic_sds_request *scic_io_request); | ||
350 | |||
351 | |||
352 | |||
353 | |||
354 | |||
355 | /** | ||
356 | * scic_io_request_construct_basic_sata() - This method is called by the SCI | ||
357 | * Core user to build an STP IO request. | ||
358 | * @scic_io_request: This parameter specifies the handle to the io request | ||
359 | * object to be built. | ||
360 | * | ||
361 | * - The user must have previously called scic_io_request_construct() on the | ||
362 | * supplied IO request. Indicate if the controller successfully built the IO | ||
363 | * request. SCI_SUCCESS This value is returned if the IO request was | ||
364 | * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned | ||
365 | * if the remote_device does not support the STP protocol. | ||
366 | * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not | ||
367 | * properly set the association between the SCIC IO request and the user's IO | ||
368 | * request. Please refer to the sci_object_set_association() routine for more | ||
369 | * information. | ||
370 | */ | ||
371 | enum sci_status scic_io_request_construct_basic_sata( | ||
372 | struct scic_sds_request *scic_io_request); | ||
373 | |||
374 | |||
375 | |||
376 | |||
377 | /** | ||
378 | * scic_io_request_construct_smp() - This method is called by the SCI user to | ||
379 | * build an SMP IO request. | ||
380 | * @scic_io_request: This parameter specifies the handle to the io request | ||
381 | * object to be built. | ||
382 | * | ||
383 | * - The user must have previously called scic_io_request_construct() on the | ||
384 | * supplied IO request. Indicate if the controller successfully built the IO | ||
385 | * request. SCI_SUCCESS This value is returned if the IO request was | ||
386 | * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned | ||
387 | * if the remote_device does not support the SMP protocol. | ||
388 | * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not | ||
389 | * properly set the association between the SCIC IO request and the user's IO | ||
390 | * request. Please refer to the sci_object_set_association() routine for more | ||
391 | * information. | ||
392 | */ | ||
393 | enum sci_status scic_io_request_construct_smp( | ||
394 | struct scic_sds_request *scic_io_request); | ||
395 | |||
396 | |||
397 | |||
398 | /** | ||
399 | * scic_request_get_controller_status() - This method returns the controller | ||
400 | * specific IO/Task request status. These status values are unique to the | ||
401 | * specific controller being managed by the SCIC. | ||
402 | * @io_request: the handle to the IO or task management request object for | ||
403 | * which to retrieve the status. | ||
404 | * | ||
405 | * This method returns a value indicating the controller specific request | ||
406 | * status. | ||
407 | */ | ||
408 | u32 scic_request_get_controller_status( | ||
409 | struct scic_sds_request *io_request); | ||
410 | |||
411 | |||
412 | |||
413 | /** | ||
414 | * scic_io_request_get_command_iu_address() - This method will return the | ||
415 | * address to the command information unit. | ||
416 | * @scic_io_request: This parameter specifies the handle to the io request | ||
417 | * object to be built. | ||
418 | * | ||
419 | * The address of the SSP/SMP command information unit. | ||
420 | */ | ||
421 | void *scic_io_request_get_command_iu_address( | ||
422 | struct scic_sds_request *scic_io_request); | ||
423 | |||
424 | /** | ||
425 | * scic_io_request_get_response_iu_address() - This method will return the | ||
426 | * address to the response information unit. For an SSP request this buffer | ||
427 | * is only valid if the IO request is completed with the status | ||
428 | * SCI_FAILURE_IO_RESPONSE_VALID. | ||
429 | * @scic_io_request: This parameter specifies the handle to the io request | ||
430 | * object to be built. | ||
431 | * | ||
432 | * The address of the SSP/SMP response information unit. | ||
433 | */ | ||
434 | void *scic_io_request_get_response_iu_address( | ||
435 | struct scic_sds_request *scic_io_request); | ||
436 | |||
437 | /** | ||
438 | * scic_io_request_get_io_tag() - This method will return the IO tag utilized | ||
439 | * by the IO request. | ||
440 | * @scic_io_request: This parameter specifies the handle to the io request | ||
441 | * object for which to return the IO tag. | ||
442 | * | ||
443 | * An unsigned integer representing the IO tag being utilized. | ||
444 | * SCI_CONTROLLER_INVALID_IO_TAG This value is returned if the IO does not | ||
445 | * currently have an IO tag allocated to it. All return other values indicate a | ||
446 | * legitimate tag. | ||
447 | */ | ||
448 | u16 scic_io_request_get_io_tag( | ||
449 | struct scic_sds_request *scic_io_request); | ||
450 | |||
451 | |||
452 | /** | ||
453 | * scic_stp_io_request_set_ncq_tag() - This method will assign an NCQ tag to | ||
454 | * the io request object. The caller of this function must make sure that | ||
455 | * only valid NCQ tags are assigned to the io request object. | ||
456 | * @scic_io_request: This parameter specifies the handle to the io request | ||
457 | * object to which to assign the ncq tag. | ||
458 | * @ncq_tag: This parameter specifies the NCQ tag to be utilized for the | ||
459 | * supplied core IO request. It is up to the user to make sure that this is | ||
460 | * a valid NCQ tag. | ||
461 | * | ||
462 | * none This function is only valid for SATA NCQ requests. | ||
463 | */ | ||
464 | void scic_stp_io_request_set_ncq_tag( | ||
465 | struct scic_sds_request *scic_io_request, | ||
466 | u16 ncq_tag); | ||
467 | |||
468 | /** | ||
469 | * scic_stp_io_request_get_h2d_reg_address() - This method will return the | ||
470 | * address of the host to device register fis region for the io request | ||
471 | * object. | ||
472 | * @scic_io_request: This parameter specifies the handle to the io request | ||
473 | * object from which to get the host to device register fis buffer. | ||
474 | * | ||
475 | * The address of the host to device register fis buffer in the io request | ||
476 | * object. This function is only valid for SATA requests. | ||
477 | */ | ||
478 | void *scic_stp_io_request_get_h2d_reg_address( | ||
479 | struct scic_sds_request *scic_io_request); | ||
480 | |||
481 | /** | ||
482 | * scic_stp_io_request_get_d2h_reg_address() - This method will return the | ||
483 | * address of the device to host register fis region for the io request | ||
484 | * object. | ||
485 | * @scic_io_request: This parameter specifies teh handle to the io request | ||
486 | * object from which to get the device to host register fis buffer. | ||
487 | * | ||
488 | * The address fo the device to host register fis ending the io request. This | ||
489 | * function is only valid for SATA requests. | ||
490 | */ | ||
491 | void *scic_stp_io_request_get_d2h_reg_address( | ||
492 | struct scic_sds_request *scic_io_request); | ||
493 | |||
494 | |||
495 | /** | ||
496 | * scic_io_request_get_number_of_bytes_transferred() - This method will return | ||
497 | * the number of bytes transferred from the SCU | ||
498 | * @scic_io_request: This parameter specifies the handle to the io request | ||
499 | * whose data length was not eqaul to the data length specified in the | ||
500 | * request. When the driver gets an early io completion status from the | ||
501 | * hardware, this routine should be called to get the actual number of bytes | ||
502 | * transferred | ||
503 | * | ||
504 | * The return is the number of bytes transferred when the data legth is not | ||
505 | * equal to the specified length in the io request | ||
506 | */ | ||
507 | u32 scic_io_request_get_number_of_bytes_transferred( | ||
508 | struct scic_sds_request *scic_io_request); | ||
509 | |||
510 | |||
511 | #endif /* _SCIC_IO_REQUEST_H_ */ | ||
512 | |||
diff --git a/drivers/scsi/isci/core/scic_phy.h b/drivers/scsi/isci/core/scic_phy.h new file mode 100644 index 000000000000..25a6140fa9e4 --- /dev/null +++ b/drivers/scsi/isci/core/scic_phy.h | |||
@@ -0,0 +1,303 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_PHY_H_ | ||
57 | #define _SCIC_PHY_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the interface methods that can be called by an | ||
61 | * SCIC user on a phy (SAS or SATA) object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_status.h" | ||
69 | |||
70 | #include "intel_sata.h" | ||
71 | #include "intel_sas.h" | ||
72 | |||
73 | struct scic_sds_phy; | ||
74 | struct scic_sds_port; | ||
75 | |||
76 | /** | ||
77 | * struct scic_phy_properties - This structure defines the properties common to | ||
78 | * all phys that can be retrieved. | ||
79 | * | ||
80 | * | ||
81 | */ | ||
82 | struct scic_phy_properties { | ||
83 | /** | ||
84 | * This field specifies the port that currently contains the | ||
85 | * supplied phy. This field may be set to SCI_INVALID_HANDLE | ||
86 | * if the phy is not currently contained in a port. | ||
87 | */ | ||
88 | struct scic_sds_port *owning_port; | ||
89 | |||
90 | /** | ||
91 | * This field specifies the link rate at which the phy is | ||
92 | * currently operating. | ||
93 | */ | ||
94 | enum sci_sas_link_rate negotiated_link_rate; | ||
95 | |||
96 | /** | ||
97 | * This field indicates the protocols supported by the phy. | ||
98 | */ | ||
99 | struct sci_sas_identify_address_frame_protocols protocols; | ||
100 | |||
101 | /** | ||
102 | * This field specifies the index of the phy in relation to other | ||
103 | * phys within the controller. This index is zero relative. | ||
104 | */ | ||
105 | u8 index; | ||
106 | |||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * struct scic_sas_phy_properties - This structure defines the properties, | ||
111 | * specific to a SAS phy, that can be retrieved. | ||
112 | * | ||
113 | * | ||
114 | */ | ||
115 | struct scic_sas_phy_properties { | ||
116 | /** | ||
117 | * This field delineates the Identify Address Frame received | ||
118 | * from the remote end point. | ||
119 | */ | ||
120 | struct sci_sas_identify_address_frame received_iaf; | ||
121 | |||
122 | /** | ||
123 | * This field delineates the Phy capabilities structure received | ||
124 | * from the remote end point. | ||
125 | */ | ||
126 | struct sas_capabilities received_capabilities; | ||
127 | |||
128 | }; | ||
129 | |||
130 | /** | ||
131 | * struct scic_sata_phy_properties - This structure defines the properties, | ||
132 | * specific to a SATA phy, that can be retrieved. | ||
133 | * | ||
134 | * | ||
135 | */ | ||
136 | struct scic_sata_phy_properties { | ||
137 | /** | ||
138 | * This field delineates the signature FIS received from the | ||
139 | * attached target. | ||
140 | */ | ||
141 | struct sata_fis_reg_d2h signature_fis; | ||
142 | |||
143 | /** | ||
144 | * This field specifies to the user if a port selector is connected | ||
145 | * on the specified phy. | ||
146 | */ | ||
147 | bool is_port_selector_present; | ||
148 | |||
149 | }; | ||
150 | |||
151 | /** | ||
152 | * enum scic_phy_counter_id - This enumeration depicts the various pieces of | ||
153 | * optional information that can be retrieved for a specific phy. | ||
154 | * | ||
155 | * | ||
156 | */ | ||
157 | enum scic_phy_counter_id { | ||
158 | /** | ||
159 | * This PHY information field tracks the number of frames received. | ||
160 | */ | ||
161 | SCIC_PHY_COUNTER_RECEIVED_FRAME, | ||
162 | |||
163 | /** | ||
164 | * This PHY information field tracks the number of frames transmitted. | ||
165 | */ | ||
166 | SCIC_PHY_COUNTER_TRANSMITTED_FRAME, | ||
167 | |||
168 | /** | ||
169 | * This PHY information field tracks the number of DWORDs received. | ||
170 | */ | ||
171 | SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD, | ||
172 | |||
173 | /** | ||
174 | * This PHY information field tracks the number of DWORDs transmitted. | ||
175 | */ | ||
176 | SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD, | ||
177 | |||
178 | /** | ||
179 | * This PHY information field tracks the number of times DWORD | ||
180 | * synchronization was lost. | ||
181 | */ | ||
182 | SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR, | ||
183 | |||
184 | /** | ||
185 | * This PHY information field tracks the number of received DWORDs with | ||
186 | * running disparity errors. | ||
187 | */ | ||
188 | SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR, | ||
189 | |||
190 | /** | ||
191 | * This PHY information field tracks the number of received frames with a | ||
192 | * CRC error (not including short or truncated frames). | ||
193 | */ | ||
194 | SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR, | ||
195 | |||
196 | /** | ||
197 | * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) | ||
198 | * primitives received. | ||
199 | */ | ||
200 | SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT, | ||
201 | |||
202 | /** | ||
203 | * This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT) | ||
204 | * primitives transmitted. | ||
205 | */ | ||
206 | SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT, | ||
207 | |||
208 | /** | ||
209 | * This PHY information field tracks the number of times the inactivity | ||
210 | * timer for connections on the phy has been utilized. | ||
211 | */ | ||
212 | SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED, | ||
213 | |||
214 | /** | ||
215 | * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) | ||
216 | * primitives received. | ||
217 | */ | ||
218 | SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT, | ||
219 | |||
220 | /** | ||
221 | * This PHY information field tracks the number of DONE (CREDIT TIMEOUT) | ||
222 | * primitives transmitted. | ||
223 | */ | ||
224 | SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT, | ||
225 | |||
226 | /** | ||
227 | * This PHY information field tracks the number of CREDIT BLOCKED | ||
228 | * primitives received. | ||
229 | * @note Depending on remote device implementation, credit blocks | ||
230 | * may occur regularly. | ||
231 | */ | ||
232 | SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED, | ||
233 | |||
234 | /** | ||
235 | * This PHY information field contains the number of short frames | ||
236 | * received. A short frame is simply a frame smaller then what is | ||
237 | * allowed by either the SAS or SATA specification. | ||
238 | */ | ||
239 | SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME, | ||
240 | |||
241 | /** | ||
242 | * This PHY information field contains the number of frames received after | ||
243 | * credit has been exhausted. | ||
244 | */ | ||
245 | SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT, | ||
246 | |||
247 | /** | ||
248 | * This PHY information field contains the number of frames received after | ||
249 | * a DONE has been received. | ||
250 | */ | ||
251 | SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE, | ||
252 | |||
253 | /** | ||
254 | * This PHY information field contains the number of times the phy | ||
255 | * failed to achieve DWORD synchronization during speed negotiation. | ||
256 | */ | ||
257 | SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR | ||
258 | }; | ||
259 | |||
260 | |||
261 | /** | ||
262 | * scic_sas_phy_get_properties() - This method will enable the user to retrieve | ||
263 | * information specific to a SAS phy, such as: the received identify address | ||
264 | * frame, received phy capabilities, etc. | ||
265 | * @phy: this parameter specifies the phy for which to retrieve properties. | ||
266 | * @properties: This parameter specifies the properties structure into which to | ||
267 | * copy the requested information. | ||
268 | * | ||
269 | * This method returns an indication as to whether the SAS phy properties were | ||
270 | * successfully retrieved. SCI_SUCCESS This value is returned if the SAS | ||
271 | * properties are successfully retrieved. SCI_FAILURE This value is returned if | ||
272 | * the SAS properties are not successfully retrieved (e.g. It's not a SAS Phy). | ||
273 | */ | ||
274 | enum sci_status scic_sas_phy_get_properties( | ||
275 | struct scic_sds_phy *phy, | ||
276 | struct scic_sas_phy_properties *properties); | ||
277 | |||
278 | /** | ||
279 | * scic_sata_phy_get_properties() - This method will enable the user to | ||
280 | * retrieve information specific to a SATA phy, such as: the received | ||
281 | * signature FIS, if a port selector is present, etc. | ||
282 | * @phy: this parameter specifies the phy for which to retrieve properties. | ||
283 | * @properties: This parameter specifies the properties structure into which to | ||
284 | * copy the requested information. | ||
285 | * | ||
286 | * This method returns an indication as to whether the SATA phy properties were | ||
287 | * successfully retrieved. SCI_SUCCESS This value is returned if the SATA | ||
288 | * properties are successfully retrieved. SCI_FAILURE This value is returned if | ||
289 | * the SATA properties are not successfully retrieved (e.g. It's not a SATA | ||
290 | * Phy). | ||
291 | */ | ||
292 | enum sci_status scic_sata_phy_get_properties( | ||
293 | struct scic_sds_phy *phy, | ||
294 | struct scic_sata_phy_properties *properties); | ||
295 | |||
296 | |||
297 | |||
298 | |||
299 | |||
300 | |||
301 | |||
302 | #endif /* _SCIC_PHY_H_ */ | ||
303 | |||
diff --git a/drivers/scsi/isci/core/scic_port.h b/drivers/scsi/isci/core/scic_port.h new file mode 100644 index 000000000000..34d22c04aa56 --- /dev/null +++ b/drivers/scsi/isci/core/scic_port.h | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_PORT_H_ | ||
57 | #define _SCIC_PORT_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the interface methods that can be called by an SCI | ||
61 | * Core user on a SAS or SATA port. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_status.h" | ||
69 | #include "intel_sas.h" | ||
70 | |||
71 | struct scic_sds_port; | ||
72 | |||
73 | enum SCIC_PORT_NOT_READY_REASON_CODE { | ||
74 | SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS, | ||
75 | SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED, | ||
76 | SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION, | ||
77 | SCIC_PORT_NOT_READY_RECONFIGURING, | ||
78 | |||
79 | SCIC_PORT_NOT_READY_REASON_CODE_MAX | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * struct scic_port_end_point_properties - This structure defines the | ||
84 | * properties that can be retrieved for each end-point local or remote | ||
85 | * (attached) port in the controller. | ||
86 | * | ||
87 | * | ||
88 | */ | ||
89 | struct scic_port_end_point_properties { | ||
90 | /** | ||
91 | * This field indicates the SAS address for the associated end | ||
92 | * point in the port. | ||
93 | */ | ||
94 | struct sci_sas_address sas_address; | ||
95 | |||
96 | /** | ||
97 | * This field indicates the protocols supported by the associated | ||
98 | * end-point in the port. | ||
99 | */ | ||
100 | struct sci_sas_identify_address_frame_protocols protocols; | ||
101 | |||
102 | }; | ||
103 | |||
104 | /** | ||
105 | * struct scic_port_properties - This structure defines the properties that can | ||
106 | * be retrieved for each port in the controller. | ||
107 | * | ||
108 | * | ||
109 | */ | ||
110 | struct scic_port_properties { | ||
111 | /** | ||
112 | * This field specifies the logical index of the port (0 relative). | ||
113 | */ | ||
114 | u32 index; | ||
115 | |||
116 | /** | ||
117 | * This field indicates the local end-point properties for port. | ||
118 | */ | ||
119 | struct scic_port_end_point_properties local; | ||
120 | |||
121 | /** | ||
122 | * This field indicates the remote (attached) end-point properties | ||
123 | * for the port. | ||
124 | */ | ||
125 | struct scic_port_end_point_properties remote; | ||
126 | |||
127 | /** | ||
128 | * This field specifies the phys contained inside the port. | ||
129 | */ | ||
130 | u32 phy_mask; | ||
131 | |||
132 | }; | ||
133 | |||
134 | /** | ||
135 | * scic_port_get_properties() - This method simply returns the properties | ||
136 | * regarding the port, such as: physical index, protocols, sas address, etc. | ||
137 | * @port: this parameter specifies the port for which to retrieve the physical | ||
138 | * index. | ||
139 | * @properties: This parameter specifies the properties structure into which to | ||
140 | * copy the requested information. | ||
141 | * | ||
142 | * Indicate if the user specified a valid port. SCI_SUCCESS This value is | ||
143 | * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This | ||
144 | * value is returned if the specified port is not valid. When this value is | ||
145 | * returned, no data is copied to the properties output parameter. | ||
146 | */ | ||
147 | enum sci_status scic_port_get_properties( | ||
148 | struct scic_sds_port *port, | ||
149 | struct scic_port_properties *properties); | ||
150 | |||
151 | |||
152 | |||
153 | /** | ||
154 | * scic_port_start() - This method will make the port ready for operation. | ||
155 | * Prior to calling the start method IO operation is not possible. | ||
156 | * @port: This parameter specifies the port to be started. | ||
157 | * | ||
158 | * Indicate if the port was successfully started. SCI_SUCCESS This value is | ||
159 | * returned if the port was successfully started. SCI_WARNING_ALREADY_IN_STATE | ||
160 | * This value is returned if the port is in the process of starting. | ||
161 | * SCI_FAILURE_INVALID_PORT This value is returned if the supplied port is not | ||
162 | * valid. SCI_FAILURE_INVALID_STATE This value is returned if a start operation | ||
163 | * can't be completed due to the state of port. | ||
164 | */ | ||
165 | enum sci_status scic_port_start( | ||
166 | struct scic_sds_port *port); | ||
167 | |||
168 | /** | ||
169 | * scic_port_stop() - This method will make the port no longer ready for | ||
170 | * operation. After invoking this method IO operation is not possible. | ||
171 | * @port: This parameter specifies the port to be stopped. | ||
172 | * | ||
173 | * Indicate if the port was successfully stopped. SCI_SUCCESS This value is | ||
174 | * returned if the port was successfully stopped. SCI_WARNING_ALREADY_IN_STATE | ||
175 | * This value is returned if the port is already stopped or in the process of | ||
176 | * stopping. SCI_FAILURE_INVALID_PORT This value is returned if the supplied | ||
177 | * port is not valid. SCI_FAILURE_INVALID_STATE This value is returned if a | ||
178 | * stop operation can't be completed due to the state of port. | ||
179 | */ | ||
180 | enum sci_status scic_port_stop( | ||
181 | struct scic_sds_port *port); | ||
182 | |||
183 | /** | ||
184 | * scic_port_hard_reset() - This method will request the SCI implementation to | ||
185 | * perform a HARD RESET on the SAS Port. If/When the HARD RESET completes | ||
186 | * the SCI user will be notified via an SCI OS callback indicating a direct | ||
187 | * attached device was found. | ||
188 | * @port: a handle corresponding to the SAS port to be hard reset. | ||
189 | * @reset_timeout: This parameter specifies the number of milliseconds in which | ||
190 | * the port reset operation should complete. | ||
191 | * | ||
192 | * The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for | ||
193 | * each phy in the SAS Port at completion of the hard reset sequence. Return a | ||
194 | * status indicating whether the hard reset started successfully. SCI_SUCCESS | ||
195 | * This value is returned if the hard reset operation started successfully. | ||
196 | */ | ||
197 | enum sci_status scic_port_hard_reset( | ||
198 | struct scic_sds_port *port, | ||
199 | u32 reset_timeout); | ||
200 | |||
201 | /** | ||
202 | * scic_port_enable_broadcast_change_notification() - This API method enables | ||
203 | * the broadcast change notification from underneath hardware. | ||
204 | * @port: The port upon which broadcast change notifications (BCN) are to be | ||
205 | * enabled. | ||
206 | * | ||
207 | */ | ||
208 | void scic_port_enable_broadcast_change_notification( | ||
209 | struct scic_sds_port *port); | ||
210 | |||
211 | |||
212 | #endif /* _SCIC_PORT_H_ */ | ||
213 | |||
diff --git a/drivers/scsi/isci/core/scic_remote_device.h b/drivers/scsi/isci/core/scic_remote_device.h new file mode 100644 index 000000000000..e8c04592763e --- /dev/null +++ b/drivers/scsi/isci/core/scic_remote_device.h | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_REMOTE_DEVICE_H_ | ||
57 | #define _SCIC_REMOTE_DEVICE_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the interface methods that can be called by an | ||
61 | * SCIC user on the device object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_status.h" | ||
69 | #include "intel_sas.h" | ||
70 | |||
71 | struct scic_sds_port; | ||
72 | struct scic_sds_remote_device; | ||
73 | |||
74 | /** | ||
75 | * | ||
76 | * | ||
77 | * | ||
78 | */ | ||
79 | enum scic_remote_device_not_ready_reason_code { | ||
80 | SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED, | ||
81 | SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED, | ||
82 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED, | ||
83 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED, | ||
84 | SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED, | ||
85 | |||
86 | SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX | ||
87 | |||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * scic_remote_device_get_object_size() - This method simply returns the | ||
92 | * maximum memory space needed to store a remote device object. | ||
93 | * | ||
94 | * a positive integer value indicating the size (in bytes) of the remote device | ||
95 | * object. | ||
96 | */ | ||
97 | u32 scic_remote_device_get_object_size( | ||
98 | void); | ||
99 | |||
100 | struct scic_sds_port; | ||
101 | struct scic_sds_remote_device; | ||
102 | /** | ||
103 | * scic_remote_device_construct() - This method will perform the construction | ||
104 | * common to all remote device objects. | ||
105 | * @sci_port: SAS/SATA port through which this device is accessed. | ||
106 | * @sci_dev: remote device to construct | ||
107 | * | ||
108 | * It isn't necessary to call scic_remote_device_destruct() for device objects | ||
109 | * that have only called this method for construction. Once subsequent | ||
110 | * construction methods have been invoked (e.g. | ||
111 | * scic_remote_device_da_construct()), then destruction should occur. none | ||
112 | */ | ||
113 | void scic_remote_device_construct(struct scic_sds_port *sci_port, | ||
114 | struct scic_sds_remote_device *sci_dev); | ||
115 | |||
116 | /** | ||
117 | * scic_remote_device_da_construct() - This method will construct a | ||
118 | * SCIC_REMOTE_DEVICE object for a direct attached (da) device. The | ||
119 | * information (e.g. IAF, Signature FIS, etc.) necessary to build the device | ||
120 | * is known to the SCI Core since it is contained in the scic_phy object. | ||
121 | * @remote_device: This parameter specifies the remote device to be destructed. | ||
122 | * | ||
123 | * The user must have previously called scic_remote_device_construct() Remote | ||
124 | * device objects are a limited resource. As such, they must be protected. | ||
125 | * Thus calls to construct and destruct are mutually exclusive and | ||
126 | * non-reentrant. Indicate if the remote device was successfully constructed. | ||
127 | * SCI_SUCCESS Returned if the device was successfully constructed. | ||
128 | * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been | ||
129 | * constructed. If it's an additional phy for the target, then call | ||
130 | * scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned | ||
131 | * if the supplied parameters necessitate creation of a remote device for which | ||
132 | * the protocol is not supported by the underlying controller hardware. | ||
133 | * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core | ||
134 | * controller associated with the supplied parameters is unable to support | ||
135 | * additional remote devices. | ||
136 | */ | ||
137 | enum sci_status scic_remote_device_da_construct( | ||
138 | struct scic_sds_remote_device *remote_device); | ||
139 | |||
140 | /** | ||
141 | * scic_remote_device_ea_construct() - This method will construct an | ||
142 | * SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an | ||
143 | * SMP Discover Response. | ||
144 | * @remote_device: This parameter specifies the remote device to be destructed. | ||
145 | * @discover_response: This parameter specifies the SMP Discovery Response to | ||
146 | * be used in device creation. | ||
147 | * | ||
148 | * The user must have previously called scic_remote_device_construct() Remote | ||
149 | * device objects are a limited resource. As such, they must be protected. | ||
150 | * Thus calls to construct and destruct are mutually exclusive and | ||
151 | * non-reentrant. Indicate if the remote device was successfully constructed. | ||
152 | * SCI_SUCCESS Returned if the device was successfully constructed. | ||
153 | * SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been | ||
154 | * constructed. If it's an additional phy for the target, then call | ||
155 | * scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned | ||
156 | * if the supplied parameters necessitate creation of a remote device for which | ||
157 | * the protocol is not supported by the underlying controller hardware. | ||
158 | * SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core | ||
159 | * controller associated with the supplied parameters is unable to support | ||
160 | * additional remote devices. | ||
161 | */ | ||
162 | enum sci_status scic_remote_device_ea_construct( | ||
163 | struct scic_sds_remote_device *remote_device, | ||
164 | struct smp_response_discover *discover_response); | ||
165 | |||
166 | /** | ||
167 | * scic_remote_device_destruct() - This method is utilized to free up a core's | ||
168 | * remote device object. | ||
169 | * @remote_device: This parameter specifies the remote device to be destructed. | ||
170 | * | ||
171 | * Remote device objects are a limited resource. As such, they must be | ||
172 | * protected. Thus calls to construct and destruct are mutually exclusive and | ||
173 | * non-reentrant. The return value shall indicate if the device was | ||
174 | * successfully destructed or if some failure occurred. enum sci_status This value | ||
175 | * is returned if the device is successfully destructed. | ||
176 | * SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied | ||
177 | * device isn't valid (e.g. it's already been destoryed, the handle isn't | ||
178 | * valid, etc.). | ||
179 | */ | ||
180 | enum sci_status scic_remote_device_destruct( | ||
181 | struct scic_sds_remote_device *remote_device); | ||
182 | |||
183 | |||
184 | |||
185 | |||
186 | |||
187 | /** | ||
188 | * scic_remote_device_start() - This method will start the supplied remote | ||
189 | * device. This method enables normal IO requests to flow through to the | ||
190 | * remote device. | ||
191 | * @remote_device: This parameter specifies the device to be started. | ||
192 | * @timeout: This parameter specifies the number of milliseconds in which the | ||
193 | * start operation should complete. | ||
194 | * | ||
195 | * An indication of whether the device was successfully started. SCI_SUCCESS | ||
196 | * This value is returned if the device was successfully started. | ||
197 | * SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start | ||
198 | * the device when there have been no phys added to it. | ||
199 | */ | ||
200 | enum sci_status scic_remote_device_start( | ||
201 | struct scic_sds_remote_device *remote_device, | ||
202 | u32 timeout); | ||
203 | |||
204 | /** | ||
205 | * scic_remote_device_stop() - This method will stop both transmission and | ||
206 | * reception of link activity for the supplied remote device. This method | ||
207 | * disables normal IO requests from flowing through to the remote device. | ||
208 | * @remote_device: This parameter specifies the device to be stopped. | ||
209 | * @timeout: This parameter specifies the number of milliseconds in which the | ||
210 | * stop operation should complete. | ||
211 | * | ||
212 | * An indication of whether the device was successfully stopped. SCI_SUCCESS | ||
213 | * This value is returned if the transmission and reception for the device was | ||
214 | * successfully stopped. | ||
215 | */ | ||
216 | enum sci_status scic_remote_device_stop( | ||
217 | struct scic_sds_remote_device *remote_device, | ||
218 | u32 timeout); | ||
219 | |||
220 | /** | ||
221 | * scic_remote_device_reset() - This method will reset the device making it | ||
222 | * ready for operation. This method must be called anytime the device is | ||
223 | * reset either through a SMP phy control or a port hard reset request. | ||
224 | * @remote_device: This parameter specifies the device to be reset. | ||
225 | * | ||
226 | * This method does not actually cause the device hardware to be reset. This | ||
227 | * method resets the software object so that it will be operational after a | ||
228 | * device hardware reset completes. An indication of whether the device reset | ||
229 | * was accepted. SCI_SUCCESS This value is returned if the device reset is | ||
230 | * started. | ||
231 | */ | ||
232 | enum sci_status scic_remote_device_reset( | ||
233 | struct scic_sds_remote_device *remote_device); | ||
234 | |||
235 | /** | ||
236 | * scic_remote_device_reset_complete() - This method informs the device object | ||
237 | * that the reset operation is complete and the device can resume operation | ||
238 | * again. | ||
239 | * @remote_device: This parameter specifies the device which is to be informed | ||
240 | * of the reset complete operation. | ||
241 | * | ||
242 | * An indication that the device is resuming operation. SCI_SUCCESS the device | ||
243 | * is resuming operation. | ||
244 | */ | ||
245 | enum sci_status scic_remote_device_reset_complete( | ||
246 | struct scic_sds_remote_device *remote_device); | ||
247 | |||
248 | |||
249 | |||
250 | /** | ||
251 | * scic_remote_device_get_connection_rate() - This method simply returns the | ||
252 | * link rate at which communications to the remote device occur. | ||
253 | * @remote_device: This parameter specifies the device for which to get the | ||
254 | * connection rate. | ||
255 | * | ||
256 | * Return the link rate at which we transfer for the supplied remote device. | ||
257 | */ | ||
258 | enum sci_sas_link_rate scic_remote_device_get_connection_rate( | ||
259 | struct scic_sds_remote_device *remote_device); | ||
260 | |||
261 | /** | ||
262 | * scic_remote_device_get_protocols() - This method will indicate which | ||
263 | * protocols are supported by this remote device. | ||
264 | * @remote_device: This parameter specifies the device for which to return the | ||
265 | * protocol. | ||
266 | * @protocols: This parameter specifies the output values, from the remote | ||
267 | * device object, which indicate the protocols supported by the supplied | ||
268 | * remote_device. | ||
269 | * | ||
270 | * The type of protocols supported by this device. The values are returned as | ||
271 | * part of a bit mask in order to allow for multi-protocol support. | ||
272 | */ | ||
273 | void scic_remote_device_get_protocols( | ||
274 | struct scic_sds_remote_device *remote_device, | ||
275 | struct smp_discover_response_protocols *protocols); | ||
276 | |||
277 | |||
278 | #if !defined(DISABLE_ATAPI) | ||
279 | /** | ||
280 | * scic_remote_device_is_atapi() - | ||
281 | * @this_device: The device whose type is to be decided. | ||
282 | * | ||
283 | * This method first decide whether a device is a stp target, then decode the | ||
284 | * signature fis of a DA STP device to tell whether it is a standard end disk | ||
285 | * or an ATAPI device. bool Indicate a device is ATAPI device or not. | ||
286 | */ | ||
287 | bool scic_remote_device_is_atapi( | ||
288 | struct scic_sds_remote_device *device_handle); | ||
289 | #else /* !defined(DISABLE_ATAPI) */ | ||
290 | #define scic_remote_device_is_atapi(device_handle) false | ||
291 | #endif /* !defined(DISABLE_ATAPI) */ | ||
292 | |||
293 | |||
294 | #endif /* _SCIC_REMOTE_DEVICE_H_ */ | ||
295 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c new file mode 100644 index 000000000000..35f7796df661 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_controller.c | |||
@@ -0,0 +1,4147 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include <linux/device.h> | ||
57 | #include "scic_controller.h" | ||
58 | #include "scic_phy.h" | ||
59 | #include "scic_port.h" | ||
60 | #include "scic_remote_device.h" | ||
61 | #include "scic_sds_controller.h" | ||
62 | #include "scic_sds_controller_registers.h" | ||
63 | #include "scic_sds_pci.h" | ||
64 | #include "scic_sds_phy.h" | ||
65 | #include "scic_sds_port_configuration_agent.h" | ||
66 | #include "scic_sds_port.h" | ||
67 | #include "scic_sds_remote_device.h" | ||
68 | #include "scic_sds_request.h" | ||
69 | #include "scic_user_callback.h" | ||
70 | #include "sci_environment.h" | ||
71 | #include "sci_util.h" | ||
72 | #include "scu_completion_codes.h" | ||
73 | #include "scu_constants.h" | ||
74 | #include "scu_event_codes.h" | ||
75 | #include "scu_remote_node_context.h" | ||
76 | #include "scu_task_context.h" | ||
77 | #include "scu_unsolicited_frame.h" | ||
78 | |||
79 | #define SCU_CONTEXT_RAM_INIT_STALL_TIME 200 | ||
80 | |||
81 | /** | ||
82 | * smu_dcc_get_max_ports() - | ||
83 | * | ||
84 | * This macro returns the maximum number of logical ports supported by the | ||
85 | * hardware. The caller passes in the value read from the device context | ||
86 | * capacity register and this macro will mash and shift the value appropriately. | ||
87 | */ | ||
88 | #define smu_dcc_get_max_ports(dcc_value) \ | ||
89 | (\ | ||
90 | (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ | ||
91 | >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT) + 1 \ | ||
92 | ) | ||
93 | |||
94 | /** | ||
95 | * smu_dcc_get_max_task_context() - | ||
96 | * | ||
97 | * This macro returns the maximum number of task contexts supported by the | ||
98 | * hardware. The caller passes in the value read from the device context | ||
99 | * capacity register and this macro will mash and shift the value appropriately. | ||
100 | */ | ||
101 | #define smu_dcc_get_max_task_context(dcc_value) \ | ||
102 | (\ | ||
103 | (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ | ||
104 | >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT) + 1 \ | ||
105 | ) | ||
106 | |||
107 | /** | ||
108 | * smu_dcc_get_max_remote_node_context() - | ||
109 | * | ||
110 | * This macro returns the maximum number of remote node contexts supported by | ||
111 | * the hardware. The caller passes in the value read from the device context | ||
112 | * capacity register and this macro will mash and shift the value appropriately. | ||
113 | */ | ||
114 | #define smu_dcc_get_max_remote_node_context(dcc_value) \ | ||
115 | (\ | ||
116 | (((dcc_value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ | ||
117 | >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT) + 1 \ | ||
118 | ) | ||
119 | |||
120 | |||
121 | static void scic_sds_controller_power_control_timer_handler( | ||
122 | void *controller); | ||
123 | #define SCIC_SDS_CONTROLLER_MIN_TIMER_COUNT 3 | ||
124 | #define SCIC_SDS_CONTROLLER_MAX_TIMER_COUNT 3 | ||
125 | |||
126 | /** | ||
127 | * | ||
128 | * | ||
129 | * The number of milliseconds to wait for a phy to start. | ||
130 | */ | ||
131 | #define SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT 100 | ||
132 | |||
133 | /** | ||
134 | * | ||
135 | * | ||
136 | * The number of milliseconds to wait while a given phy is consuming power | ||
137 | * before allowing another set of phys to consume power. Ultimately, this will | ||
138 | * be specified by OEM parameter. | ||
139 | */ | ||
140 | #define SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL 500 | ||
141 | |||
142 | /** | ||
143 | * COMPLETION_QUEUE_CYCLE_BIT() - | ||
144 | * | ||
145 | * This macro will return the cycle bit of the completion queue entry | ||
146 | */ | ||
147 | #define COMPLETION_QUEUE_CYCLE_BIT(x) ((x) & 0x80000000) | ||
148 | |||
149 | /** | ||
150 | * NORMALIZE_GET_POINTER() - | ||
151 | * | ||
152 | * This macro will normalize the completion queue get pointer so its value can | ||
153 | * be used as an index into an array | ||
154 | */ | ||
155 | #define NORMALIZE_GET_POINTER(x) \ | ||
156 | ((x) & SMU_COMPLETION_QUEUE_GET_POINTER_MASK) | ||
157 | |||
158 | /** | ||
159 | * NORMALIZE_PUT_POINTER() - | ||
160 | * | ||
161 | * This macro will normalize the completion queue put pointer so its value can | ||
162 | * be used as an array inde | ||
163 | */ | ||
164 | #define NORMALIZE_PUT_POINTER(x) \ | ||
165 | ((x) & SMU_COMPLETION_QUEUE_PUT_POINTER_MASK) | ||
166 | |||
167 | |||
168 | /** | ||
169 | * NORMALIZE_GET_POINTER_CYCLE_BIT() - | ||
170 | * | ||
171 | * This macro will normalize the completion queue cycle pointer so it matches | ||
172 | * the completion queue cycle bit | ||
173 | */ | ||
174 | #define NORMALIZE_GET_POINTER_CYCLE_BIT(x) \ | ||
175 | ((SMU_CQGR_CYCLE_BIT & (x)) << (31 - SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT)) | ||
176 | |||
177 | /** | ||
178 | * NORMALIZE_EVENT_POINTER() - | ||
179 | * | ||
180 | * This macro will normalize the completion queue event entry so its value can | ||
181 | * be used as an index. | ||
182 | */ | ||
183 | #define NORMALIZE_EVENT_POINTER(x) \ | ||
184 | (\ | ||
185 | ((x) & SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK) \ | ||
186 | >> SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT \ | ||
187 | ) | ||
188 | |||
189 | /** | ||
190 | * INCREMENT_COMPLETION_QUEUE_GET() - | ||
191 | * | ||
192 | * This macro will increment the controllers completion queue index value and | ||
193 | * possibly toggle the cycle bit if the completion queue index wraps back to 0. | ||
194 | */ | ||
195 | #define INCREMENT_COMPLETION_QUEUE_GET(controller, index, cycle) \ | ||
196 | INCREMENT_QUEUE_GET(\ | ||
197 | (index), \ | ||
198 | (cycle), \ | ||
199 | (controller)->completion_queue_entries, \ | ||
200 | SMU_CQGR_CYCLE_BIT \ | ||
201 | ) | ||
202 | |||
203 | /** | ||
204 | * INCREMENT_EVENT_QUEUE_GET() - | ||
205 | * | ||
206 | * This macro will increment the controllers event queue index value and | ||
207 | * possibly toggle the event cycle bit if the event queue index wraps back to 0. | ||
208 | */ | ||
209 | #define INCREMENT_EVENT_QUEUE_GET(controller, index, cycle) \ | ||
210 | INCREMENT_QUEUE_GET(\ | ||
211 | (index), \ | ||
212 | (cycle), \ | ||
213 | (controller)->completion_event_entries, \ | ||
214 | SMU_CQGR_EVENT_CYCLE_BIT \ | ||
215 | ) | ||
216 | |||
217 | struct sci_base_memory_descriptor_list * | ||
218 | sci_controller_get_memory_descriptor_list_handle(struct scic_sds_controller *scic) | ||
219 | { | ||
220 | return &scic->parent.mdl; | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * ****************************************************************************- | ||
225 | * * SCIC SDS Controller Initialization Methods | ||
226 | * ****************************************************************************- */ | ||
227 | |||
228 | /** | ||
229 | * This timer is used to start another phy after we have given up on the | ||
230 | * previous phy to transition to the ready state. | ||
231 | * | ||
232 | * | ||
233 | */ | ||
234 | static void scic_sds_controller_phy_startup_timeout_handler( | ||
235 | void *controller) | ||
236 | { | ||
237 | enum sci_status status; | ||
238 | struct scic_sds_controller *this_controller; | ||
239 | |||
240 | this_controller = (struct scic_sds_controller *)controller; | ||
241 | |||
242 | this_controller->phy_startup_timer_pending = false; | ||
243 | |||
244 | status = SCI_FAILURE; | ||
245 | |||
246 | while (status != SCI_SUCCESS) { | ||
247 | status = scic_sds_controller_start_next_phy(this_controller); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * | ||
253 | * | ||
254 | * This method initializes the phy startup operations for controller start. | ||
255 | */ | ||
256 | void scic_sds_controller_initialize_phy_startup( | ||
257 | struct scic_sds_controller *this_controller) | ||
258 | { | ||
259 | this_controller->phy_startup_timer = scic_cb_timer_create( | ||
260 | this_controller, | ||
261 | scic_sds_controller_phy_startup_timeout_handler, | ||
262 | this_controller | ||
263 | ); | ||
264 | |||
265 | this_controller->next_phy_to_start = 0; | ||
266 | this_controller->phy_startup_timer_pending = false; | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * | ||
271 | * | ||
272 | * This method initializes the power control operations for the controller | ||
273 | * object. | ||
274 | */ | ||
275 | void scic_sds_controller_initialize_power_control( | ||
276 | struct scic_sds_controller *this_controller) | ||
277 | { | ||
278 | this_controller->power_control.timer = scic_cb_timer_create( | ||
279 | this_controller, | ||
280 | scic_sds_controller_power_control_timer_handler, | ||
281 | this_controller | ||
282 | ); | ||
283 | |||
284 | memset( | ||
285 | this_controller->power_control.requesters, | ||
286 | 0, | ||
287 | sizeof(this_controller->power_control.requesters) | ||
288 | ); | ||
289 | |||
290 | this_controller->power_control.phys_waiting = 0; | ||
291 | } | ||
292 | |||
293 | /* --------------------------------------------------------------------------- */ | ||
294 | |||
295 | #define SCU_REMOTE_NODE_CONTEXT_ALIGNMENT (32) | ||
296 | #define SCU_TASK_CONTEXT_ALIGNMENT (256) | ||
297 | #define SCU_UNSOLICITED_FRAME_ADDRESS_ALIGNMENT (64) | ||
298 | #define SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT (1024) | ||
299 | #define SCU_UNSOLICITED_FRAME_HEADER_ALIGNMENT (64) | ||
300 | |||
301 | /* --------------------------------------------------------------------------- */ | ||
302 | |||
303 | /** | ||
304 | * This method builds the memory descriptor table for this controller. | ||
305 | * @this_controller: This parameter specifies the controller object for which | ||
306 | * to build the memory table. | ||
307 | * | ||
308 | */ | ||
309 | static void scic_sds_controller_build_memory_descriptor_table( | ||
310 | struct scic_sds_controller *this_controller) | ||
311 | { | ||
312 | sci_base_mde_construct( | ||
313 | &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE], | ||
314 | SCU_COMPLETION_RAM_ALIGNMENT, | ||
315 | (sizeof(u32) * this_controller->completion_queue_entries), | ||
316 | (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS) | ||
317 | ); | ||
318 | |||
319 | sci_base_mde_construct( | ||
320 | &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT], | ||
321 | SCU_REMOTE_NODE_CONTEXT_ALIGNMENT, | ||
322 | this_controller->remote_node_entries * sizeof(union scu_remote_node_context), | ||
323 | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS | ||
324 | ); | ||
325 | |||
326 | sci_base_mde_construct( | ||
327 | &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT], | ||
328 | SCU_TASK_CONTEXT_ALIGNMENT, | ||
329 | this_controller->task_context_entries * sizeof(struct scu_task_context), | ||
330 | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS | ||
331 | ); | ||
332 | |||
333 | /* | ||
334 | * The UF buffer address table size must be programmed to a power | ||
335 | * of 2. Find the first power of 2 that is equal to or greater then | ||
336 | * the number of unsolicited frame buffers to be utilized. */ | ||
337 | scic_sds_unsolicited_frame_control_set_address_table_count( | ||
338 | &this_controller->uf_control | ||
339 | ); | ||
340 | |||
341 | sci_base_mde_construct( | ||
342 | &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER], | ||
343 | SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT, | ||
344 | scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control), | ||
345 | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS | ||
346 | ); | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * This method validates the driver supplied memory descriptor table. | ||
351 | * @this_controller: | ||
352 | * | ||
353 | * enum sci_status | ||
354 | */ | ||
355 | enum sci_status scic_sds_controller_validate_memory_descriptor_table( | ||
356 | struct scic_sds_controller *this_controller) | ||
357 | { | ||
358 | bool mde_list_valid; | ||
359 | |||
360 | mde_list_valid = sci_base_mde_is_valid( | ||
361 | &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE], | ||
362 | SCU_COMPLETION_RAM_ALIGNMENT, | ||
363 | (sizeof(u32) * this_controller->completion_queue_entries), | ||
364 | (SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS) | ||
365 | ); | ||
366 | |||
367 | if (mde_list_valid == false) | ||
368 | return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; | ||
369 | |||
370 | mde_list_valid = sci_base_mde_is_valid( | ||
371 | &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT], | ||
372 | SCU_REMOTE_NODE_CONTEXT_ALIGNMENT, | ||
373 | this_controller->remote_node_entries * sizeof(union scu_remote_node_context), | ||
374 | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS | ||
375 | ); | ||
376 | |||
377 | if (mde_list_valid == false) | ||
378 | return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; | ||
379 | |||
380 | mde_list_valid = sci_base_mde_is_valid( | ||
381 | &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT], | ||
382 | SCU_TASK_CONTEXT_ALIGNMENT, | ||
383 | this_controller->task_context_entries * sizeof(struct scu_task_context), | ||
384 | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS | ||
385 | ); | ||
386 | |||
387 | if (mde_list_valid == false) | ||
388 | return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; | ||
389 | |||
390 | mde_list_valid = sci_base_mde_is_valid( | ||
391 | &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER], | ||
392 | SCU_UNSOLICITED_FRAME_BUFFER_ALIGNMENT, | ||
393 | scic_sds_unsolicited_frame_control_get_mde_size(this_controller->uf_control), | ||
394 | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS | ||
395 | ); | ||
396 | |||
397 | if (mde_list_valid == false) | ||
398 | return SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD; | ||
399 | |||
400 | return SCI_SUCCESS; | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * This method initializes the controller with the physical memory addresses | ||
405 | * that are used to communicate with the driver. | ||
406 | * @this_controller: | ||
407 | * | ||
408 | */ | ||
409 | void scic_sds_controller_ram_initialization( | ||
410 | struct scic_sds_controller *this_controller) | ||
411 | { | ||
412 | struct sci_physical_memory_descriptor *mde; | ||
413 | |||
414 | /* | ||
415 | * The completion queue is actually placed in cacheable memory | ||
416 | * Therefore it no longer comes out of memory in the MDL. */ | ||
417 | mde = &this_controller->memory_descriptors[SCU_MDE_COMPLETION_QUEUE]; | ||
418 | this_controller->completion_queue = (u32 *)mde->virtual_address; | ||
419 | SMU_CQBAR_WRITE(this_controller, mde->physical_address); | ||
420 | |||
421 | /* | ||
422 | * Program the location of the Remote Node Context table | ||
423 | * into the SCU. */ | ||
424 | mde = &this_controller->memory_descriptors[SCU_MDE_REMOTE_NODE_CONTEXT]; | ||
425 | this_controller->remote_node_context_table = (union scu_remote_node_context *) | ||
426 | mde->virtual_address; | ||
427 | SMU_RNCBAR_WRITE(this_controller, mde->physical_address); | ||
428 | |||
429 | /* Program the location of the Task Context table into the SCU. */ | ||
430 | mde = &this_controller->memory_descriptors[SCU_MDE_TASK_CONTEXT]; | ||
431 | this_controller->task_context_table = (struct scu_task_context *) | ||
432 | mde->virtual_address; | ||
433 | SMU_HTTBAR_WRITE(this_controller, mde->physical_address); | ||
434 | |||
435 | mde = &this_controller->memory_descriptors[SCU_MDE_UF_BUFFER]; | ||
436 | scic_sds_unsolicited_frame_control_construct( | ||
437 | &this_controller->uf_control, mde, this_controller | ||
438 | ); | ||
439 | |||
440 | /* | ||
441 | * Inform the silicon as to the location of the UF headers and | ||
442 | * address table. */ | ||
443 | SCU_UFHBAR_WRITE( | ||
444 | this_controller, | ||
445 | this_controller->uf_control.headers.physical_address); | ||
446 | SCU_PUFATHAR_WRITE( | ||
447 | this_controller, | ||
448 | this_controller->uf_control.address_table.physical_address); | ||
449 | } | ||
450 | |||
451 | /** | ||
452 | * This method initializes the task context data for the controller. | ||
453 | * @this_controller: | ||
454 | * | ||
455 | */ | ||
456 | void scic_sds_controller_assign_task_entries( | ||
457 | struct scic_sds_controller *this_controller) | ||
458 | { | ||
459 | u32 task_assignment; | ||
460 | |||
461 | /* | ||
462 | * Assign all the TCs to function 0 | ||
463 | * TODO: Do we actually need to read this register to write it back? */ | ||
464 | task_assignment = SMU_TCA_READ(this_controller, 0); | ||
465 | |||
466 | task_assignment = | ||
467 | ( | ||
468 | task_assignment | ||
469 | | (SMU_TCA_GEN_VAL(STARTING, 0)) | ||
470 | | (SMU_TCA_GEN_VAL(ENDING, this_controller->task_context_entries - 1)) | ||
471 | | (SMU_TCA_GEN_BIT(RANGE_CHECK_ENABLE)) | ||
472 | ); | ||
473 | |||
474 | SMU_TCA_WRITE(this_controller, 0, task_assignment); | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * This method initializes the hardware completion queue. | ||
479 | * | ||
480 | * | ||
481 | */ | ||
482 | void scic_sds_controller_initialize_completion_queue( | ||
483 | struct scic_sds_controller *this_controller) | ||
484 | { | ||
485 | u32 index; | ||
486 | u32 completion_queue_control_value; | ||
487 | u32 completion_queue_get_value; | ||
488 | u32 completion_queue_put_value; | ||
489 | |||
490 | this_controller->completion_queue_get = 0; | ||
491 | |||
492 | completion_queue_control_value = ( | ||
493 | SMU_CQC_QUEUE_LIMIT_SET(this_controller->completion_queue_entries - 1) | ||
494 | | SMU_CQC_EVENT_LIMIT_SET(this_controller->completion_event_entries - 1) | ||
495 | ); | ||
496 | |||
497 | SMU_CQC_WRITE(this_controller, completion_queue_control_value); | ||
498 | |||
499 | /* Set the completion queue get pointer and enable the queue */ | ||
500 | completion_queue_get_value = ( | ||
501 | (SMU_CQGR_GEN_VAL(POINTER, 0)) | ||
502 | | (SMU_CQGR_GEN_VAL(EVENT_POINTER, 0)) | ||
503 | | (SMU_CQGR_GEN_BIT(ENABLE)) | ||
504 | | (SMU_CQGR_GEN_BIT(EVENT_ENABLE)) | ||
505 | ); | ||
506 | |||
507 | SMU_CQGR_WRITE(this_controller, completion_queue_get_value); | ||
508 | |||
509 | /* Set the completion queue put pointer */ | ||
510 | completion_queue_put_value = ( | ||
511 | (SMU_CQPR_GEN_VAL(POINTER, 0)) | ||
512 | | (SMU_CQPR_GEN_VAL(EVENT_POINTER, 0)) | ||
513 | ); | ||
514 | |||
515 | SMU_CQPR_WRITE(this_controller, completion_queue_put_value); | ||
516 | |||
517 | /* Initialize the cycle bit of the completion queue entries */ | ||
518 | for (index = 0; index < this_controller->completion_queue_entries; index++) { | ||
519 | /* | ||
520 | * If get.cycle_bit != completion_queue.cycle_bit | ||
521 | * its not a valid completion queue entry | ||
522 | * so at system start all entries are invalid */ | ||
523 | this_controller->completion_queue[index] = 0x80000000; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /** | ||
528 | * This method initializes the hardware unsolicited frame queue. | ||
529 | * | ||
530 | * | ||
531 | */ | ||
532 | void scic_sds_controller_initialize_unsolicited_frame_queue( | ||
533 | struct scic_sds_controller *this_controller) | ||
534 | { | ||
535 | u32 frame_queue_control_value; | ||
536 | u32 frame_queue_get_value; | ||
537 | u32 frame_queue_put_value; | ||
538 | |||
539 | /* Write the queue size */ | ||
540 | frame_queue_control_value = | ||
541 | SCU_UFQC_GEN_VAL(QUEUE_SIZE, this_controller->uf_control.address_table.count); | ||
542 | |||
543 | SCU_UFQC_WRITE(this_controller, frame_queue_control_value); | ||
544 | |||
545 | /* Setup the get pointer for the unsolicited frame queue */ | ||
546 | frame_queue_get_value = ( | ||
547 | SCU_UFQGP_GEN_VAL(POINTER, 0) | ||
548 | | SCU_UFQGP_GEN_BIT(ENABLE_BIT) | ||
549 | ); | ||
550 | |||
551 | SCU_UFQGP_WRITE(this_controller, frame_queue_get_value); | ||
552 | |||
553 | /* Setup the put pointer for the unsolicited frame queue */ | ||
554 | frame_queue_put_value = SCU_UFQPP_GEN_VAL(POINTER, 0); | ||
555 | |||
556 | SCU_UFQPP_WRITE(this_controller, frame_queue_put_value); | ||
557 | } | ||
558 | |||
559 | /** | ||
560 | * This method enables the hardware port task scheduler. | ||
561 | * | ||
562 | * | ||
563 | */ | ||
564 | void scic_sds_controller_enable_port_task_scheduler( | ||
565 | struct scic_sds_controller *this_controller) | ||
566 | { | ||
567 | u32 port_task_scheduler_value; | ||
568 | |||
569 | port_task_scheduler_value = SCU_PTSGCR_READ(this_controller); | ||
570 | |||
571 | port_task_scheduler_value |= | ||
572 | (SCU_PTSGCR_GEN_BIT(ETM_ENABLE) | SCU_PTSGCR_GEN_BIT(PTSG_ENABLE)); | ||
573 | |||
574 | SCU_PTSGCR_WRITE(this_controller, port_task_scheduler_value); | ||
575 | } | ||
576 | |||
577 | /* --------------------------------------------------------------------------- */ | ||
578 | |||
579 | /** | ||
580 | * | ||
581 | * | ||
582 | * This macro is used to delay between writes to the AFE registers during AFE | ||
583 | * initialization. | ||
584 | */ | ||
585 | #define AFE_REGISTER_WRITE_DELAY 10 | ||
586 | |||
587 | static bool is_a0(void) | ||
588 | { | ||
589 | return isci_si_rev == ISCI_SI_REVA0; | ||
590 | } | ||
591 | |||
592 | static bool is_a2(void) | ||
593 | { | ||
594 | return isci_si_rev == ISCI_SI_REVA2; | ||
595 | } | ||
596 | |||
597 | static bool is_b0(void) | ||
598 | { | ||
599 | return isci_si_rev > ISCI_SI_REVA2; | ||
600 | } | ||
601 | |||
602 | /* Initialize the AFE for this phy index. We need to read the AFE setup from | ||
603 | * the OEM parameters none | ||
604 | */ | ||
605 | void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) | ||
606 | { | ||
607 | u32 afe_status; | ||
608 | u32 phy_id; | ||
609 | |||
610 | /* Clear DFX Status registers */ | ||
611 | scu_afe_register_write(scic, afe_dfx_master_control0, 0x0081000f); | ||
612 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
613 | |||
614 | /* Configure bias currents to normal */ | ||
615 | if (is_a0()) | ||
616 | scu_afe_register_write(scic, afe_bias_control, 0x00005500); | ||
617 | else | ||
618 | scu_afe_register_write(scic, afe_bias_control, 0x00005A00); | ||
619 | |||
620 | |||
621 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
622 | |||
623 | /* Enable PLL */ | ||
624 | if (is_b0()) | ||
625 | scu_afe_register_write(scic, afe_pll_control0, 0x80040A08); | ||
626 | else | ||
627 | scu_afe_register_write(scic, afe_pll_control0, 0x80040908); | ||
628 | |||
629 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
630 | |||
631 | /* Wait for the PLL to lock */ | ||
632 | do { | ||
633 | afe_status = scu_afe_register_read( | ||
634 | scic, afe_common_block_status); | ||
635 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
636 | } while ((afe_status & 0x00001000) == 0); | ||
637 | |||
638 | if (is_b0()) { | ||
639 | /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */ | ||
640 | scu_afe_register_write(scic, afe_pmsn_master_control0, 0x7bcc96ad); | ||
641 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
642 | } | ||
643 | |||
644 | for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) { | ||
645 | if (is_b0()) { | ||
646 | /* Configure transmitter SSC parameters */ | ||
647 | scu_afe_txreg_write(scic, phy_id, afe_tx_ssc_control, 0x00030000); | ||
648 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
649 | } else { | ||
650 | /* | ||
651 | * All defaults, except the Receive Word Alignament/Comma Detect | ||
652 | * Enable....(0xe800) */ | ||
653 | scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004512); | ||
654 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
655 | |||
656 | scu_afe_txreg_write(scic, phy_id, afe_xcvr_control1, 0x0050100F); | ||
657 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
658 | } | ||
659 | |||
660 | /* | ||
661 | * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) | ||
662 | * & increase TX int & ext bias 20%....(0xe85c) */ | ||
663 | if (is_a0()) | ||
664 | scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003D4); | ||
665 | else if (is_a2()) | ||
666 | scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003F0); | ||
667 | else { | ||
668 | /* Power down TX and RX (PWRDNTX and PWRDNRX) */ | ||
669 | scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d7); | ||
670 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
671 | |||
672 | /* | ||
673 | * Power up TX and RX out from power down (PWRDNTX and PWRDNRX) | ||
674 | * & increase TX int & ext bias 20%....(0xe85c) */ | ||
675 | scu_afe_txreg_write(scic, phy_id, afe_channel_control, 0x000003d4); | ||
676 | } | ||
677 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
678 | |||
679 | if (is_a0() || is_a2()) { | ||
680 | /* Enable TX equalization (0xe824) */ | ||
681 | scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); | ||
682 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
683 | } | ||
684 | |||
685 | /* | ||
686 | * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On), | ||
687 | * RDD=0x0(RX Detect Enabled) ....(0xe800) */ | ||
688 | scu_afe_txreg_write(scic, phy_id, afe_xcvr_control0, 0x00004100); | ||
689 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
690 | |||
691 | /* Leave DFE/FFE on */ | ||
692 | if (is_a0()) | ||
693 | scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F09983F); | ||
694 | else if (is_a2()) | ||
695 | scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); | ||
696 | else { | ||
697 | scu_afe_txreg_write(scic, phy_id, afe_rx_ssc_control0, 0x3F11103F); | ||
698 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
699 | /* Enable TX equalization (0xe824) */ | ||
700 | scu_afe_txreg_write(scic, phy_id, afe_tx_control, 0x00040000); | ||
701 | } | ||
702 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
703 | |||
704 | scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control0, 0x000E7C03); | ||
705 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
706 | |||
707 | scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control1, 0x000E7C03); | ||
708 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
709 | |||
710 | scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control2, 0x000E7C03); | ||
711 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
712 | |||
713 | scu_afe_txreg_write(scic, phy_id, afe_tx_amp_control3, 0x000E7C03); | ||
714 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
715 | } | ||
716 | |||
717 | /* Transfer control to the PEs */ | ||
718 | scu_afe_register_write(scic, afe_dfx_master_control0, 0x00010f00); | ||
719 | scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); | ||
720 | } | ||
721 | |||
722 | /* | ||
723 | * ****************************************************************************- | ||
724 | * * SCIC SDS Controller Internal Start/Stop Routines | ||
725 | * ****************************************************************************- */ | ||
726 | |||
727 | |||
728 | /** | ||
729 | * This method will attempt to transition into the ready state for the | ||
730 | * controller and indicate that the controller start operation has completed | ||
731 | * if all criteria are met. | ||
732 | * @this_controller: This parameter indicates the controller object for which | ||
733 | * to transition to ready. | ||
734 | * @status: This parameter indicates the status value to be pass into the call | ||
735 | * to scic_cb_controller_start_complete(). | ||
736 | * | ||
737 | * none. | ||
738 | */ | ||
739 | static void scic_sds_controller_transition_to_ready( | ||
740 | struct scic_sds_controller *this_controller, | ||
741 | enum sci_status status) | ||
742 | { | ||
743 | if (this_controller->parent.state_machine.current_state_id | ||
744 | == SCI_BASE_CONTROLLER_STATE_STARTING) { | ||
745 | /* | ||
746 | * We move into the ready state, because some of the phys/ports | ||
747 | * may be up and operational. */ | ||
748 | sci_base_state_machine_change_state( | ||
749 | scic_sds_controller_get_base_state_machine(this_controller), | ||
750 | SCI_BASE_CONTROLLER_STATE_READY | ||
751 | ); | ||
752 | |||
753 | scic_cb_controller_start_complete(this_controller, status); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | /** | ||
758 | * This method is the general timeout handler for the controller. It will take | ||
759 | * the correct timetout action based on the current controller state | ||
760 | */ | ||
761 | void scic_sds_controller_timeout_handler( | ||
762 | struct scic_sds_controller *scic) | ||
763 | { | ||
764 | enum sci_base_controller_states current_state; | ||
765 | |||
766 | current_state = sci_base_state_machine_get_state( | ||
767 | scic_sds_controller_get_base_state_machine(scic)); | ||
768 | |||
769 | if (current_state == SCI_BASE_CONTROLLER_STATE_STARTING) { | ||
770 | scic_sds_controller_transition_to_ready( | ||
771 | scic, SCI_FAILURE_TIMEOUT); | ||
772 | } else if (current_state == SCI_BASE_CONTROLLER_STATE_STOPPING) { | ||
773 | sci_base_state_machine_change_state( | ||
774 | scic_sds_controller_get_base_state_machine(scic), | ||
775 | SCI_BASE_CONTROLLER_STATE_FAILED); | ||
776 | scic_cb_controller_stop_complete(scic, SCI_FAILURE_TIMEOUT); | ||
777 | } else /* / @todo Now what do we want to do in this case? */ | ||
778 | dev_err(scic_to_dev(scic), | ||
779 | "%s: Controller timer fired when controller was not " | ||
780 | "in a state being timed.\n", | ||
781 | __func__); | ||
782 | } | ||
783 | |||
784 | /** | ||
785 | * scic_sds_controller_get_port_configuration_mode | ||
786 | * @this_controller: This is the controller to use to determine if we are using | ||
787 | * manual or automatic port configuration. | ||
788 | * | ||
789 | * SCIC_PORT_CONFIGURATION_MODE | ||
790 | */ | ||
791 | enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode( | ||
792 | struct scic_sds_controller *this_controller) | ||
793 | { | ||
794 | u32 index; | ||
795 | enum SCIC_PORT_CONFIGURATION_MODE mode; | ||
796 | |||
797 | mode = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE; | ||
798 | |||
799 | for (index = 0; index < SCI_MAX_PORTS; index++) { | ||
800 | if (this_controller->oem_parameters.sds1.ports[index].phy_mask != 0) { | ||
801 | mode = SCIC_PORT_MANUAL_CONFIGURATION_MODE; | ||
802 | break; | ||
803 | } | ||
804 | } | ||
805 | |||
806 | return mode; | ||
807 | } | ||
808 | |||
809 | enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic) | ||
810 | { | ||
811 | u32 index; | ||
812 | enum sci_status port_status; | ||
813 | enum sci_status status = SCI_SUCCESS; | ||
814 | |||
815 | for (index = 0; index < scic->logical_port_entries; index++) { | ||
816 | port_status = scic_port_stop(&scic->port_table[index]); | ||
817 | |||
818 | if ((port_status != SCI_SUCCESS) && | ||
819 | (port_status != SCI_FAILURE_INVALID_STATE)) { | ||
820 | status = SCI_FAILURE; | ||
821 | |||
822 | dev_warn(scic_to_dev(scic), | ||
823 | "%s: Controller stop operation failed to " | ||
824 | "stop port %d because of status %d.\n", | ||
825 | __func__, | ||
826 | scic->port_table[index].logical_port_index, | ||
827 | port_status); | ||
828 | } | ||
829 | } | ||
830 | |||
831 | return status; | ||
832 | } | ||
833 | |||
834 | /** | ||
835 | * | ||
836 | * | ||
837 | * | ||
838 | */ | ||
839 | static void scic_sds_controller_phy_timer_start( | ||
840 | struct scic_sds_controller *this_controller) | ||
841 | { | ||
842 | scic_cb_timer_start( | ||
843 | this_controller, | ||
844 | this_controller->phy_startup_timer, | ||
845 | SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT | ||
846 | ); | ||
847 | |||
848 | this_controller->phy_startup_timer_pending = true; | ||
849 | } | ||
850 | |||
851 | /** | ||
852 | * | ||
853 | * | ||
854 | * | ||
855 | */ | ||
856 | void scic_sds_controller_phy_timer_stop( | ||
857 | struct scic_sds_controller *this_controller) | ||
858 | { | ||
859 | scic_cb_timer_stop( | ||
860 | this_controller, | ||
861 | this_controller->phy_startup_timer | ||
862 | ); | ||
863 | |||
864 | this_controller->phy_startup_timer_pending = false; | ||
865 | } | ||
866 | |||
867 | /** | ||
868 | * This method is called internally by the controller object to start the next | ||
869 | * phy on the controller. If all the phys have been starte, then this | ||
870 | * method will attempt to transition the controller to the READY state and | ||
871 | * inform the user (scic_cb_controller_start_complete()). | ||
872 | * @this_controller: This parameter specifies the controller object for which | ||
873 | * to start the next phy. | ||
874 | * | ||
875 | * enum sci_status | ||
876 | */ | ||
877 | enum sci_status scic_sds_controller_start_next_phy( | ||
878 | struct scic_sds_controller *this_controller) | ||
879 | { | ||
880 | enum sci_status status; | ||
881 | |||
882 | status = SCI_SUCCESS; | ||
883 | |||
884 | if (this_controller->phy_startup_timer_pending == false) { | ||
885 | if (this_controller->next_phy_to_start == SCI_MAX_PHYS) { | ||
886 | bool is_controller_start_complete = true; | ||
887 | struct scic_sds_phy *the_phy; | ||
888 | u8 index; | ||
889 | |||
890 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
891 | the_phy = &this_controller->phy_table[index]; | ||
892 | |||
893 | if (scic_sds_phy_get_port(the_phy) != SCI_INVALID_HANDLE) { | ||
894 | /** | ||
895 | * The controller start operation is complete if and only | ||
896 | * if: | ||
897 | * - all links have been given an opportunity to start | ||
898 | * - have no indication of a connected device | ||
899 | * - have an indication of a connected device and it has | ||
900 | * finished the link training process. | ||
901 | */ | ||
902 | if ( | ||
903 | ( | ||
904 | (the_phy->is_in_link_training == false) | ||
905 | && (the_phy->parent.state_machine.current_state_id | ||
906 | == SCI_BASE_PHY_STATE_INITIAL) | ||
907 | ) | ||
908 | || ( | ||
909 | (the_phy->is_in_link_training == false) | ||
910 | && (the_phy->parent.state_machine.current_state_id | ||
911 | == SCI_BASE_PHY_STATE_STOPPED) | ||
912 | ) | ||
913 | || ( | ||
914 | (the_phy->is_in_link_training == true) | ||
915 | && (the_phy->parent.state_machine.current_state_id | ||
916 | == SCI_BASE_PHY_STATE_STARTING) | ||
917 | ) | ||
918 | ) { | ||
919 | is_controller_start_complete = false; | ||
920 | break; | ||
921 | } | ||
922 | } | ||
923 | } | ||
924 | |||
925 | /* | ||
926 | * The controller has successfully finished the start process. | ||
927 | * Inform the SCI Core user and transition to the READY state. */ | ||
928 | if (is_controller_start_complete == true) { | ||
929 | scic_sds_controller_transition_to_ready( | ||
930 | this_controller, SCI_SUCCESS | ||
931 | ); | ||
932 | scic_sds_controller_phy_timer_stop(this_controller); | ||
933 | } | ||
934 | } else { | ||
935 | struct scic_sds_phy *the_phy; | ||
936 | |||
937 | the_phy = &this_controller->phy_table[this_controller->next_phy_to_start]; | ||
938 | |||
939 | if ( | ||
940 | scic_sds_controller_get_port_configuration_mode(this_controller) | ||
941 | == SCIC_PORT_MANUAL_CONFIGURATION_MODE | ||
942 | ) { | ||
943 | if (scic_sds_phy_get_port(the_phy) == SCI_INVALID_HANDLE) { | ||
944 | this_controller->next_phy_to_start++; | ||
945 | |||
946 | /* | ||
947 | * Caution recursion ahead be forwarned | ||
948 | * | ||
949 | * The PHY was never added to a PORT in MPC mode so start the next phy in sequence | ||
950 | * This phy will never go link up and will not draw power the OEM parameters either | ||
951 | * configured the phy incorrectly for the PORT or it was never assigned to a PORT */ | ||
952 | return scic_sds_controller_start_next_phy(this_controller); | ||
953 | } | ||
954 | } | ||
955 | |||
956 | status = scic_sds_phy_start(the_phy); | ||
957 | |||
958 | if (status == SCI_SUCCESS) { | ||
959 | scic_sds_controller_phy_timer_start(this_controller); | ||
960 | } else { | ||
961 | dev_warn(scic_to_dev(this_controller), | ||
962 | "%s: Controller stop operation failed " | ||
963 | "to stop phy %d because of status " | ||
964 | "%d.\n", | ||
965 | __func__, | ||
966 | this_controller->phy_table[this_controller->next_phy_to_start].phy_index, | ||
967 | status); | ||
968 | } | ||
969 | |||
970 | this_controller->next_phy_to_start++; | ||
971 | } | ||
972 | } | ||
973 | |||
974 | return status; | ||
975 | } | ||
976 | |||
977 | /** | ||
978 | * | ||
979 | * @this_controller: | ||
980 | * | ||
981 | * enum sci_status | ||
982 | */ | ||
983 | enum sci_status scic_sds_controller_stop_phys( | ||
984 | struct scic_sds_controller *this_controller) | ||
985 | { | ||
986 | u32 index; | ||
987 | enum sci_status status; | ||
988 | enum sci_status phy_status; | ||
989 | |||
990 | status = SCI_SUCCESS; | ||
991 | |||
992 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
993 | phy_status = scic_sds_phy_stop(&this_controller->phy_table[index]); | ||
994 | |||
995 | if ( | ||
996 | (phy_status != SCI_SUCCESS) | ||
997 | && (phy_status != SCI_FAILURE_INVALID_STATE) | ||
998 | ) { | ||
999 | status = SCI_FAILURE; | ||
1000 | |||
1001 | dev_warn(scic_to_dev(this_controller), | ||
1002 | "%s: Controller stop operation failed to stop " | ||
1003 | "phy %d because of status %d.\n", | ||
1004 | __func__, | ||
1005 | this_controller->phy_table[index].phy_index, phy_status); | ||
1006 | } | ||
1007 | } | ||
1008 | |||
1009 | return status; | ||
1010 | } | ||
1011 | |||
1012 | /** | ||
1013 | * | ||
1014 | * @this_controller: | ||
1015 | * | ||
1016 | * enum sci_status | ||
1017 | */ | ||
1018 | enum sci_status scic_sds_controller_stop_devices( | ||
1019 | struct scic_sds_controller *this_controller) | ||
1020 | { | ||
1021 | u32 index; | ||
1022 | enum sci_status status; | ||
1023 | enum sci_status device_status; | ||
1024 | |||
1025 | status = SCI_SUCCESS; | ||
1026 | |||
1027 | for (index = 0; index < this_controller->remote_node_entries; index++) { | ||
1028 | if (this_controller->device_table[index] != SCI_INVALID_HANDLE) { | ||
1029 | /* / @todo What timeout value do we want to provide to this request? */ | ||
1030 | device_status = scic_remote_device_stop(this_controller->device_table[index], 0); | ||
1031 | |||
1032 | if ((device_status != SCI_SUCCESS) && | ||
1033 | (device_status != SCI_FAILURE_INVALID_STATE)) { | ||
1034 | dev_warn(scic_to_dev(this_controller), | ||
1035 | "%s: Controller stop operation failed " | ||
1036 | "to stop device 0x%p because of " | ||
1037 | "status %d.\n", | ||
1038 | __func__, | ||
1039 | this_controller->device_table[index], device_status); | ||
1040 | } | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | return status; | ||
1045 | } | ||
1046 | |||
1047 | /* | ||
1048 | * ****************************************************************************- | ||
1049 | * * SCIC SDS Controller Power Control (Staggered Spinup) | ||
1050 | * ****************************************************************************- */ | ||
1051 | |||
1052 | /** | ||
1053 | * | ||
1054 | * | ||
1055 | * This method starts the power control timer for this controller object. | ||
1056 | */ | ||
1057 | static void scic_sds_controller_power_control_timer_start( | ||
1058 | struct scic_sds_controller *this_controller) | ||
1059 | { | ||
1060 | scic_cb_timer_start( | ||
1061 | this_controller, this_controller->power_control.timer, | ||
1062 | SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL | ||
1063 | ); | ||
1064 | |||
1065 | this_controller->power_control.timer_started = true; | ||
1066 | } | ||
1067 | |||
1068 | /** | ||
1069 | * | ||
1070 | * | ||
1071 | * | ||
1072 | */ | ||
1073 | static void scic_sds_controller_power_control_timer_handler( | ||
1074 | void *controller) | ||
1075 | { | ||
1076 | struct scic_sds_controller *this_controller; | ||
1077 | |||
1078 | this_controller = (struct scic_sds_controller *)controller; | ||
1079 | |||
1080 | if (this_controller->power_control.phys_waiting == 0) { | ||
1081 | this_controller->power_control.timer_started = false; | ||
1082 | } else { | ||
1083 | struct scic_sds_phy *the_phy = NULL; | ||
1084 | u8 i; | ||
1085 | |||
1086 | for (i = 0; | ||
1087 | (i < SCI_MAX_PHYS) | ||
1088 | && (this_controller->power_control.phys_waiting != 0); | ||
1089 | i++) { | ||
1090 | if (this_controller->power_control.requesters[i] != NULL) { | ||
1091 | the_phy = this_controller->power_control.requesters[i]; | ||
1092 | this_controller->power_control.requesters[i] = NULL; | ||
1093 | this_controller->power_control.phys_waiting--; | ||
1094 | break; | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1098 | /* | ||
1099 | * It doesn't matter if the power list is empty, we need to start the | ||
1100 | * timer in case another phy becomes ready. */ | ||
1101 | scic_sds_controller_power_control_timer_start(this_controller); | ||
1102 | |||
1103 | scic_sds_phy_consume_power_handler(the_phy); | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | /** | ||
1108 | * This method inserts the phy in the stagger spinup control queue. | ||
1109 | * @this_controller: | ||
1110 | * | ||
1111 | * | ||
1112 | */ | ||
1113 | void scic_sds_controller_power_control_queue_insert( | ||
1114 | struct scic_sds_controller *this_controller, | ||
1115 | struct scic_sds_phy *the_phy) | ||
1116 | { | ||
1117 | BUG_ON(the_phy == NULL); | ||
1118 | |||
1119 | if ( | ||
1120 | (this_controller->power_control.timer_started) | ||
1121 | && (this_controller->power_control.requesters[the_phy->phy_index] == NULL) | ||
1122 | ) { | ||
1123 | this_controller->power_control.requesters[the_phy->phy_index] = the_phy; | ||
1124 | this_controller->power_control.phys_waiting++; | ||
1125 | } else { | ||
1126 | scic_sds_controller_power_control_timer_start(this_controller); | ||
1127 | scic_sds_phy_consume_power_handler(the_phy); | ||
1128 | } | ||
1129 | } | ||
1130 | |||
1131 | /** | ||
1132 | * This method removes the phy from the stagger spinup control queue. | ||
1133 | * @this_controller: | ||
1134 | * | ||
1135 | * | ||
1136 | */ | ||
1137 | void scic_sds_controller_power_control_queue_remove( | ||
1138 | struct scic_sds_controller *this_controller, | ||
1139 | struct scic_sds_phy *the_phy) | ||
1140 | { | ||
1141 | BUG_ON(the_phy == NULL); | ||
1142 | |||
1143 | if (this_controller->power_control.requesters[the_phy->phy_index] != NULL) { | ||
1144 | this_controller->power_control.phys_waiting--; | ||
1145 | } | ||
1146 | |||
1147 | this_controller->power_control.requesters[the_phy->phy_index] = NULL; | ||
1148 | } | ||
1149 | |||
1150 | /* | ||
1151 | * ****************************************************************************- | ||
1152 | * * SCIC SDS Controller Completion Routines | ||
1153 | * ****************************************************************************- */ | ||
1154 | |||
1155 | /** | ||
1156 | * This method returns a true value if the completion queue has entries that | ||
1157 | * can be processed | ||
1158 | * @this_controller: | ||
1159 | * | ||
1160 | * bool true if the completion queue has entries to process false if the | ||
1161 | * completion queue has no entries to process | ||
1162 | */ | ||
1163 | static bool scic_sds_controller_completion_queue_has_entries( | ||
1164 | struct scic_sds_controller *this_controller) | ||
1165 | { | ||
1166 | u32 get_value = this_controller->completion_queue_get; | ||
1167 | u32 get_index = get_value & SMU_COMPLETION_QUEUE_GET_POINTER_MASK; | ||
1168 | |||
1169 | if ( | ||
1170 | NORMALIZE_GET_POINTER_CYCLE_BIT(get_value) | ||
1171 | == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index]) | ||
1172 | ) { | ||
1173 | return true; | ||
1174 | } | ||
1175 | |||
1176 | return false; | ||
1177 | } | ||
1178 | |||
1179 | /* --------------------------------------------------------------------------- */ | ||
1180 | |||
1181 | /** | ||
1182 | * This method processes a task completion notification. This is called from | ||
1183 | * within the controller completion handler. | ||
1184 | * @this_controller: | ||
1185 | * @completion_entry: | ||
1186 | * | ||
1187 | */ | ||
1188 | static void scic_sds_controller_task_completion( | ||
1189 | struct scic_sds_controller *this_controller, | ||
1190 | u32 completion_entry) | ||
1191 | { | ||
1192 | u32 index; | ||
1193 | struct scic_sds_request *io_request; | ||
1194 | |||
1195 | index = SCU_GET_COMPLETION_INDEX(completion_entry); | ||
1196 | io_request = this_controller->io_request_table[index]; | ||
1197 | |||
1198 | /* Make sure that we really want to process this IO request */ | ||
1199 | if ( | ||
1200 | (io_request != SCI_INVALID_HANDLE) | ||
1201 | && (io_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) | ||
1202 | && ( | ||
1203 | scic_sds_io_tag_get_sequence(io_request->io_tag) | ||
1204 | == this_controller->io_request_sequence[index] | ||
1205 | ) | ||
1206 | ) { | ||
1207 | /* Yep this is a valid io request pass it along to the io request handler */ | ||
1208 | scic_sds_io_request_tc_completion(io_request, completion_entry); | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | /** | ||
1213 | * This method processes an SDMA completion event. This is called from within | ||
1214 | * the controller completion handler. | ||
1215 | * @this_controller: | ||
1216 | * @completion_entry: | ||
1217 | * | ||
1218 | */ | ||
1219 | static void scic_sds_controller_sdma_completion( | ||
1220 | struct scic_sds_controller *this_controller, | ||
1221 | u32 completion_entry) | ||
1222 | { | ||
1223 | u32 index; | ||
1224 | struct scic_sds_request *io_request; | ||
1225 | struct scic_sds_remote_device *device; | ||
1226 | |||
1227 | index = SCU_GET_COMPLETION_INDEX(completion_entry); | ||
1228 | |||
1229 | switch (scu_get_command_request_type(completion_entry)) { | ||
1230 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC: | ||
1231 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC: | ||
1232 | io_request = this_controller->io_request_table[index]; | ||
1233 | dev_warn(scic_to_dev(this_controller), | ||
1234 | "%s: SCIC SDS Completion type SDMA %x for io request " | ||
1235 | "%p\n", | ||
1236 | __func__, | ||
1237 | completion_entry, | ||
1238 | io_request); | ||
1239 | /* @todo For a post TC operation we need to fail the IO | ||
1240 | * request | ||
1241 | */ | ||
1242 | break; | ||
1243 | |||
1244 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC: | ||
1245 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC: | ||
1246 | case SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC: | ||
1247 | device = this_controller->device_table[index]; | ||
1248 | dev_warn(scic_to_dev(this_controller), | ||
1249 | "%s: SCIC SDS Completion type SDMA %x for remote " | ||
1250 | "device %p\n", | ||
1251 | __func__, | ||
1252 | completion_entry, | ||
1253 | device); | ||
1254 | /* @todo For a port RNC operation we need to fail the | ||
1255 | * device | ||
1256 | */ | ||
1257 | break; | ||
1258 | |||
1259 | default: | ||
1260 | dev_warn(scic_to_dev(this_controller), | ||
1261 | "%s: SCIC SDS Completion unknown SDMA completion " | ||
1262 | "type %x\n", | ||
1263 | __func__, | ||
1264 | completion_entry); | ||
1265 | break; | ||
1266 | |||
1267 | } | ||
1268 | } | ||
1269 | |||
1270 | /** | ||
1271 | * | ||
1272 | * @this_controller: | ||
1273 | * @completion_entry: | ||
1274 | * | ||
1275 | * This method processes an unsolicited frame message. This is called from | ||
1276 | * within the controller completion handler. none | ||
1277 | */ | ||
1278 | static void scic_sds_controller_unsolicited_frame( | ||
1279 | struct scic_sds_controller *this_controller, | ||
1280 | u32 completion_entry) | ||
1281 | { | ||
1282 | u32 index; | ||
1283 | u32 frame_index; | ||
1284 | |||
1285 | struct scu_unsolicited_frame_header *frame_header; | ||
1286 | struct scic_sds_phy *phy; | ||
1287 | struct scic_sds_remote_device *device; | ||
1288 | |||
1289 | enum sci_status result = SCI_FAILURE; | ||
1290 | |||
1291 | frame_index = SCU_GET_FRAME_INDEX(completion_entry); | ||
1292 | |||
1293 | frame_header | ||
1294 | = this_controller->uf_control.buffers.array[frame_index].header; | ||
1295 | this_controller->uf_control.buffers.array[frame_index].state | ||
1296 | = UNSOLICITED_FRAME_IN_USE; | ||
1297 | |||
1298 | if (SCU_GET_FRAME_ERROR(completion_entry)) { | ||
1299 | /* | ||
1300 | * / @todo If the IAF frame or SIGNATURE FIS frame has an error will | ||
1301 | * / this cause a problem? We expect the phy initialization will | ||
1302 | * / fail if there is an error in the frame. */ | ||
1303 | scic_sds_controller_release_frame(this_controller, frame_index); | ||
1304 | return; | ||
1305 | } | ||
1306 | |||
1307 | if (frame_header->is_address_frame) { | ||
1308 | index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); | ||
1309 | phy = &this_controller->phy_table[index]; | ||
1310 | if (phy != NULL) { | ||
1311 | result = scic_sds_phy_frame_handler(phy, frame_index); | ||
1312 | } | ||
1313 | } else { | ||
1314 | |||
1315 | index = SCU_GET_COMPLETION_INDEX(completion_entry); | ||
1316 | |||
1317 | if (index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { | ||
1318 | /* | ||
1319 | * This is a signature fis or a frame from a direct attached SATA | ||
1320 | * device that has not yet been created. In either case forwared | ||
1321 | * the frame to the PE and let it take care of the frame data. */ | ||
1322 | index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); | ||
1323 | phy = &this_controller->phy_table[index]; | ||
1324 | result = scic_sds_phy_frame_handler(phy, frame_index); | ||
1325 | } else { | ||
1326 | if (index < this_controller->remote_node_entries) | ||
1327 | device = this_controller->device_table[index]; | ||
1328 | else | ||
1329 | device = NULL; | ||
1330 | |||
1331 | if (device != NULL) | ||
1332 | result = scic_sds_remote_device_frame_handler(device, frame_index); | ||
1333 | else | ||
1334 | scic_sds_controller_release_frame(this_controller, frame_index); | ||
1335 | } | ||
1336 | } | ||
1337 | |||
1338 | if (result != SCI_SUCCESS) { | ||
1339 | /* | ||
1340 | * / @todo Is there any reason to report some additional error message | ||
1341 | * / when we get this failure notifiction? */ | ||
1342 | } | ||
1343 | } | ||
1344 | |||
1345 | /** | ||
1346 | * This method processes an event completion entry. This is called from within | ||
1347 | * the controller completion handler. | ||
1348 | * @this_controller: | ||
1349 | * @completion_entry: | ||
1350 | * | ||
1351 | */ | ||
1352 | static void scic_sds_controller_event_completion( | ||
1353 | struct scic_sds_controller *this_controller, | ||
1354 | u32 completion_entry) | ||
1355 | { | ||
1356 | u32 index; | ||
1357 | struct scic_sds_request *io_request; | ||
1358 | struct scic_sds_remote_device *device; | ||
1359 | struct scic_sds_phy *phy; | ||
1360 | |||
1361 | index = SCU_GET_COMPLETION_INDEX(completion_entry); | ||
1362 | |||
1363 | switch (scu_get_event_type(completion_entry)) { | ||
1364 | case SCU_EVENT_TYPE_SMU_COMMAND_ERROR: | ||
1365 | /* / @todo The driver did something wrong and we need to fix the condtion. */ | ||
1366 | dev_err(scic_to_dev(this_controller), | ||
1367 | "%s: SCIC Controller 0x%p received SMU command error " | ||
1368 | "0x%x\n", | ||
1369 | __func__, | ||
1370 | this_controller, | ||
1371 | completion_entry); | ||
1372 | break; | ||
1373 | |||
1374 | case SCU_EVENT_TYPE_SMU_PCQ_ERROR: | ||
1375 | case SCU_EVENT_TYPE_SMU_ERROR: | ||
1376 | case SCU_EVENT_TYPE_FATAL_MEMORY_ERROR: | ||
1377 | /* | ||
1378 | * / @todo This is a hardware failure and its likely that we want to | ||
1379 | * / reset the controller. */ | ||
1380 | dev_err(scic_to_dev(this_controller), | ||
1381 | "%s: SCIC Controller 0x%p received fatal controller " | ||
1382 | "event 0x%x\n", | ||
1383 | __func__, | ||
1384 | this_controller, | ||
1385 | completion_entry); | ||
1386 | break; | ||
1387 | |||
1388 | case SCU_EVENT_TYPE_TRANSPORT_ERROR: | ||
1389 | io_request = this_controller->io_request_table[index]; | ||
1390 | scic_sds_io_request_event_handler(io_request, completion_entry); | ||
1391 | break; | ||
1392 | |||
1393 | case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: | ||
1394 | switch (scu_get_event_specifier(completion_entry)) { | ||
1395 | case SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE: | ||
1396 | case SCU_EVENT_SPECIFIC_TASK_TIMEOUT: | ||
1397 | io_request = this_controller->io_request_table[index]; | ||
1398 | if (io_request != SCI_INVALID_HANDLE) | ||
1399 | scic_sds_io_request_event_handler(io_request, completion_entry); | ||
1400 | else | ||
1401 | dev_warn(scic_to_dev(this_controller), | ||
1402 | "%s: SCIC Controller 0x%p received " | ||
1403 | "event 0x%x for io request object " | ||
1404 | "that doesnt exist.\n", | ||
1405 | __func__, | ||
1406 | this_controller, | ||
1407 | completion_entry); | ||
1408 | |||
1409 | break; | ||
1410 | |||
1411 | case SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT: | ||
1412 | device = this_controller->device_table[index]; | ||
1413 | if (device != SCI_INVALID_HANDLE) | ||
1414 | scic_sds_remote_device_event_handler(device, completion_entry); | ||
1415 | else | ||
1416 | dev_warn(scic_to_dev(this_controller), | ||
1417 | "%s: SCIC Controller 0x%p received " | ||
1418 | "event 0x%x for remote device object " | ||
1419 | "that doesnt exist.\n", | ||
1420 | __func__, | ||
1421 | this_controller, | ||
1422 | completion_entry); | ||
1423 | |||
1424 | break; | ||
1425 | } | ||
1426 | break; | ||
1427 | |||
1428 | case SCU_EVENT_TYPE_BROADCAST_CHANGE: | ||
1429 | /* | ||
1430 | * direct the broadcast change event to the phy first and then let | ||
1431 | * the phy redirect the broadcast change to the port object */ | ||
1432 | case SCU_EVENT_TYPE_ERR_CNT_EVENT: | ||
1433 | /* | ||
1434 | * direct error counter event to the phy object since that is where | ||
1435 | * we get the event notification. This is a type 4 event. */ | ||
1436 | case SCU_EVENT_TYPE_OSSP_EVENT: | ||
1437 | index = SCU_GET_PROTOCOL_ENGINE_INDEX(completion_entry); | ||
1438 | phy = &this_controller->phy_table[index]; | ||
1439 | scic_sds_phy_event_handler(phy, completion_entry); | ||
1440 | break; | ||
1441 | |||
1442 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX: | ||
1443 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: | ||
1444 | case SCU_EVENT_TYPE_RNC_OPS_MISC: | ||
1445 | if (index < this_controller->remote_node_entries) { | ||
1446 | device = this_controller->device_table[index]; | ||
1447 | |||
1448 | if (device != NULL) | ||
1449 | scic_sds_remote_device_event_handler(device, completion_entry); | ||
1450 | } else | ||
1451 | dev_err(scic_to_dev(this_controller), | ||
1452 | "%s: SCIC Controller 0x%p received event 0x%x " | ||
1453 | "for remote device object 0x%0x that doesnt " | ||
1454 | "exist.\n", | ||
1455 | __func__, | ||
1456 | this_controller, | ||
1457 | completion_entry, | ||
1458 | index); | ||
1459 | |||
1460 | break; | ||
1461 | |||
1462 | default: | ||
1463 | dev_warn(scic_to_dev(this_controller), | ||
1464 | "%s: SCIC Controller received unknown event code %x\n", | ||
1465 | __func__, | ||
1466 | completion_entry); | ||
1467 | break; | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | /** | ||
1472 | * This method is a private routine for processing the completion queue entries. | ||
1473 | * @this_controller: | ||
1474 | * | ||
1475 | */ | ||
1476 | static void scic_sds_controller_process_completions( | ||
1477 | struct scic_sds_controller *this_controller) | ||
1478 | { | ||
1479 | u32 completion_count = 0; | ||
1480 | u32 completion_entry; | ||
1481 | u32 get_index; | ||
1482 | u32 get_cycle; | ||
1483 | u32 event_index; | ||
1484 | u32 event_cycle; | ||
1485 | |||
1486 | dev_dbg(scic_to_dev(this_controller), | ||
1487 | "%s: completion queue begining get:0x%08x\n", | ||
1488 | __func__, | ||
1489 | this_controller->completion_queue_get); | ||
1490 | |||
1491 | /* Get the component parts of the completion queue */ | ||
1492 | get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get); | ||
1493 | get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get; | ||
1494 | |||
1495 | event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get); | ||
1496 | event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get; | ||
1497 | |||
1498 | while ( | ||
1499 | NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) | ||
1500 | == COMPLETION_QUEUE_CYCLE_BIT(this_controller->completion_queue[get_index]) | ||
1501 | ) { | ||
1502 | completion_count++; | ||
1503 | |||
1504 | completion_entry = this_controller->completion_queue[get_index]; | ||
1505 | INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle); | ||
1506 | |||
1507 | dev_dbg(scic_to_dev(this_controller), | ||
1508 | "%s: completion queue entry:0x%08x\n", | ||
1509 | __func__, | ||
1510 | completion_entry); | ||
1511 | |||
1512 | switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { | ||
1513 | case SCU_COMPLETION_TYPE_TASK: | ||
1514 | scic_sds_controller_task_completion(this_controller, completion_entry); | ||
1515 | break; | ||
1516 | |||
1517 | case SCU_COMPLETION_TYPE_SDMA: | ||
1518 | scic_sds_controller_sdma_completion(this_controller, completion_entry); | ||
1519 | break; | ||
1520 | |||
1521 | case SCU_COMPLETION_TYPE_UFI: | ||
1522 | scic_sds_controller_unsolicited_frame(this_controller, completion_entry); | ||
1523 | break; | ||
1524 | |||
1525 | case SCU_COMPLETION_TYPE_EVENT: | ||
1526 | INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); | ||
1527 | scic_sds_controller_event_completion(this_controller, completion_entry); | ||
1528 | break; | ||
1529 | |||
1530 | case SCU_COMPLETION_TYPE_NOTIFY: | ||
1531 | /* | ||
1532 | * Presently we do the same thing with a notify event that we do with the | ||
1533 | * other event codes. */ | ||
1534 | INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); | ||
1535 | scic_sds_controller_event_completion(this_controller, completion_entry); | ||
1536 | break; | ||
1537 | |||
1538 | default: | ||
1539 | dev_warn(scic_to_dev(this_controller), | ||
1540 | "%s: SCIC Controller received unknown " | ||
1541 | "completion type %x\n", | ||
1542 | __func__, | ||
1543 | completion_entry); | ||
1544 | break; | ||
1545 | } | ||
1546 | } | ||
1547 | |||
1548 | /* Update the get register if we completed one or more entries */ | ||
1549 | if (completion_count > 0) { | ||
1550 | this_controller->completion_queue_get = | ||
1551 | SMU_CQGR_GEN_BIT(ENABLE) | ||
1552 | | SMU_CQGR_GEN_BIT(EVENT_ENABLE) | ||
1553 | | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) | ||
1554 | | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); | ||
1555 | |||
1556 | SMU_CQGR_WRITE(this_controller, | ||
1557 | this_controller->completion_queue_get); | ||
1558 | } | ||
1559 | |||
1560 | dev_dbg(scic_to_dev(this_controller), | ||
1561 | "%s: completion queue ending get:0x%08x\n", | ||
1562 | __func__, | ||
1563 | this_controller->completion_queue_get); | ||
1564 | |||
1565 | } | ||
1566 | |||
1567 | /** | ||
1568 | * This method is a private routine for processing the completion queue entries. | ||
1569 | * @this_controller: | ||
1570 | * | ||
1571 | */ | ||
1572 | static void scic_sds_controller_transitioned_process_completions( | ||
1573 | struct scic_sds_controller *this_controller) | ||
1574 | { | ||
1575 | u32 completion_count = 0; | ||
1576 | u32 completion_entry; | ||
1577 | u32 get_index; | ||
1578 | u32 get_cycle; | ||
1579 | u32 event_index; | ||
1580 | u32 event_cycle; | ||
1581 | |||
1582 | dev_dbg(scic_to_dev(this_controller), | ||
1583 | "%s: completion queue begining get:0x%08x\n", | ||
1584 | __func__, | ||
1585 | this_controller->completion_queue_get); | ||
1586 | |||
1587 | /* Get the component parts of the completion queue */ | ||
1588 | get_index = NORMALIZE_GET_POINTER(this_controller->completion_queue_get); | ||
1589 | get_cycle = SMU_CQGR_CYCLE_BIT & this_controller->completion_queue_get; | ||
1590 | |||
1591 | event_index = NORMALIZE_EVENT_POINTER(this_controller->completion_queue_get); | ||
1592 | event_cycle = SMU_CQGR_EVENT_CYCLE_BIT & this_controller->completion_queue_get; | ||
1593 | |||
1594 | while ( | ||
1595 | NORMALIZE_GET_POINTER_CYCLE_BIT(get_cycle) | ||
1596 | == COMPLETION_QUEUE_CYCLE_BIT( | ||
1597 | this_controller->completion_queue[get_index]) | ||
1598 | ) { | ||
1599 | completion_count++; | ||
1600 | |||
1601 | completion_entry = this_controller->completion_queue[get_index]; | ||
1602 | INCREMENT_COMPLETION_QUEUE_GET(this_controller, get_index, get_cycle); | ||
1603 | |||
1604 | dev_dbg(scic_to_dev(this_controller), | ||
1605 | "%s: completion queue entry:0x%08x\n", | ||
1606 | __func__, | ||
1607 | completion_entry); | ||
1608 | |||
1609 | switch (SCU_GET_COMPLETION_TYPE(completion_entry)) { | ||
1610 | case SCU_COMPLETION_TYPE_TASK: | ||
1611 | scic_sds_controller_task_completion(this_controller, completion_entry); | ||
1612 | break; | ||
1613 | |||
1614 | case SCU_COMPLETION_TYPE_NOTIFY: | ||
1615 | case SCU_COMPLETION_TYPE_EVENT: | ||
1616 | /* | ||
1617 | * Presently we do the same thing with a notify event that we | ||
1618 | * do with the other event codes. */ | ||
1619 | INCREMENT_EVENT_QUEUE_GET(this_controller, event_index, event_cycle); | ||
1620 | /* Fall-through */ | ||
1621 | |||
1622 | case SCU_COMPLETION_TYPE_SDMA: | ||
1623 | case SCU_COMPLETION_TYPE_UFI: | ||
1624 | default: | ||
1625 | dev_warn(scic_to_dev(this_controller), | ||
1626 | "%s: SCIC Controller ignoring completion type " | ||
1627 | "%x\n", | ||
1628 | __func__, | ||
1629 | completion_entry); | ||
1630 | break; | ||
1631 | } | ||
1632 | } | ||
1633 | |||
1634 | /* Update the get register if we completed one or more entries */ | ||
1635 | if (completion_count > 0) { | ||
1636 | this_controller->completion_queue_get = | ||
1637 | SMU_CQGR_GEN_BIT(ENABLE) | ||
1638 | | SMU_CQGR_GEN_BIT(EVENT_ENABLE) | ||
1639 | | event_cycle | SMU_CQGR_GEN_VAL(EVENT_POINTER, event_index) | ||
1640 | | get_cycle | SMU_CQGR_GEN_VAL(POINTER, get_index); | ||
1641 | |||
1642 | SMU_CQGR_WRITE(this_controller, this_controller->completion_queue_get); | ||
1643 | } | ||
1644 | |||
1645 | dev_dbg(scic_to_dev(this_controller), | ||
1646 | "%s: completion queue ending get:0x%08x\n", | ||
1647 | __func__, | ||
1648 | this_controller->completion_queue_get); | ||
1649 | } | ||
1650 | |||
1651 | /* | ||
1652 | * ****************************************************************************- | ||
1653 | * * SCIC SDS Controller Interrupt and Completion functions | ||
1654 | * ****************************************************************************- */ | ||
1655 | |||
1656 | /** | ||
1657 | * This method provides standard (common) processing of interrupts for polling | ||
1658 | * and legacy based interrupts. | ||
1659 | * @controller: | ||
1660 | * @interrupt_status: | ||
1661 | * | ||
1662 | * This method returns a boolean (bool) indication as to whether an completions | ||
1663 | * are pending to be processed. true if an interrupt is to be processed false | ||
1664 | * if no interrupt was pending | ||
1665 | */ | ||
1666 | static bool scic_sds_controller_standard_interrupt_handler( | ||
1667 | struct scic_sds_controller *this_controller, | ||
1668 | u32 interrupt_status) | ||
1669 | { | ||
1670 | bool is_completion_needed = false; | ||
1671 | |||
1672 | if ((interrupt_status & SMU_ISR_QUEUE_ERROR) || | ||
1673 | ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && | ||
1674 | (!scic_sds_controller_completion_queue_has_entries( | ||
1675 | this_controller)))) { | ||
1676 | /* | ||
1677 | * We have a fatal error on the read of the completion queue bar | ||
1678 | * OR | ||
1679 | * We have a fatal error there is nothing in the completion queue | ||
1680 | * but we have a report from the hardware that the queue is full | ||
1681 | * / @todo how do we request the a controller reset */ | ||
1682 | is_completion_needed = true; | ||
1683 | this_controller->encountered_fatal_error = true; | ||
1684 | } | ||
1685 | |||
1686 | if (scic_sds_controller_completion_queue_has_entries(this_controller)) { | ||
1687 | is_completion_needed = true; | ||
1688 | } | ||
1689 | |||
1690 | return is_completion_needed; | ||
1691 | } | ||
1692 | |||
1693 | /** | ||
1694 | * This is the method provided to handle polling for interrupts for the | ||
1695 | * controller object. | ||
1696 | * | ||
1697 | * bool true if an interrupt is to be processed false if no interrupt was | ||
1698 | * pending | ||
1699 | */ | ||
1700 | static bool scic_sds_controller_polling_interrupt_handler( | ||
1701 | struct scic_sds_controller *scic) | ||
1702 | { | ||
1703 | u32 interrupt_status; | ||
1704 | |||
1705 | /* | ||
1706 | * In INTERRUPT_POLLING_MODE we exit the interrupt handler if the | ||
1707 | * hardware indicates nothing is pending. Since we are not being | ||
1708 | * called from a real interrupt, we don't want to confuse the hardware | ||
1709 | * by servicing the completion queue before the hardware indicates it | ||
1710 | * is ready. We'll simply wait for another polling interval and check | ||
1711 | * again. | ||
1712 | */ | ||
1713 | interrupt_status = SMU_ISR_READ(scic); | ||
1714 | if ((interrupt_status & | ||
1715 | (SMU_ISR_COMPLETION | | ||
1716 | SMU_ISR_QUEUE_ERROR | | ||
1717 | SMU_ISR_QUEUE_SUSPEND)) == 0) { | ||
1718 | return false; | ||
1719 | } | ||
1720 | |||
1721 | return scic_sds_controller_standard_interrupt_handler( | ||
1722 | scic, interrupt_status); | ||
1723 | } | ||
1724 | |||
1725 | /** | ||
1726 | * This is the method provided to handle completions when interrupt polling is | ||
1727 | * in use. | ||
1728 | */ | ||
1729 | static void scic_sds_controller_polling_completion_handler( | ||
1730 | struct scic_sds_controller *scic) | ||
1731 | { | ||
1732 | if (scic->encountered_fatal_error == true) { | ||
1733 | dev_err(scic_to_dev(scic), | ||
1734 | "%s: SCIC Controller has encountered a fatal error.\n", | ||
1735 | __func__); | ||
1736 | |||
1737 | sci_base_state_machine_change_state( | ||
1738 | scic_sds_controller_get_base_state_machine(scic), | ||
1739 | SCI_BASE_CONTROLLER_STATE_FAILED); | ||
1740 | } else if (scic_sds_controller_completion_queue_has_entries(scic)) { | ||
1741 | if (scic->restrict_completions == false) | ||
1742 | scic_sds_controller_process_completions(scic); | ||
1743 | else | ||
1744 | scic_sds_controller_transitioned_process_completions( | ||
1745 | scic); | ||
1746 | } | ||
1747 | |||
1748 | /* | ||
1749 | * The interrupt handler does not adjust the CQ's | ||
1750 | * get pointer. So, SCU's INTx pin stays asserted during the | ||
1751 | * interrupt handler even though it tries to clear the interrupt | ||
1752 | * source. Therefore, the completion handler must ensure that the | ||
1753 | * interrupt source is cleared. Otherwise, we get a spurious | ||
1754 | * interrupt for which the interrupt handler will not issue a | ||
1755 | * corresponding completion event. Also, we unmask interrupts. | ||
1756 | */ | ||
1757 | SMU_ISR_WRITE( | ||
1758 | scic, | ||
1759 | (u32)(SMU_ISR_COMPLETION | SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND) | ||
1760 | ); | ||
1761 | } | ||
1762 | |||
1763 | /** | ||
1764 | * This is the method provided to handle legacy interrupts for the controller | ||
1765 | * object. | ||
1766 | * | ||
1767 | * bool true if an interrupt is processed false if no interrupt was processed | ||
1768 | */ | ||
1769 | static bool scic_sds_controller_legacy_interrupt_handler( | ||
1770 | struct scic_sds_controller *scic) | ||
1771 | { | ||
1772 | u32 interrupt_status; | ||
1773 | bool is_completion_needed; | ||
1774 | |||
1775 | interrupt_status = SMU_ISR_READ(scic); | ||
1776 | is_completion_needed = scic_sds_controller_standard_interrupt_handler( | ||
1777 | scic, interrupt_status); | ||
1778 | |||
1779 | return is_completion_needed; | ||
1780 | } | ||
1781 | |||
1782 | |||
1783 | /** | ||
1784 | * This is the method provided to handle legacy completions it is expected that | ||
1785 | * the SCI User will call this completion handler anytime the interrupt | ||
1786 | * handler reports that it has handled an interrupt. | ||
1787 | */ | ||
1788 | static void scic_sds_controller_legacy_completion_handler( | ||
1789 | struct scic_sds_controller *scic) | ||
1790 | { | ||
1791 | scic_sds_controller_polling_completion_handler(scic); | ||
1792 | SMU_IMR_WRITE(scic, 0x00000000); | ||
1793 | } | ||
1794 | |||
1795 | /** | ||
1796 | * This is the method provided to handle an MSIX interrupt message when there | ||
1797 | * is just a single MSIX message being provided by the hardware. This mode | ||
1798 | * of operation is single vector mode. | ||
1799 | * | ||
1800 | * bool true if an interrupt is processed false if no interrupt was processed | ||
1801 | */ | ||
1802 | static bool scic_sds_controller_single_vector_interrupt_handler( | ||
1803 | struct scic_sds_controller *scic) | ||
1804 | { | ||
1805 | u32 interrupt_status; | ||
1806 | |||
1807 | /* | ||
1808 | * Mask the interrupts | ||
1809 | * There is a race in the hardware that could cause us not to be notified | ||
1810 | * of an interrupt completion if we do not take this step. We will unmask | ||
1811 | * the interrupts in the completion routine. */ | ||
1812 | SMU_IMR_WRITE(scic, 0xFFFFFFFF); | ||
1813 | |||
1814 | interrupt_status = SMU_ISR_READ(scic); | ||
1815 | interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); | ||
1816 | |||
1817 | if ((interrupt_status == 0) && | ||
1818 | scic_sds_controller_completion_queue_has_entries(scic)) { | ||
1819 | /* | ||
1820 | * There is at least one completion queue entry to process so we can | ||
1821 | * return a success and ignore for now the case of an error interrupt */ | ||
1822 | SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); | ||
1823 | return true; | ||
1824 | } | ||
1825 | |||
1826 | if (interrupt_status != 0) { | ||
1827 | /* | ||
1828 | * There is an error interrupt pending so let it through and handle | ||
1829 | * in the callback */ | ||
1830 | return true; | ||
1831 | } | ||
1832 | |||
1833 | /* | ||
1834 | * Clear any offending interrupts since we could not find any to handle | ||
1835 | * and unmask them all */ | ||
1836 | SMU_ISR_WRITE(scic, 0x00000000); | ||
1837 | SMU_IMR_WRITE(scic, 0x00000000); | ||
1838 | |||
1839 | return false; | ||
1840 | } | ||
1841 | |||
1842 | /** | ||
1843 | * This is the method provided to handle completions for a single MSIX message. | ||
1844 | */ | ||
1845 | static void scic_sds_controller_single_vector_completion_handler( | ||
1846 | struct scic_sds_controller *scic) | ||
1847 | { | ||
1848 | u32 interrupt_status; | ||
1849 | |||
1850 | interrupt_status = SMU_ISR_READ(scic); | ||
1851 | interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); | ||
1852 | |||
1853 | if (interrupt_status & SMU_ISR_QUEUE_ERROR) { | ||
1854 | dev_err(scic_to_dev(scic), | ||
1855 | "%s: SCIC Controller has encountered a fatal error.\n", | ||
1856 | __func__); | ||
1857 | |||
1858 | /* | ||
1859 | * We have a fatal condition and must reset the controller | ||
1860 | * Leave the interrupt mask in place and get the controller reset */ | ||
1861 | sci_base_state_machine_change_state( | ||
1862 | scic_sds_controller_get_base_state_machine(scic), | ||
1863 | SCI_BASE_CONTROLLER_STATE_FAILED); | ||
1864 | return; | ||
1865 | } | ||
1866 | |||
1867 | if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && | ||
1868 | !scic_sds_controller_completion_queue_has_entries(scic)) { | ||
1869 | dev_err(scic_to_dev(scic), | ||
1870 | "%s: SCIC Controller has encountered a fatal error.\n", | ||
1871 | __func__); | ||
1872 | |||
1873 | /* | ||
1874 | * We have a fatal condtion and must reset the controller | ||
1875 | * Leave the interrupt mask in place and get the controller reset */ | ||
1876 | sci_base_state_machine_change_state( | ||
1877 | scic_sds_controller_get_base_state_machine(scic), | ||
1878 | SCI_BASE_CONTROLLER_STATE_FAILED); | ||
1879 | return; | ||
1880 | } | ||
1881 | |||
1882 | if (scic_sds_controller_completion_queue_has_entries(scic)) { | ||
1883 | scic_sds_controller_process_completions(scic); | ||
1884 | |||
1885 | /* | ||
1886 | * We dont care which interrupt got us to processing the completion queu | ||
1887 | * so clear them both. */ | ||
1888 | SMU_ISR_WRITE( | ||
1889 | scic, | ||
1890 | (SMU_ISR_COMPLETION | SMU_ISR_QUEUE_SUSPEND)); | ||
1891 | } | ||
1892 | |||
1893 | SMU_IMR_WRITE(scic, 0x00000000); | ||
1894 | } | ||
1895 | |||
1896 | /** | ||
1897 | * This is the method provided to handle a MSIX message for a normal completion. | ||
1898 | * | ||
1899 | * bool true if an interrupt is processed false if no interrupt was processed | ||
1900 | */ | ||
1901 | static bool scic_sds_controller_normal_vector_interrupt_handler( | ||
1902 | struct scic_sds_controller *scic) | ||
1903 | { | ||
1904 | if (scic_sds_controller_completion_queue_has_entries(scic)) { | ||
1905 | return true; | ||
1906 | } else { | ||
1907 | /* | ||
1908 | * we have a spurious interrupt it could be that we have already | ||
1909 | * emptied the completion queue from a previous interrupt */ | ||
1910 | SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); | ||
1911 | |||
1912 | /* | ||
1913 | * There is a race in the hardware that could cause us not to be notified | ||
1914 | * of an interrupt completion if we do not take this step. We will mask | ||
1915 | * then unmask the interrupts so if there is another interrupt pending | ||
1916 | * the clearing of the interrupt source we get the next interrupt message. */ | ||
1917 | SMU_IMR_WRITE(scic, 0xFF000000); | ||
1918 | SMU_IMR_WRITE(scic, 0x00000000); | ||
1919 | } | ||
1920 | |||
1921 | return false; | ||
1922 | } | ||
1923 | |||
1924 | /** | ||
1925 | * This is the method provided to handle the completions for a normal MSIX | ||
1926 | * message. | ||
1927 | */ | ||
1928 | static void scic_sds_controller_normal_vector_completion_handler( | ||
1929 | struct scic_sds_controller *scic) | ||
1930 | { | ||
1931 | /* Empty out the completion queue */ | ||
1932 | if (scic_sds_controller_completion_queue_has_entries(scic)) | ||
1933 | scic_sds_controller_process_completions(scic); | ||
1934 | |||
1935 | /* Clear the interrupt and enable all interrupts again */ | ||
1936 | SMU_ISR_WRITE(scic, SMU_ISR_COMPLETION); | ||
1937 | /* Could we write the value of SMU_ISR_COMPLETION? */ | ||
1938 | SMU_IMR_WRITE(scic, 0xFF000000); | ||
1939 | SMU_IMR_WRITE(scic, 0x00000000); | ||
1940 | } | ||
1941 | |||
1942 | /** | ||
1943 | * This is the method provided to handle the error MSIX message interrupt. | ||
1944 | * This is the normal operating mode for the hardware if MSIX is enabled. | ||
1945 | * | ||
1946 | * bool true if an interrupt is processed false if no interrupt was processed | ||
1947 | */ | ||
1948 | static bool scic_sds_controller_error_vector_interrupt_handler( | ||
1949 | struct scic_sds_controller *scic) | ||
1950 | { | ||
1951 | u32 interrupt_status; | ||
1952 | |||
1953 | interrupt_status = SMU_ISR_READ(scic); | ||
1954 | interrupt_status &= (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND); | ||
1955 | |||
1956 | if (interrupt_status != 0) { | ||
1957 | /* | ||
1958 | * There is an error interrupt pending so let it through and handle | ||
1959 | * in the callback */ | ||
1960 | return true; | ||
1961 | } | ||
1962 | |||
1963 | /* | ||
1964 | * There is a race in the hardware that could cause us not to be notified | ||
1965 | * of an interrupt completion if we do not take this step. We will mask | ||
1966 | * then unmask the error interrupts so if there was another interrupt | ||
1967 | * pending we will be notified. | ||
1968 | * Could we write the value of (SMU_ISR_QUEUE_ERROR | SMU_ISR_QUEUE_SUSPEND)? */ | ||
1969 | SMU_IMR_WRITE(scic, 0x000000FF); | ||
1970 | SMU_IMR_WRITE(scic, 0x00000000); | ||
1971 | |||
1972 | return false; | ||
1973 | } | ||
1974 | |||
1975 | /** | ||
1976 | * This is the method provided to handle the error completions when the | ||
1977 | * hardware is using two MSIX messages. | ||
1978 | */ | ||
1979 | static void scic_sds_controller_error_vector_completion_handler( | ||
1980 | struct scic_sds_controller *scic) | ||
1981 | { | ||
1982 | u32 interrupt_status; | ||
1983 | |||
1984 | interrupt_status = SMU_ISR_READ(scic); | ||
1985 | |||
1986 | if ((interrupt_status & SMU_ISR_QUEUE_SUSPEND) && | ||
1987 | scic_sds_controller_completion_queue_has_entries(scic)) { | ||
1988 | |||
1989 | scic_sds_controller_process_completions(scic); | ||
1990 | SMU_ISR_WRITE(scic, SMU_ISR_QUEUE_SUSPEND); | ||
1991 | |||
1992 | } else { | ||
1993 | dev_err(scic_to_dev(scic), | ||
1994 | "%s: SCIC Controller reports CRC error on completion " | ||
1995 | "ISR %x\n", | ||
1996 | __func__, | ||
1997 | interrupt_status); | ||
1998 | |||
1999 | sci_base_state_machine_change_state( | ||
2000 | scic_sds_controller_get_base_state_machine(scic), | ||
2001 | SCI_BASE_CONTROLLER_STATE_FAILED); | ||
2002 | |||
2003 | return; | ||
2004 | } | ||
2005 | |||
2006 | /* | ||
2007 | * If we dont process any completions I am not sure that we want to do this. | ||
2008 | * We are in the middle of a hardware fault and should probably be reset. */ | ||
2009 | SMU_IMR_WRITE(scic, 0x00000000); | ||
2010 | } | ||
2011 | |||
2012 | |||
2013 | /* | ||
2014 | * ****************************************************************************- | ||
2015 | * * SCIC SDS Controller External Methods | ||
2016 | * ****************************************************************************- */ | ||
2017 | |||
2018 | /** | ||
2019 | * This method returns the sizeof the SCIC SDS Controller Object | ||
2020 | */ | ||
2021 | u32 scic_sds_controller_get_object_size(void) | ||
2022 | { | ||
2023 | return sizeof(struct scic_sds_controller); | ||
2024 | } | ||
2025 | |||
2026 | |||
2027 | void scic_sds_controller_link_up( | ||
2028 | struct scic_sds_controller *scic, | ||
2029 | struct scic_sds_port *sci_port, | ||
2030 | struct scic_sds_phy *sci_phy) | ||
2031 | { | ||
2032 | scic_sds_controller_phy_handler_t link_up; | ||
2033 | u32 state; | ||
2034 | |||
2035 | state = scic->parent.state_machine.current_state_id; | ||
2036 | link_up = scic_sds_controller_state_handler_table[state].link_up; | ||
2037 | |||
2038 | if (link_up) | ||
2039 | link_up(scic, sci_port, sci_phy); | ||
2040 | else | ||
2041 | dev_warn(scic_to_dev(scic), | ||
2042 | "%s: SCIC Controller linkup event from phy %d in " | ||
2043 | "unexpected state %d\n", | ||
2044 | __func__, | ||
2045 | sci_phy->phy_index, | ||
2046 | sci_base_state_machine_get_state( | ||
2047 | scic_sds_controller_get_base_state_machine( | ||
2048 | scic))); | ||
2049 | } | ||
2050 | |||
2051 | |||
2052 | void scic_sds_controller_link_down( | ||
2053 | struct scic_sds_controller *scic, | ||
2054 | struct scic_sds_port *sci_port, | ||
2055 | struct scic_sds_phy *sci_phy) | ||
2056 | { | ||
2057 | u32 state; | ||
2058 | scic_sds_controller_phy_handler_t link_down; | ||
2059 | |||
2060 | state = scic->parent.state_machine.current_state_id; | ||
2061 | link_down = scic_sds_controller_state_handler_table[state].link_down; | ||
2062 | |||
2063 | if (link_down) | ||
2064 | link_down(scic, sci_port, sci_phy); | ||
2065 | else | ||
2066 | dev_warn(scic_to_dev(scic), | ||
2067 | "%s: SCIC Controller linkdown event from phy %d in " | ||
2068 | "unexpected state %d\n", | ||
2069 | __func__, | ||
2070 | sci_phy->phy_index, | ||
2071 | sci_base_state_machine_get_state( | ||
2072 | scic_sds_controller_get_base_state_machine( | ||
2073 | scic))); | ||
2074 | } | ||
2075 | |||
2076 | /** | ||
2077 | * This method will write to the SCU PCP register the request value. The method | ||
2078 | * is used to suspend/resume ports, devices, and phys. | ||
2079 | * @this_controller: | ||
2080 | * | ||
2081 | * | ||
2082 | */ | ||
2083 | void scic_sds_controller_post_request( | ||
2084 | struct scic_sds_controller *this_controller, | ||
2085 | u32 request) | ||
2086 | { | ||
2087 | dev_dbg(scic_to_dev(this_controller), | ||
2088 | "%s: SCIC Controller 0x%p post request 0x%08x\n", | ||
2089 | __func__, | ||
2090 | this_controller, | ||
2091 | request); | ||
2092 | |||
2093 | SMU_PCP_WRITE(this_controller, request); | ||
2094 | } | ||
2095 | |||
2096 | /** | ||
2097 | * This method will copy the soft copy of the task context into the physical | ||
2098 | * memory accessible by the controller. | ||
2099 | * @this_controller: This parameter specifies the controller for which to copy | ||
2100 | * the task context. | ||
2101 | * @this_request: This parameter specifies the request for which the task | ||
2102 | * context is being copied. | ||
2103 | * | ||
2104 | * After this call is made the SCIC_SDS_IO_REQUEST object will always point to | ||
2105 | * the physical memory version of the task context. Thus, all subsequent | ||
2106 | * updates to the task context are performed in the TC table (i.e. DMAable | ||
2107 | * memory). none | ||
2108 | */ | ||
2109 | void scic_sds_controller_copy_task_context( | ||
2110 | struct scic_sds_controller *this_controller, | ||
2111 | struct scic_sds_request *this_request) | ||
2112 | { | ||
2113 | struct scu_task_context *task_context_buffer; | ||
2114 | |||
2115 | task_context_buffer = scic_sds_controller_get_task_context_buffer( | ||
2116 | this_controller, this_request->io_tag | ||
2117 | ); | ||
2118 | |||
2119 | memcpy( | ||
2120 | task_context_buffer, | ||
2121 | this_request->task_context_buffer, | ||
2122 | SCI_FIELD_OFFSET(struct scu_task_context, sgl_snapshot_ac) | ||
2123 | ); | ||
2124 | |||
2125 | /* | ||
2126 | * Now that the soft copy of the TC has been copied into the TC | ||
2127 | * table accessible by the silicon. Thus, any further changes to | ||
2128 | * the TC (e.g. TC termination) occur in the appropriate location. */ | ||
2129 | this_request->task_context_buffer = task_context_buffer; | ||
2130 | } | ||
2131 | |||
2132 | /** | ||
2133 | * This method returns the task context buffer for the given io tag. | ||
2134 | * @this_controller: | ||
2135 | * @io_tag: | ||
2136 | * | ||
2137 | * struct scu_task_context* | ||
2138 | */ | ||
2139 | struct scu_task_context *scic_sds_controller_get_task_context_buffer( | ||
2140 | struct scic_sds_controller *this_controller, | ||
2141 | u16 io_tag | ||
2142 | ) { | ||
2143 | u16 task_index = scic_sds_io_tag_get_index(io_tag); | ||
2144 | |||
2145 | if (task_index < this_controller->task_context_entries) { | ||
2146 | return &this_controller->task_context_table[task_index]; | ||
2147 | } | ||
2148 | |||
2149 | return NULL; | ||
2150 | } | ||
2151 | |||
2152 | /** | ||
2153 | * This method returnst the sequence value from the io tag value | ||
2154 | * @this_controller: | ||
2155 | * @io_tag: | ||
2156 | * | ||
2157 | * u16 | ||
2158 | */ | ||
2159 | |||
2160 | /** | ||
2161 | * This method returns the IO request associated with the tag value | ||
2162 | * @this_controller: | ||
2163 | * @io_tag: | ||
2164 | * | ||
2165 | * SCIC_SDS_IO_REQUEST_T* NULL if there is no valid IO request at the tag value | ||
2166 | */ | ||
2167 | struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( | ||
2168 | struct scic_sds_controller *this_controller, | ||
2169 | u16 io_tag | ||
2170 | ) { | ||
2171 | u16 task_index; | ||
2172 | u16 task_sequence; | ||
2173 | |||
2174 | task_index = scic_sds_io_tag_get_index(io_tag); | ||
2175 | |||
2176 | if (task_index < this_controller->task_context_entries) { | ||
2177 | if (this_controller->io_request_table[task_index] != SCI_INVALID_HANDLE) { | ||
2178 | task_sequence = scic_sds_io_tag_get_sequence(io_tag); | ||
2179 | |||
2180 | if (task_sequence == this_controller->io_request_sequence[task_index]) { | ||
2181 | return this_controller->io_request_table[task_index]; | ||
2182 | } | ||
2183 | } | ||
2184 | } | ||
2185 | |||
2186 | return SCI_INVALID_HANDLE; | ||
2187 | } | ||
2188 | |||
2189 | /** | ||
2190 | * This method allocates remote node index and the reserves the remote node | ||
2191 | * context space for use. This method can fail if there are no more remote | ||
2192 | * node index available. | ||
2193 | * @this_controller: This is the controller object which contains the set of | ||
2194 | * free remote node ids | ||
2195 | * @the_devce: This is the device object which is requesting the a remote node | ||
2196 | * id | ||
2197 | * @node_id: This is the remote node id that is assinged to the device if one | ||
2198 | * is available | ||
2199 | * | ||
2200 | * enum sci_status SCI_FAILURE_OUT_OF_RESOURCES if there are no available remote | ||
2201 | * node index available. | ||
2202 | */ | ||
2203 | enum sci_status scic_sds_controller_allocate_remote_node_context( | ||
2204 | struct scic_sds_controller *this_controller, | ||
2205 | struct scic_sds_remote_device *the_device, | ||
2206 | u16 *node_id) | ||
2207 | { | ||
2208 | u16 node_index; | ||
2209 | u32 remote_node_count = scic_sds_remote_device_node_count(the_device); | ||
2210 | |||
2211 | node_index = scic_sds_remote_node_table_allocate_remote_node( | ||
2212 | &this_controller->available_remote_nodes, remote_node_count | ||
2213 | ); | ||
2214 | |||
2215 | if (node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { | ||
2216 | this_controller->device_table[node_index] = the_device; | ||
2217 | |||
2218 | *node_id = node_index; | ||
2219 | |||
2220 | return SCI_SUCCESS; | ||
2221 | } | ||
2222 | |||
2223 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; | ||
2224 | } | ||
2225 | |||
2226 | /** | ||
2227 | * This method frees the remote node index back to the available pool. Once | ||
2228 | * this is done the remote node context buffer is no longer valid and can | ||
2229 | * not be used. | ||
2230 | * @this_controller: | ||
2231 | * @the_device: | ||
2232 | * @node_id: | ||
2233 | * | ||
2234 | */ | ||
2235 | void scic_sds_controller_free_remote_node_context( | ||
2236 | struct scic_sds_controller *this_controller, | ||
2237 | struct scic_sds_remote_device *the_device, | ||
2238 | u16 node_id) | ||
2239 | { | ||
2240 | u32 remote_node_count = scic_sds_remote_device_node_count(the_device); | ||
2241 | |||
2242 | if (this_controller->device_table[node_id] == the_device) { | ||
2243 | this_controller->device_table[node_id] = SCI_INVALID_HANDLE; | ||
2244 | |||
2245 | scic_sds_remote_node_table_release_remote_node_index( | ||
2246 | &this_controller->available_remote_nodes, remote_node_count, node_id | ||
2247 | ); | ||
2248 | } | ||
2249 | } | ||
2250 | |||
2251 | /** | ||
2252 | * This method returns the union scu_remote_node_context for the specified remote | ||
2253 | * node id. | ||
2254 | * @this_controller: | ||
2255 | * @node_id: | ||
2256 | * | ||
2257 | * union scu_remote_node_context* | ||
2258 | */ | ||
2259 | union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( | ||
2260 | struct scic_sds_controller *this_controller, | ||
2261 | u16 node_id | ||
2262 | ) { | ||
2263 | if ( | ||
2264 | (node_id < this_controller->remote_node_entries) | ||
2265 | && (this_controller->device_table[node_id] != SCI_INVALID_HANDLE) | ||
2266 | ) { | ||
2267 | return &this_controller->remote_node_context_table[node_id]; | ||
2268 | } | ||
2269 | |||
2270 | return NULL; | ||
2271 | } | ||
2272 | |||
2273 | /** | ||
2274 | * | ||
2275 | * @resposne_buffer: This is the buffer into which the D2H register FIS will be | ||
2276 | * constructed. | ||
2277 | * @frame_header: This is the frame header returned by the hardware. | ||
2278 | * @frame_buffer: This is the frame buffer returned by the hardware. | ||
2279 | * | ||
2280 | * This method will combind the frame header and frame buffer to create a SATA | ||
2281 | * D2H register FIS none | ||
2282 | */ | ||
2283 | void scic_sds_controller_copy_sata_response( | ||
2284 | void *response_buffer, | ||
2285 | void *frame_header, | ||
2286 | void *frame_buffer) | ||
2287 | { | ||
2288 | memcpy( | ||
2289 | response_buffer, | ||
2290 | frame_header, | ||
2291 | sizeof(u32) | ||
2292 | ); | ||
2293 | |||
2294 | memcpy( | ||
2295 | (char *)((char *)response_buffer + sizeof(u32)), | ||
2296 | frame_buffer, | ||
2297 | sizeof(struct sata_fis_reg_d2h) - sizeof(u32) | ||
2298 | ); | ||
2299 | } | ||
2300 | |||
2301 | /** | ||
2302 | * This method releases the frame once this is done the frame is available for | ||
2303 | * re-use by the hardware. The data contained in the frame header and frame | ||
2304 | * buffer is no longer valid. The UF queue get pointer is only updated if UF | ||
2305 | * control indicates this is appropriate. | ||
2306 | * @this_controller: | ||
2307 | * @frame_index: | ||
2308 | * | ||
2309 | */ | ||
2310 | void scic_sds_controller_release_frame( | ||
2311 | struct scic_sds_controller *this_controller, | ||
2312 | u32 frame_index) | ||
2313 | { | ||
2314 | if (scic_sds_unsolicited_frame_control_release_frame( | ||
2315 | &this_controller->uf_control, frame_index) == true) | ||
2316 | SCU_UFQGP_WRITE(this_controller, this_controller->uf_control.get); | ||
2317 | } | ||
2318 | |||
2319 | /** | ||
2320 | * This method sets user parameters and OEM parameters to default values. | ||
2321 | * Users can override these values utilizing the scic_user_parameters_set() | ||
2322 | * and scic_oem_parameters_set() methods. | ||
2323 | * @controller: This parameter specifies the controller for which to set the | ||
2324 | * configuration parameters to their default values. | ||
2325 | * | ||
2326 | */ | ||
2327 | static void scic_sds_controller_set_default_config_parameters( | ||
2328 | struct scic_sds_controller *this_controller) | ||
2329 | { | ||
2330 | u16 index; | ||
2331 | |||
2332 | /* Default to no SSC operation. */ | ||
2333 | this_controller->oem_parameters.sds1.controller.do_enable_ssc = false; | ||
2334 | |||
2335 | /* Initialize all of the port parameter information to narrow ports. */ | ||
2336 | for (index = 0; index < SCI_MAX_PORTS; index++) { | ||
2337 | this_controller->oem_parameters.sds1.ports[index].phy_mask = 0; | ||
2338 | } | ||
2339 | |||
2340 | /* Initialize all of the phy parameter information. */ | ||
2341 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
2342 | /* | ||
2343 | * Default to 3G (i.e. Gen 2) for now. User can override if | ||
2344 | * they choose. */ | ||
2345 | this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2; | ||
2346 | |||
2347 | /* | ||
2348 | * Previous Vitesse based expanders had a arbitration issue that | ||
2349 | * is worked around by having the upper 32-bits of SAS address | ||
2350 | * with a value greater then the Vitesse company identifier. | ||
2351 | * Hence, usage of 0x5FCFFFFF. */ | ||
2352 | this_controller->oem_parameters.sds1.phys[index].sas_address.low | ||
2353 | = 0x00000001; | ||
2354 | this_controller->oem_parameters.sds1.phys[index].sas_address.high | ||
2355 | = 0x5FCFFFFF; | ||
2356 | } | ||
2357 | |||
2358 | this_controller->user_parameters.sds1.stp_inactivity_timeout = 5; | ||
2359 | this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5; | ||
2360 | this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5; | ||
2361 | this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20; | ||
2362 | this_controller->user_parameters.sds1.no_outbound_task_timeout = 5; | ||
2363 | |||
2364 | } | ||
2365 | |||
2366 | |||
2367 | enum sci_status scic_controller_construct(struct scic_sds_controller *controller, | ||
2368 | void __iomem *scu_base, | ||
2369 | void __iomem *smu_base) | ||
2370 | { | ||
2371 | u8 index; | ||
2372 | |||
2373 | sci_base_controller_construct( | ||
2374 | &controller->parent, | ||
2375 | scic_sds_controller_state_table, | ||
2376 | controller->memory_descriptors, | ||
2377 | ARRAY_SIZE(controller->memory_descriptors), | ||
2378 | NULL | ||
2379 | ); | ||
2380 | |||
2381 | controller->scu_registers = scu_base; | ||
2382 | controller->smu_registers = smu_base; | ||
2383 | |||
2384 | scic_sds_port_configuration_agent_construct(&controller->port_agent); | ||
2385 | |||
2386 | /* Construct the ports for this controller */ | ||
2387 | for (index = 0; index < SCI_MAX_PORTS; index++) | ||
2388 | scic_sds_port_construct(&controller->port_table[index], | ||
2389 | index, controller); | ||
2390 | scic_sds_port_construct(&controller->port_table[index], | ||
2391 | SCIC_SDS_DUMMY_PORT, controller); | ||
2392 | |||
2393 | /* Construct the phys for this controller */ | ||
2394 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
2395 | /* Add all the PHYs to the dummy port */ | ||
2396 | scic_sds_phy_construct( | ||
2397 | &controller->phy_table[index], | ||
2398 | &controller->port_table[SCI_MAX_PORTS], | ||
2399 | index | ||
2400 | ); | ||
2401 | } | ||
2402 | |||
2403 | controller->invalid_phy_mask = 0; | ||
2404 | |||
2405 | /* Set the default maximum values */ | ||
2406 | controller->completion_event_entries = SCU_EVENT_COUNT; | ||
2407 | controller->completion_queue_entries = SCU_COMPLETION_QUEUE_COUNT; | ||
2408 | controller->remote_node_entries = SCI_MAX_REMOTE_DEVICES; | ||
2409 | controller->logical_port_entries = SCI_MAX_PORTS; | ||
2410 | controller->task_context_entries = SCU_IO_REQUEST_COUNT; | ||
2411 | controller->uf_control.buffers.count = SCU_UNSOLICITED_FRAME_COUNT; | ||
2412 | controller->uf_control.address_table.count = SCU_UNSOLICITED_FRAME_COUNT; | ||
2413 | |||
2414 | /* Initialize the User and OEM parameters to default values. */ | ||
2415 | scic_sds_controller_set_default_config_parameters(controller); | ||
2416 | |||
2417 | return SCI_SUCCESS; | ||
2418 | } | ||
2419 | |||
2420 | /* --------------------------------------------------------------------------- */ | ||
2421 | |||
2422 | enum sci_status scic_controller_initialize( | ||
2423 | struct scic_sds_controller *scic) | ||
2424 | { | ||
2425 | enum sci_status status = SCI_FAILURE_INVALID_STATE; | ||
2426 | sci_base_controller_handler_t initialize; | ||
2427 | u32 state; | ||
2428 | |||
2429 | state = scic->parent.state_machine.current_state_id; | ||
2430 | initialize = scic_sds_controller_state_handler_table[state].base.initialize; | ||
2431 | |||
2432 | if (initialize) | ||
2433 | status = initialize(&scic->parent); | ||
2434 | else | ||
2435 | dev_warn(scic_to_dev(scic), | ||
2436 | "%s: SCIC Controller initialize operation requested " | ||
2437 | "in invalid state %d\n", | ||
2438 | __func__, | ||
2439 | sci_base_state_machine_get_state( | ||
2440 | scic_sds_controller_get_base_state_machine( | ||
2441 | scic))); | ||
2442 | |||
2443 | return status; | ||
2444 | } | ||
2445 | |||
2446 | /* --------------------------------------------------------------------------- */ | ||
2447 | |||
2448 | u32 scic_controller_get_suggested_start_timeout( | ||
2449 | struct scic_sds_controller *sc) | ||
2450 | { | ||
2451 | /* Validate the user supplied parameters. */ | ||
2452 | if (sc == SCI_INVALID_HANDLE) | ||
2453 | return 0; | ||
2454 | |||
2455 | /* | ||
2456 | * The suggested minimum timeout value for a controller start operation: | ||
2457 | * | ||
2458 | * Signature FIS Timeout | ||
2459 | * + Phy Start Timeout | ||
2460 | * + Number of Phy Spin Up Intervals | ||
2461 | * --------------------------------- | ||
2462 | * Number of milliseconds for the controller start operation. | ||
2463 | * | ||
2464 | * NOTE: The number of phy spin up intervals will be equivalent | ||
2465 | * to the number of phys divided by the number phys allowed | ||
2466 | * per interval - 1 (once OEM parameters are supported). | ||
2467 | * Currently we assume only 1 phy per interval. */ | ||
2468 | |||
2469 | return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT | ||
2470 | + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT | ||
2471 | + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL)); | ||
2472 | } | ||
2473 | |||
2474 | /* --------------------------------------------------------------------------- */ | ||
2475 | |||
2476 | enum sci_status scic_controller_start( | ||
2477 | struct scic_sds_controller *scic, | ||
2478 | u32 timeout) | ||
2479 | { | ||
2480 | enum sci_status status = SCI_FAILURE_INVALID_STATE; | ||
2481 | sci_base_controller_timed_handler_t start; | ||
2482 | u32 state; | ||
2483 | |||
2484 | state = scic->parent.state_machine.current_state_id; | ||
2485 | start = scic_sds_controller_state_handler_table[state].base.start; | ||
2486 | |||
2487 | if (start) | ||
2488 | status = start(&scic->parent, timeout); | ||
2489 | else | ||
2490 | dev_warn(scic_to_dev(scic), | ||
2491 | "%s: SCIC Controller start operation requested in " | ||
2492 | "invalid state %d\n", | ||
2493 | __func__, | ||
2494 | sci_base_state_machine_get_state( | ||
2495 | scic_sds_controller_get_base_state_machine( | ||
2496 | scic))); | ||
2497 | |||
2498 | return status; | ||
2499 | } | ||
2500 | |||
2501 | /* --------------------------------------------------------------------------- */ | ||
2502 | |||
2503 | enum sci_status scic_controller_stop( | ||
2504 | struct scic_sds_controller *scic, | ||
2505 | u32 timeout) | ||
2506 | { | ||
2507 | enum sci_status status = SCI_FAILURE_INVALID_STATE; | ||
2508 | sci_base_controller_timed_handler_t stop; | ||
2509 | u32 state; | ||
2510 | |||
2511 | state = scic->parent.state_machine.current_state_id; | ||
2512 | stop = scic_sds_controller_state_handler_table[state].base.stop; | ||
2513 | |||
2514 | if (stop) | ||
2515 | status = stop(&scic->parent, timeout); | ||
2516 | else | ||
2517 | dev_warn(scic_to_dev(scic), | ||
2518 | "%s: SCIC Controller stop operation requested in " | ||
2519 | "invalid state %d\n", | ||
2520 | __func__, | ||
2521 | sci_base_state_machine_get_state( | ||
2522 | scic_sds_controller_get_base_state_machine( | ||
2523 | scic))); | ||
2524 | |||
2525 | return status; | ||
2526 | } | ||
2527 | |||
2528 | /* --------------------------------------------------------------------------- */ | ||
2529 | |||
2530 | enum sci_status scic_controller_reset( | ||
2531 | struct scic_sds_controller *scic) | ||
2532 | { | ||
2533 | enum sci_status status = SCI_FAILURE_INVALID_STATE; | ||
2534 | sci_base_controller_handler_t reset; | ||
2535 | u32 state; | ||
2536 | |||
2537 | state = scic->parent.state_machine.current_state_id; | ||
2538 | reset = scic_sds_controller_state_handler_table[state].base.reset; | ||
2539 | |||
2540 | if (reset) | ||
2541 | status = reset(&scic->parent); | ||
2542 | else | ||
2543 | dev_warn(scic_to_dev(scic), | ||
2544 | "%s: SCIC Controller reset operation requested in " | ||
2545 | "invalid state %d\n", | ||
2546 | __func__, | ||
2547 | sci_base_state_machine_get_state( | ||
2548 | scic_sds_controller_get_base_state_machine( | ||
2549 | scic))); | ||
2550 | |||
2551 | return status; | ||
2552 | } | ||
2553 | |||
2554 | /* --------------------------------------------------------------------------- */ | ||
2555 | |||
2556 | enum sci_status scic_controller_get_handler_methods( | ||
2557 | enum scic_interrupt_type interrupt_type, | ||
2558 | u16 message_count, | ||
2559 | struct scic_controller_handler_methods *handler_methods) | ||
2560 | { | ||
2561 | enum sci_status status = SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT; | ||
2562 | |||
2563 | switch (interrupt_type) { | ||
2564 | case SCIC_LEGACY_LINE_INTERRUPT_TYPE: | ||
2565 | if (message_count == 0) { | ||
2566 | handler_methods[0].interrupt_handler | ||
2567 | = scic_sds_controller_legacy_interrupt_handler; | ||
2568 | handler_methods[0].completion_handler | ||
2569 | = scic_sds_controller_legacy_completion_handler; | ||
2570 | |||
2571 | status = SCI_SUCCESS; | ||
2572 | } | ||
2573 | break; | ||
2574 | |||
2575 | case SCIC_MSIX_INTERRUPT_TYPE: | ||
2576 | if (message_count == 1) { | ||
2577 | handler_methods[0].interrupt_handler | ||
2578 | = scic_sds_controller_single_vector_interrupt_handler; | ||
2579 | handler_methods[0].completion_handler | ||
2580 | = scic_sds_controller_single_vector_completion_handler; | ||
2581 | |||
2582 | status = SCI_SUCCESS; | ||
2583 | } else if (message_count == 2) { | ||
2584 | handler_methods[0].interrupt_handler | ||
2585 | = scic_sds_controller_normal_vector_interrupt_handler; | ||
2586 | handler_methods[0].completion_handler | ||
2587 | = scic_sds_controller_normal_vector_completion_handler; | ||
2588 | |||
2589 | handler_methods[1].interrupt_handler | ||
2590 | = scic_sds_controller_error_vector_interrupt_handler; | ||
2591 | handler_methods[1].completion_handler | ||
2592 | = scic_sds_controller_error_vector_completion_handler; | ||
2593 | |||
2594 | status = SCI_SUCCESS; | ||
2595 | } | ||
2596 | break; | ||
2597 | |||
2598 | case SCIC_NO_INTERRUPTS: | ||
2599 | if (message_count == 0) { | ||
2600 | |||
2601 | handler_methods[0].interrupt_handler | ||
2602 | = scic_sds_controller_polling_interrupt_handler; | ||
2603 | handler_methods[0].completion_handler | ||
2604 | = scic_sds_controller_polling_completion_handler; | ||
2605 | |||
2606 | status = SCI_SUCCESS; | ||
2607 | } | ||
2608 | break; | ||
2609 | |||
2610 | default: | ||
2611 | status = SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2612 | break; | ||
2613 | } | ||
2614 | |||
2615 | return status; | ||
2616 | } | ||
2617 | |||
2618 | /* --------------------------------------------------------------------------- */ | ||
2619 | |||
2620 | enum sci_io_status scic_controller_start_io( | ||
2621 | struct scic_sds_controller *scic, | ||
2622 | struct scic_sds_remote_device *remote_device, | ||
2623 | struct scic_sds_request *io_request, | ||
2624 | u16 io_tag) | ||
2625 | { | ||
2626 | u32 state; | ||
2627 | sci_base_controller_start_request_handler_t start_io; | ||
2628 | |||
2629 | state = scic->parent.state_machine.current_state_id; | ||
2630 | start_io = scic_sds_controller_state_handler_table[state].base.start_io; | ||
2631 | |||
2632 | return start_io(&scic->parent, | ||
2633 | (struct sci_base_remote_device *) remote_device, | ||
2634 | (struct sci_base_request *)io_request, io_tag); | ||
2635 | } | ||
2636 | |||
2637 | /* --------------------------------------------------------------------------- */ | ||
2638 | |||
2639 | enum sci_status scic_controller_terminate_request( | ||
2640 | struct scic_sds_controller *scic, | ||
2641 | struct scic_sds_remote_device *remote_device, | ||
2642 | struct scic_sds_request *request) | ||
2643 | { | ||
2644 | sci_base_controller_request_handler_t terminate_request; | ||
2645 | u32 state; | ||
2646 | |||
2647 | state = scic->parent.state_machine.current_state_id; | ||
2648 | terminate_request = scic_sds_controller_state_handler_table[state].terminate_request; | ||
2649 | |||
2650 | return terminate_request(&scic->parent, | ||
2651 | (struct sci_base_remote_device *)remote_device, | ||
2652 | (struct sci_base_request *)request); | ||
2653 | } | ||
2654 | |||
2655 | /* --------------------------------------------------------------------------- */ | ||
2656 | |||
2657 | enum sci_status scic_controller_complete_io( | ||
2658 | struct scic_sds_controller *scic, | ||
2659 | struct scic_sds_remote_device *remote_device, | ||
2660 | struct scic_sds_request *io_request) | ||
2661 | { | ||
2662 | u32 state; | ||
2663 | sci_base_controller_request_handler_t complete_io; | ||
2664 | |||
2665 | state = scic->parent.state_machine.current_state_id; | ||
2666 | complete_io = scic_sds_controller_state_handler_table[state].base.complete_io; | ||
2667 | |||
2668 | return complete_io(&scic->parent, | ||
2669 | (struct sci_base_remote_device *)remote_device, | ||
2670 | (struct sci_base_request *)io_request); | ||
2671 | } | ||
2672 | |||
2673 | /* --------------------------------------------------------------------------- */ | ||
2674 | |||
2675 | |||
2676 | enum sci_task_status scic_controller_start_task( | ||
2677 | struct scic_sds_controller *scic, | ||
2678 | struct scic_sds_remote_device *remote_device, | ||
2679 | struct scic_sds_request *task_request, | ||
2680 | u16 task_tag) | ||
2681 | { | ||
2682 | u32 state; | ||
2683 | sci_base_controller_start_request_handler_t start_task; | ||
2684 | enum sci_task_status status = SCI_TASK_FAILURE_INVALID_STATE; | ||
2685 | |||
2686 | state = scic->parent.state_machine.current_state_id; | ||
2687 | start_task = scic_sds_controller_state_handler_table[state].base.start_task; | ||
2688 | |||
2689 | if (start_task) | ||
2690 | status = start_task(&scic->parent, | ||
2691 | (struct sci_base_remote_device *)remote_device, | ||
2692 | (struct sci_base_request *)task_request, | ||
2693 | task_tag); | ||
2694 | else | ||
2695 | dev_warn(scic_to_dev(scic), | ||
2696 | "%s: SCIC Controller starting task from invalid " | ||
2697 | "state\n", | ||
2698 | __func__); | ||
2699 | |||
2700 | return status; | ||
2701 | } | ||
2702 | |||
2703 | /* --------------------------------------------------------------------------- */ | ||
2704 | |||
2705 | enum sci_status scic_controller_complete_task( | ||
2706 | struct scic_sds_controller *scic, | ||
2707 | struct scic_sds_remote_device *remote_device, | ||
2708 | struct scic_sds_request *task_request) | ||
2709 | { | ||
2710 | u32 state; | ||
2711 | sci_base_controller_request_handler_t complete_task; | ||
2712 | enum sci_status status = SCI_FAILURE_INVALID_STATE; | ||
2713 | |||
2714 | state = scic->parent.state_machine.current_state_id; | ||
2715 | complete_task = scic_sds_controller_state_handler_table[state].base.complete_task; | ||
2716 | |||
2717 | if (complete_task) | ||
2718 | status = complete_task(&scic->parent, | ||
2719 | (struct sci_base_remote_device *)remote_device, | ||
2720 | (struct sci_base_request *)task_request); | ||
2721 | else | ||
2722 | dev_warn(scic_to_dev(scic), | ||
2723 | "%s: SCIC Controller completing task from invalid " | ||
2724 | "state\n", | ||
2725 | __func__); | ||
2726 | |||
2727 | return status; | ||
2728 | } | ||
2729 | |||
2730 | |||
2731 | /* --------------------------------------------------------------------------- */ | ||
2732 | |||
2733 | enum sci_status scic_controller_get_port_handle( | ||
2734 | struct scic_sds_controller *scic, | ||
2735 | u8 port_index, | ||
2736 | struct scic_sds_port **port_handle) | ||
2737 | { | ||
2738 | if (port_index < scic->logical_port_entries) { | ||
2739 | *port_handle = &scic->port_table[port_index]; | ||
2740 | |||
2741 | return SCI_SUCCESS; | ||
2742 | } | ||
2743 | |||
2744 | return SCI_FAILURE_INVALID_PORT; | ||
2745 | } | ||
2746 | |||
2747 | /* --------------------------------------------------------------------------- */ | ||
2748 | |||
2749 | enum sci_status scic_controller_get_phy_handle( | ||
2750 | struct scic_sds_controller *scic, | ||
2751 | u8 phy_index, | ||
2752 | struct scic_sds_phy **phy_handle) | ||
2753 | { | ||
2754 | if (phy_index < ARRAY_SIZE(scic->phy_table)) { | ||
2755 | *phy_handle = &scic->phy_table[phy_index]; | ||
2756 | |||
2757 | return SCI_SUCCESS; | ||
2758 | } | ||
2759 | |||
2760 | dev_err(scic_to_dev(scic), | ||
2761 | "%s: Controller:0x%p PhyId:0x%x invalid phy index\n", | ||
2762 | __func__, scic, phy_index); | ||
2763 | |||
2764 | return SCI_FAILURE_INVALID_PHY; | ||
2765 | } | ||
2766 | |||
2767 | /* --------------------------------------------------------------------------- */ | ||
2768 | |||
2769 | u16 scic_controller_allocate_io_tag( | ||
2770 | struct scic_sds_controller *scic) | ||
2771 | { | ||
2772 | u16 task_context; | ||
2773 | u16 sequence_count; | ||
2774 | |||
2775 | if (!sci_pool_empty(scic->tci_pool)) { | ||
2776 | sci_pool_get(scic->tci_pool, task_context); | ||
2777 | |||
2778 | sequence_count = scic->io_request_sequence[task_context]; | ||
2779 | |||
2780 | return scic_sds_io_tag_construct(sequence_count, task_context); | ||
2781 | } | ||
2782 | |||
2783 | return SCI_CONTROLLER_INVALID_IO_TAG; | ||
2784 | } | ||
2785 | |||
2786 | /* --------------------------------------------------------------------------- */ | ||
2787 | |||
2788 | enum sci_status scic_controller_free_io_tag( | ||
2789 | struct scic_sds_controller *scic, | ||
2790 | u16 io_tag) | ||
2791 | { | ||
2792 | u16 sequence; | ||
2793 | u16 index; | ||
2794 | |||
2795 | BUG_ON(io_tag == SCI_CONTROLLER_INVALID_IO_TAG); | ||
2796 | |||
2797 | sequence = scic_sds_io_tag_get_sequence(io_tag); | ||
2798 | index = scic_sds_io_tag_get_index(io_tag); | ||
2799 | |||
2800 | if (!sci_pool_full(scic->tci_pool)) { | ||
2801 | if (sequence == scic->io_request_sequence[index]) { | ||
2802 | scic_sds_io_sequence_increment( | ||
2803 | scic->io_request_sequence[index]); | ||
2804 | |||
2805 | sci_pool_put(scic->tci_pool, index); | ||
2806 | |||
2807 | return SCI_SUCCESS; | ||
2808 | } | ||
2809 | } | ||
2810 | |||
2811 | return SCI_FAILURE_INVALID_IO_TAG; | ||
2812 | } | ||
2813 | |||
2814 | /* --------------------------------------------------------------------------- */ | ||
2815 | |||
2816 | void scic_controller_enable_interrupts( | ||
2817 | struct scic_sds_controller *scic) | ||
2818 | { | ||
2819 | BUG_ON(scic->smu_registers == NULL); | ||
2820 | SMU_IMR_WRITE(scic, 0x00000000); | ||
2821 | } | ||
2822 | |||
2823 | /* --------------------------------------------------------------------------- */ | ||
2824 | |||
2825 | void scic_controller_disable_interrupts( | ||
2826 | struct scic_sds_controller *scic) | ||
2827 | { | ||
2828 | BUG_ON(scic->smu_registers == NULL); | ||
2829 | SMU_IMR_WRITE(scic, 0xffffffff); | ||
2830 | } | ||
2831 | |||
2832 | /* --------------------------------------------------------------------------- */ | ||
2833 | |||
2834 | enum sci_status scic_controller_set_mode( | ||
2835 | struct scic_sds_controller *scic, | ||
2836 | enum sci_controller_mode operating_mode) | ||
2837 | { | ||
2838 | enum sci_status status = SCI_SUCCESS; | ||
2839 | |||
2840 | if ((scic->parent.state_machine.current_state_id == | ||
2841 | SCI_BASE_CONTROLLER_STATE_INITIALIZING) || | ||
2842 | (scic->parent.state_machine.current_state_id == | ||
2843 | SCI_BASE_CONTROLLER_STATE_INITIALIZED)) { | ||
2844 | switch (operating_mode) { | ||
2845 | case SCI_MODE_SPEED: | ||
2846 | scic->remote_node_entries = SCI_MAX_REMOTE_DEVICES; | ||
2847 | scic->task_context_entries = SCU_IO_REQUEST_COUNT; | ||
2848 | scic->uf_control.buffers.count = | ||
2849 | SCU_UNSOLICITED_FRAME_COUNT; | ||
2850 | scic->completion_event_entries = SCU_EVENT_COUNT; | ||
2851 | scic->completion_queue_entries = | ||
2852 | SCU_COMPLETION_QUEUE_COUNT; | ||
2853 | scic_sds_controller_build_memory_descriptor_table(scic); | ||
2854 | break; | ||
2855 | |||
2856 | case SCI_MODE_SIZE: | ||
2857 | scic->remote_node_entries = SCI_MIN_REMOTE_DEVICES; | ||
2858 | scic->task_context_entries = SCI_MIN_IO_REQUESTS; | ||
2859 | scic->uf_control.buffers.count = | ||
2860 | SCU_MIN_UNSOLICITED_FRAMES; | ||
2861 | scic->completion_event_entries = SCU_MIN_EVENTS; | ||
2862 | scic->completion_queue_entries = | ||
2863 | SCU_MIN_COMPLETION_QUEUE_ENTRIES; | ||
2864 | scic_sds_controller_build_memory_descriptor_table(scic); | ||
2865 | break; | ||
2866 | |||
2867 | default: | ||
2868 | status = SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2869 | break; | ||
2870 | } | ||
2871 | } else | ||
2872 | status = SCI_FAILURE_INVALID_STATE; | ||
2873 | |||
2874 | return status; | ||
2875 | } | ||
2876 | |||
2877 | /** | ||
2878 | * scic_sds_controller_reset_hardware() - | ||
2879 | * | ||
2880 | * This method will reset the controller hardware. | ||
2881 | */ | ||
2882 | void scic_sds_controller_reset_hardware( | ||
2883 | struct scic_sds_controller *scic) | ||
2884 | { | ||
2885 | /* Disable interrupts so we dont take any spurious interrupts */ | ||
2886 | scic_controller_disable_interrupts(scic); | ||
2887 | |||
2888 | /* Reset the SCU */ | ||
2889 | SMU_SMUSRCR_WRITE(scic, 0xFFFFFFFF); | ||
2890 | |||
2891 | /* Delay for 1ms to before clearing the CQP and UFQPR. */ | ||
2892 | scic_cb_stall_execution(1000); | ||
2893 | |||
2894 | /* The write to the CQGR clears the CQP */ | ||
2895 | SMU_CQGR_WRITE(scic, 0x00000000); | ||
2896 | |||
2897 | /* The write to the UFQGP clears the UFQPR */ | ||
2898 | SCU_UFQGP_WRITE(scic, 0x00000000); | ||
2899 | } | ||
2900 | |||
2901 | /* --------------------------------------------------------------------------- */ | ||
2902 | |||
2903 | enum sci_status scic_user_parameters_set( | ||
2904 | struct scic_sds_controller *scic, | ||
2905 | union scic_user_parameters *scic_parms) | ||
2906 | { | ||
2907 | if ( | ||
2908 | (scic->parent.state_machine.current_state_id | ||
2909 | == SCI_BASE_CONTROLLER_STATE_RESET) | ||
2910 | || (scic->parent.state_machine.current_state_id | ||
2911 | == SCI_BASE_CONTROLLER_STATE_INITIALIZING) | ||
2912 | || (scic->parent.state_machine.current_state_id | ||
2913 | == SCI_BASE_CONTROLLER_STATE_INITIALIZED) | ||
2914 | ) { | ||
2915 | u16 index; | ||
2916 | |||
2917 | /* | ||
2918 | * Validate the user parameters. If they are not legal, then | ||
2919 | * return a failure. */ | ||
2920 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
2921 | if (! | ||
2922 | (scic_parms->sds1.phys[index].max_speed_generation | ||
2923 | <= SCIC_SDS_PARM_MAX_SPEED | ||
2924 | && scic_parms->sds1.phys[index].max_speed_generation | ||
2925 | > SCIC_SDS_PARM_NO_SPEED | ||
2926 | ) | ||
2927 | ) | ||
2928 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2929 | } | ||
2930 | |||
2931 | memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); | ||
2932 | |||
2933 | return SCI_SUCCESS; | ||
2934 | } | ||
2935 | |||
2936 | return SCI_FAILURE_INVALID_STATE; | ||
2937 | } | ||
2938 | |||
2939 | /* --------------------------------------------------------------------------- */ | ||
2940 | |||
2941 | void scic_user_parameters_get( | ||
2942 | struct scic_sds_controller *scic, | ||
2943 | union scic_user_parameters *scic_parms) | ||
2944 | { | ||
2945 | memcpy(scic_parms, (&scic->user_parameters), sizeof(*scic_parms)); | ||
2946 | } | ||
2947 | |||
2948 | /* --------------------------------------------------------------------------- */ | ||
2949 | |||
2950 | enum sci_status scic_oem_parameters_set( | ||
2951 | struct scic_sds_controller *scic, | ||
2952 | union scic_oem_parameters *scic_parms) | ||
2953 | { | ||
2954 | if ( | ||
2955 | (scic->parent.state_machine.current_state_id | ||
2956 | == SCI_BASE_CONTROLLER_STATE_RESET) | ||
2957 | || (scic->parent.state_machine.current_state_id | ||
2958 | == SCI_BASE_CONTROLLER_STATE_INITIALIZING) | ||
2959 | || (scic->parent.state_machine.current_state_id | ||
2960 | == SCI_BASE_CONTROLLER_STATE_INITIALIZED) | ||
2961 | ) { | ||
2962 | u16 index; | ||
2963 | |||
2964 | /* | ||
2965 | * Validate the oem parameters. If they are not legal, then | ||
2966 | * return a failure. */ | ||
2967 | for (index = 0; index < SCI_MAX_PORTS; index++) { | ||
2968 | if (scic_parms->sds1.ports[index].phy_mask > SCIC_SDS_PARM_PHY_MASK_MAX) { | ||
2969 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2970 | } | ||
2971 | } | ||
2972 | |||
2973 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
2974 | if ( | ||
2975 | scic_parms->sds1.phys[index].sas_address.high == 0 | ||
2976 | && scic_parms->sds1.phys[index].sas_address.low == 0 | ||
2977 | ) { | ||
2978 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
2979 | } | ||
2980 | } | ||
2981 | |||
2982 | memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms)); | ||
2983 | return SCI_SUCCESS; | ||
2984 | } | ||
2985 | |||
2986 | return SCI_FAILURE_INVALID_STATE; | ||
2987 | } | ||
2988 | |||
2989 | /* --------------------------------------------------------------------------- */ | ||
2990 | |||
2991 | void scic_oem_parameters_get( | ||
2992 | struct scic_sds_controller *scic, | ||
2993 | union scic_oem_parameters *scic_parms) | ||
2994 | { | ||
2995 | memcpy(scic_parms, (&scic->oem_parameters), sizeof(*scic_parms)); | ||
2996 | } | ||
2997 | |||
2998 | /* --------------------------------------------------------------------------- */ | ||
2999 | |||
3000 | |||
3001 | #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS 853 | ||
3002 | #define INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS 1280 | ||
3003 | #define INTERRUPT_COALESCE_TIMEOUT_MAX_US 2700000 | ||
3004 | #define INTERRUPT_COALESCE_NUMBER_MAX 256 | ||
3005 | #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN 7 | ||
3006 | #define INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX 28 | ||
3007 | |||
3008 | enum sci_status scic_controller_set_interrupt_coalescence( | ||
3009 | struct scic_sds_controller *scic_controller, | ||
3010 | u32 coalesce_number, | ||
3011 | u32 coalesce_timeout) | ||
3012 | { | ||
3013 | u8 timeout_encode = 0; | ||
3014 | u32 min = 0; | ||
3015 | u32 max = 0; | ||
3016 | |||
3017 | /* Check if the input parameters fall in the range. */ | ||
3018 | if (coalesce_number > INTERRUPT_COALESCE_NUMBER_MAX) | ||
3019 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
3020 | |||
3021 | /* | ||
3022 | * Defined encoding for interrupt coalescing timeout: | ||
3023 | * Value Min Max Units | ||
3024 | * ----- --- --- ----- | ||
3025 | * 0 - - Disabled | ||
3026 | * 1 13.3 20.0 ns | ||
3027 | * 2 26.7 40.0 | ||
3028 | * 3 53.3 80.0 | ||
3029 | * 4 106.7 160.0 | ||
3030 | * 5 213.3 320.0 | ||
3031 | * 6 426.7 640.0 | ||
3032 | * 7 853.3 1280.0 | ||
3033 | * 8 1.7 2.6 us | ||
3034 | * 9 3.4 5.1 | ||
3035 | * 10 6.8 10.2 | ||
3036 | * 11 13.7 20.5 | ||
3037 | * 12 27.3 41.0 | ||
3038 | * 13 54.6 81.9 | ||
3039 | * 14 109.2 163.8 | ||
3040 | * 15 218.5 327.7 | ||
3041 | * 16 436.9 655.4 | ||
3042 | * 17 873.8 1310.7 | ||
3043 | * 18 1.7 2.6 ms | ||
3044 | * 19 3.5 5.2 | ||
3045 | * 20 7.0 10.5 | ||
3046 | * 21 14.0 21.0 | ||
3047 | * 22 28.0 41.9 | ||
3048 | * 23 55.9 83.9 | ||
3049 | * 24 111.8 167.8 | ||
3050 | * 25 223.7 335.5 | ||
3051 | * 26 447.4 671.1 | ||
3052 | * 27 894.8 1342.2 | ||
3053 | * 28 1.8 2.7 s | ||
3054 | * Others Undefined */ | ||
3055 | |||
3056 | /* | ||
3057 | * Use the table above to decide the encode of interrupt coalescing timeout | ||
3058 | * value for register writing. */ | ||
3059 | if (coalesce_timeout == 0) | ||
3060 | timeout_encode = 0; | ||
3061 | else{ | ||
3062 | /* make the timeout value in unit of (10 ns). */ | ||
3063 | coalesce_timeout = coalesce_timeout * 100; | ||
3064 | min = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_LOWER_BOUND_NS / 10; | ||
3065 | max = INTERRUPT_COALESCE_TIMEOUT_BASE_RANGE_UPPER_BOUND_NS / 10; | ||
3066 | |||
3067 | /* get the encode of timeout for register writing. */ | ||
3068 | for (timeout_encode = INTERRUPT_COALESCE_TIMEOUT_ENCODE_MIN; | ||
3069 | timeout_encode <= INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX; | ||
3070 | timeout_encode++) { | ||
3071 | if (min <= coalesce_timeout && max > coalesce_timeout) | ||
3072 | break; | ||
3073 | else if (coalesce_timeout >= max && coalesce_timeout < min * 2 | ||
3074 | && coalesce_timeout <= INTERRUPT_COALESCE_TIMEOUT_MAX_US * 100) { | ||
3075 | if ((coalesce_timeout - max) < (2 * min - coalesce_timeout)) | ||
3076 | break; | ||
3077 | else{ | ||
3078 | timeout_encode++; | ||
3079 | break; | ||
3080 | } | ||
3081 | } else { | ||
3082 | max = max * 2; | ||
3083 | min = min * 2; | ||
3084 | } | ||
3085 | } | ||
3086 | |||
3087 | if (timeout_encode == INTERRUPT_COALESCE_TIMEOUT_ENCODE_MAX + 1) | ||
3088 | /* the value is out of range. */ | ||
3089 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
3090 | } | ||
3091 | |||
3092 | SMU_ICC_WRITE( | ||
3093 | scic_controller, | ||
3094 | (SMU_ICC_GEN_VAL(NUMBER, coalesce_number) | | ||
3095 | SMU_ICC_GEN_VAL(TIMER, timeout_encode)) | ||
3096 | ); | ||
3097 | |||
3098 | scic_controller->interrupt_coalesce_number = (u16)coalesce_number; | ||
3099 | scic_controller->interrupt_coalesce_timeout = coalesce_timeout / 100; | ||
3100 | |||
3101 | return SCI_SUCCESS; | ||
3102 | } | ||
3103 | |||
3104 | |||
3105 | struct scic_sds_controller *scic_controller_alloc(struct device *dev) | ||
3106 | { | ||
3107 | return devm_kzalloc(dev, sizeof(struct scic_sds_controller), GFP_KERNEL); | ||
3108 | } | ||
3109 | |||
3110 | /* | ||
3111 | * ***************************************************************************** | ||
3112 | * * DEFAULT STATE HANDLERS | ||
3113 | * ***************************************************************************** */ | ||
3114 | |||
3115 | /** | ||
3116 | * | ||
3117 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3118 | * struct scic_sds_controller object. | ||
3119 | * @remote_device: This is struct sci_base_remote_device which, if it was used, would | ||
3120 | * be cast to a struct scic_sds_remote_device. | ||
3121 | * @io_request: This is the struct sci_base_request which, if it was used, would be | ||
3122 | * cast to a SCIC_SDS_IO_REQUEST. | ||
3123 | * @io_tag: This is the IO tag to be assigned to the IO request or | ||
3124 | * SCI_CONTROLLER_INVALID_IO_TAG. | ||
3125 | * | ||
3126 | * This method is called when the struct scic_sds_controller default start io/task | ||
3127 | * handler is in place. - Issue a warning message enum sci_status | ||
3128 | * SCI_FAILURE_INVALID_STATE | ||
3129 | */ | ||
3130 | static enum sci_status scic_sds_controller_default_start_operation_handler( | ||
3131 | struct sci_base_controller *controller, | ||
3132 | struct sci_base_remote_device *remote_device, | ||
3133 | struct sci_base_request *io_request, | ||
3134 | u16 io_tag) | ||
3135 | { | ||
3136 | struct scic_sds_controller *this_controller; | ||
3137 | |||
3138 | this_controller = (struct scic_sds_controller *)controller; | ||
3139 | |||
3140 | dev_warn(scic_to_dev(this_controller), | ||
3141 | "%s: SCIC Controller requested to start an io/task from " | ||
3142 | "invalid state %d\n", | ||
3143 | __func__, | ||
3144 | sci_base_state_machine_get_state( | ||
3145 | scic_sds_controller_get_base_state_machine( | ||
3146 | this_controller))); | ||
3147 | |||
3148 | return SCI_FAILURE_INVALID_STATE; | ||
3149 | } | ||
3150 | |||
3151 | /** | ||
3152 | * | ||
3153 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3154 | * struct scic_sds_controller object. | ||
3155 | * @remote_device: This is struct sci_base_remote_device which, if it was used, would | ||
3156 | * be cast to a struct scic_sds_remote_device. | ||
3157 | * @io_request: This is the struct sci_base_request which, if it was used, would be | ||
3158 | * cast to a SCIC_SDS_IO_REQUEST. | ||
3159 | * | ||
3160 | * This method is called when the struct scic_sds_controller default request handler | ||
3161 | * is in place. - Issue a warning message enum sci_status SCI_FAILURE_INVALID_STATE | ||
3162 | */ | ||
3163 | static enum sci_status scic_sds_controller_default_request_handler( | ||
3164 | struct sci_base_controller *controller, | ||
3165 | struct sci_base_remote_device *remote_device, | ||
3166 | struct sci_base_request *io_request) | ||
3167 | { | ||
3168 | struct scic_sds_controller *this_controller; | ||
3169 | |||
3170 | this_controller = (struct scic_sds_controller *)controller; | ||
3171 | |||
3172 | dev_warn(scic_to_dev(this_controller), | ||
3173 | "%s: SCIC Controller request operation from invalid state %d\n", | ||
3174 | __func__, | ||
3175 | sci_base_state_machine_get_state( | ||
3176 | scic_sds_controller_get_base_state_machine( | ||
3177 | this_controller))); | ||
3178 | |||
3179 | return SCI_FAILURE_INVALID_STATE; | ||
3180 | } | ||
3181 | |||
3182 | /* | ||
3183 | * ***************************************************************************** | ||
3184 | * * GENERAL (COMMON) STATE HANDLERS | ||
3185 | * ***************************************************************************** */ | ||
3186 | |||
3187 | /** | ||
3188 | * | ||
3189 | * @controller: The struct sci_base_controller object which is cast into a | ||
3190 | * struct scic_sds_controller object. | ||
3191 | * | ||
3192 | * This method is called when the struct scic_sds_controller is in the ready state | ||
3193 | * reset handler is in place. - Transition to | ||
3194 | * SCI_BASE_CONTROLLER_STATE_RESETTING enum sci_status SCI_SUCCESS | ||
3195 | */ | ||
3196 | static enum sci_status scic_sds_controller_general_reset_handler( | ||
3197 | struct sci_base_controller *controller) | ||
3198 | { | ||
3199 | struct scic_sds_controller *this_controller; | ||
3200 | |||
3201 | this_controller = (struct scic_sds_controller *)controller; | ||
3202 | |||
3203 | /* | ||
3204 | * The reset operation is not a graceful cleanup just perform the state | ||
3205 | * transition. */ | ||
3206 | sci_base_state_machine_change_state( | ||
3207 | scic_sds_controller_get_base_state_machine(this_controller), | ||
3208 | SCI_BASE_CONTROLLER_STATE_RESETTING | ||
3209 | ); | ||
3210 | |||
3211 | return SCI_SUCCESS; | ||
3212 | } | ||
3213 | |||
3214 | /* | ||
3215 | * ***************************************************************************** | ||
3216 | * * RESET STATE HANDLERS | ||
3217 | * ***************************************************************************** */ | ||
3218 | |||
3219 | /** | ||
3220 | * | ||
3221 | * @controller: This is the struct sci_base_controller object which is cast into a | ||
3222 | * struct scic_sds_controller object. | ||
3223 | * | ||
3224 | * This method is the struct scic_sds_controller initialize handler for the reset | ||
3225 | * state. - Currently this function does nothing enum sci_status SCI_FAILURE This | ||
3226 | * function is not yet implemented and is a valid request from the reset state. | ||
3227 | */ | ||
3228 | static enum sci_status scic_sds_controller_reset_state_initialize_handler( | ||
3229 | struct sci_base_controller *controller) | ||
3230 | { | ||
3231 | u32 index; | ||
3232 | enum sci_status result = SCI_SUCCESS; | ||
3233 | struct scic_sds_controller *this_controller; | ||
3234 | |||
3235 | this_controller = (struct scic_sds_controller *)controller; | ||
3236 | |||
3237 | sci_base_state_machine_change_state( | ||
3238 | scic_sds_controller_get_base_state_machine(this_controller), | ||
3239 | SCI_BASE_CONTROLLER_STATE_INITIALIZING | ||
3240 | ); | ||
3241 | |||
3242 | this_controller->timeout_timer = scic_cb_timer_create( | ||
3243 | this_controller, | ||
3244 | (void (*)(void *))scic_sds_controller_timeout_handler, | ||
3245 | (void (*)(void *))controller); | ||
3246 | |||
3247 | scic_sds_controller_initialize_phy_startup(this_controller); | ||
3248 | |||
3249 | scic_sds_controller_initialize_power_control(this_controller); | ||
3250 | |||
3251 | /* | ||
3252 | * There is nothing to do here for B0 since we do not have to | ||
3253 | * program the AFE registers. | ||
3254 | * / @todo The AFE settings are supposed to be correct for the B0 but | ||
3255 | * / presently they seem to be wrong. */ | ||
3256 | scic_sds_controller_afe_initialization(this_controller); | ||
3257 | |||
3258 | if (SCI_SUCCESS == result) { | ||
3259 | u32 status; | ||
3260 | u32 terminate_loop; | ||
3261 | |||
3262 | /* Take the hardware out of reset */ | ||
3263 | SMU_SMUSRCR_WRITE(this_controller, 0x00000000); | ||
3264 | |||
3265 | /* | ||
3266 | * / @todo Provide meaningfull error code for hardware failure | ||
3267 | * result = SCI_FAILURE_CONTROLLER_HARDWARE; */ | ||
3268 | result = SCI_FAILURE; | ||
3269 | terminate_loop = 100; | ||
3270 | |||
3271 | while (terminate_loop-- && (result != SCI_SUCCESS)) { | ||
3272 | /* Loop until the hardware reports success */ | ||
3273 | scic_cb_stall_execution(SCU_CONTEXT_RAM_INIT_STALL_TIME); | ||
3274 | status = SMU_SMUCSR_READ(this_controller); | ||
3275 | |||
3276 | if ((status & SCU_RAM_INIT_COMPLETED) == SCU_RAM_INIT_COMPLETED) { | ||
3277 | result = SCI_SUCCESS; | ||
3278 | } | ||
3279 | } | ||
3280 | } | ||
3281 | |||
3282 | if (result == SCI_SUCCESS) { | ||
3283 | u32 max_supported_ports; | ||
3284 | u32 max_supported_devices; | ||
3285 | u32 max_supported_io_requests; | ||
3286 | u32 device_context_capacity; | ||
3287 | |||
3288 | /* | ||
3289 | * Determine what are the actaul device capacities that the | ||
3290 | * hardware will support */ | ||
3291 | device_context_capacity = SMU_DCC_READ(this_controller); | ||
3292 | |||
3293 | max_supported_ports = | ||
3294 | smu_dcc_get_max_ports(device_context_capacity); | ||
3295 | max_supported_devices = | ||
3296 | smu_dcc_get_max_remote_node_context(device_context_capacity); | ||
3297 | max_supported_io_requests = | ||
3298 | smu_dcc_get_max_task_context(device_context_capacity); | ||
3299 | |||
3300 | /* Make all PEs that are unassigned match up with the logical ports */ | ||
3301 | for (index = 0; index < max_supported_ports; index++) { | ||
3302 | scu_register_write( | ||
3303 | this_controller, | ||
3304 | this_controller->scu_registers->peg0.ptsg.protocol_engine[index], | ||
3305 | index | ||
3306 | ); | ||
3307 | } | ||
3308 | |||
3309 | /* Record the smaller of the two capacity values */ | ||
3310 | this_controller->logical_port_entries = | ||
3311 | min(max_supported_ports, this_controller->logical_port_entries); | ||
3312 | |||
3313 | this_controller->task_context_entries = | ||
3314 | min(max_supported_io_requests, this_controller->task_context_entries); | ||
3315 | |||
3316 | this_controller->remote_node_entries = | ||
3317 | min(max_supported_devices, this_controller->remote_node_entries); | ||
3318 | |||
3319 | /* | ||
3320 | * Now that we have the correct hardware reported minimum values | ||
3321 | * build the MDL for the controller. Default to a performance | ||
3322 | * configuration. */ | ||
3323 | scic_controller_set_mode(this_controller, SCI_MODE_SPEED); | ||
3324 | } | ||
3325 | |||
3326 | /* Initialize hardware PCI Relaxed ordering in DMA engines */ | ||
3327 | if (result == SCI_SUCCESS) { | ||
3328 | u32 dma_configuration; | ||
3329 | |||
3330 | /* Configure the payload DMA */ | ||
3331 | dma_configuration = SCU_PDMACR_READ(this_controller); | ||
3332 | dma_configuration |= SCU_PDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); | ||
3333 | SCU_PDMACR_WRITE(this_controller, dma_configuration); | ||
3334 | |||
3335 | /* Configure the control DMA */ | ||
3336 | dma_configuration = SCU_CDMACR_READ(this_controller); | ||
3337 | dma_configuration |= SCU_CDMACR_GEN_BIT(PCI_RELAXED_ORDERING_ENABLE); | ||
3338 | SCU_CDMACR_WRITE(this_controller, dma_configuration); | ||
3339 | } | ||
3340 | |||
3341 | /* | ||
3342 | * Initialize the PHYs before the PORTs because the PHY registers | ||
3343 | * are accessed during the port initialization. */ | ||
3344 | if (result == SCI_SUCCESS) { | ||
3345 | /* Initialize the phys */ | ||
3346 | for (index = 0; | ||
3347 | (result == SCI_SUCCESS) && (index < SCI_MAX_PHYS); | ||
3348 | index++) { | ||
3349 | result = scic_sds_phy_initialize( | ||
3350 | &this_controller->phy_table[index], | ||
3351 | &this_controller->scu_registers->peg0.pe[index].ll | ||
3352 | ); | ||
3353 | } | ||
3354 | } | ||
3355 | |||
3356 | if (result == SCI_SUCCESS) { | ||
3357 | /* Initialize the logical ports */ | ||
3358 | for (index = 0; | ||
3359 | (index < this_controller->logical_port_entries) | ||
3360 | && (result == SCI_SUCCESS); | ||
3361 | index++) { | ||
3362 | result = scic_sds_port_initialize( | ||
3363 | &this_controller->port_table[index], | ||
3364 | &this_controller->scu_registers->peg0.pe[index].tl, | ||
3365 | &this_controller->scu_registers->peg0.ptsg.port[index], | ||
3366 | &this_controller->scu_registers->peg0.ptsg.protocol_engine, | ||
3367 | &this_controller->scu_registers->peg0.viit[index] | ||
3368 | ); | ||
3369 | } | ||
3370 | } | ||
3371 | |||
3372 | if (SCI_SUCCESS == result) { | ||
3373 | result = scic_sds_port_configuration_agent_initialize( | ||
3374 | this_controller, | ||
3375 | &this_controller->port_agent | ||
3376 | ); | ||
3377 | } | ||
3378 | |||
3379 | /* Advance the controller state machine */ | ||
3380 | if (result == SCI_SUCCESS) { | ||
3381 | sci_base_state_machine_change_state( | ||
3382 | scic_sds_controller_get_base_state_machine(this_controller), | ||
3383 | SCI_BASE_CONTROLLER_STATE_INITIALIZED | ||
3384 | ); | ||
3385 | } else { | ||
3386 | sci_base_state_machine_change_state( | ||
3387 | scic_sds_controller_get_base_state_machine(this_controller), | ||
3388 | SCI_BASE_CONTROLLER_STATE_FAILED | ||
3389 | ); | ||
3390 | } | ||
3391 | |||
3392 | return result; | ||
3393 | } | ||
3394 | |||
3395 | /* | ||
3396 | * ***************************************************************************** | ||
3397 | * * INITIALIZED STATE HANDLERS | ||
3398 | * ***************************************************************************** */ | ||
3399 | |||
3400 | /** | ||
3401 | * | ||
3402 | * @controller: This is the struct sci_base_controller object which is cast into a | ||
3403 | * struct scic_sds_controller object. | ||
3404 | * @timeout: This is the allowed time for the controller object to reach the | ||
3405 | * started state. | ||
3406 | * | ||
3407 | * This method is the struct scic_sds_controller start handler for the initialized | ||
3408 | * state. - Validate we have a good memory descriptor table - Initialze the | ||
3409 | * physical memory before programming the hardware - Program the SCU hardware | ||
3410 | * with the physical memory addresses passed in the memory descriptor table. - | ||
3411 | * Initialzie the TCi pool - Initialize the RNi pool - Initialize the | ||
3412 | * completion queue - Initialize the unsolicited frame data - Take the SCU port | ||
3413 | * task scheduler out of reset - Start the first phy object. - Transition to | ||
3414 | * SCI_BASE_CONTROLLER_STATE_STARTING. enum sci_status SCI_SUCCESS if all of the | ||
3415 | * controller start operations complete | ||
3416 | * SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD if one or more of the memory | ||
3417 | * descriptor fields is invalid. | ||
3418 | */ | ||
3419 | static enum sci_status scic_sds_controller_initialized_state_start_handler( | ||
3420 | struct sci_base_controller *controller, | ||
3421 | u32 timeout) | ||
3422 | { | ||
3423 | u16 index; | ||
3424 | enum sci_status result; | ||
3425 | struct scic_sds_controller *this_controller; | ||
3426 | |||
3427 | this_controller = (struct scic_sds_controller *)controller; | ||
3428 | |||
3429 | /* Make sure that the SCI User filled in the memory descriptor table correctly */ | ||
3430 | result = scic_sds_controller_validate_memory_descriptor_table(this_controller); | ||
3431 | |||
3432 | if (result == SCI_SUCCESS) { | ||
3433 | /* The memory descriptor list looks good so program the hardware */ | ||
3434 | scic_sds_controller_ram_initialization(this_controller); | ||
3435 | } | ||
3436 | |||
3437 | if (SCI_SUCCESS == result) { | ||
3438 | /* Build the TCi free pool */ | ||
3439 | sci_pool_initialize(this_controller->tci_pool); | ||
3440 | for (index = 0; index < this_controller->task_context_entries; index++) { | ||
3441 | sci_pool_put(this_controller->tci_pool, index); | ||
3442 | } | ||
3443 | |||
3444 | /* Build the RNi free pool */ | ||
3445 | scic_sds_remote_node_table_initialize( | ||
3446 | &this_controller->available_remote_nodes, | ||
3447 | this_controller->remote_node_entries | ||
3448 | ); | ||
3449 | } | ||
3450 | |||
3451 | if (SCI_SUCCESS == result) { | ||
3452 | /* | ||
3453 | * Before anything else lets make sure we will not be interrupted | ||
3454 | * by the hardware. */ | ||
3455 | scic_controller_disable_interrupts(this_controller); | ||
3456 | |||
3457 | /* Enable the port task scheduler */ | ||
3458 | scic_sds_controller_enable_port_task_scheduler(this_controller); | ||
3459 | |||
3460 | /* Assign all the task entries to this controller physical function */ | ||
3461 | scic_sds_controller_assign_task_entries(this_controller); | ||
3462 | |||
3463 | /* Now initialze the completion queue */ | ||
3464 | scic_sds_controller_initialize_completion_queue(this_controller); | ||
3465 | |||
3466 | /* Initialize the unsolicited frame queue for use */ | ||
3467 | scic_sds_controller_initialize_unsolicited_frame_queue(this_controller); | ||
3468 | } | ||
3469 | |||
3470 | if (SCI_SUCCESS == result) { | ||
3471 | scic_sds_controller_start_next_phy(this_controller); | ||
3472 | |||
3473 | scic_cb_timer_start(this_controller, | ||
3474 | this_controller->timeout_timer, | ||
3475 | timeout); | ||
3476 | |||
3477 | sci_base_state_machine_change_state( | ||
3478 | scic_sds_controller_get_base_state_machine(this_controller), | ||
3479 | SCI_BASE_CONTROLLER_STATE_STARTING | ||
3480 | ); | ||
3481 | } | ||
3482 | |||
3483 | return result; | ||
3484 | } | ||
3485 | |||
3486 | /* | ||
3487 | * ***************************************************************************** | ||
3488 | * * INITIALIZED STATE HANDLERS | ||
3489 | * ***************************************************************************** */ | ||
3490 | |||
3491 | /** | ||
3492 | * | ||
3493 | * @controller: This is struct scic_sds_controller which receives the link up | ||
3494 | * notification. | ||
3495 | * @port: This is struct scic_sds_port with which the phy is associated. | ||
3496 | * @phy: This is the struct scic_sds_phy which has gone link up. | ||
3497 | * | ||
3498 | * This method is called when the struct scic_sds_controller is in the starting state | ||
3499 | * link up handler is called. This method will perform the following: - Stop | ||
3500 | * the phy timer - Start the next phy - Report the link up condition to the | ||
3501 | * port object none | ||
3502 | */ | ||
3503 | static void scic_sds_controller_starting_state_link_up_handler( | ||
3504 | struct scic_sds_controller *this_controller, | ||
3505 | struct scic_sds_port *port, | ||
3506 | struct scic_sds_phy *phy) | ||
3507 | { | ||
3508 | scic_sds_controller_phy_timer_stop(this_controller); | ||
3509 | |||
3510 | this_controller->port_agent.link_up_handler( | ||
3511 | this_controller, &this_controller->port_agent, port, phy | ||
3512 | ); | ||
3513 | /* scic_sds_port_link_up(port, phy); */ | ||
3514 | |||
3515 | scic_sds_controller_start_next_phy(this_controller); | ||
3516 | } | ||
3517 | |||
3518 | /** | ||
3519 | * | ||
3520 | * @controller: This is struct scic_sds_controller which receives the link down | ||
3521 | * notification. | ||
3522 | * @port: This is struct scic_sds_port with which the phy is associated. | ||
3523 | * @phy: This is the struct scic_sds_phy which has gone link down. | ||
3524 | * | ||
3525 | * This method is called when the struct scic_sds_controller is in the starting state | ||
3526 | * link down handler is called. - Report the link down condition to the port | ||
3527 | * object none | ||
3528 | */ | ||
3529 | static void scic_sds_controller_starting_state_link_down_handler( | ||
3530 | struct scic_sds_controller *this_controller, | ||
3531 | struct scic_sds_port *port, | ||
3532 | struct scic_sds_phy *phy) | ||
3533 | { | ||
3534 | this_controller->port_agent.link_down_handler( | ||
3535 | this_controller, &this_controller->port_agent, port, phy | ||
3536 | ); | ||
3537 | /* scic_sds_port_link_down(port, phy); */ | ||
3538 | } | ||
3539 | |||
3540 | /* | ||
3541 | * ***************************************************************************** | ||
3542 | * * READY STATE HANDLERS | ||
3543 | * ***************************************************************************** */ | ||
3544 | |||
3545 | /** | ||
3546 | * | ||
3547 | * @controller: The struct sci_base_controller object which is cast into a | ||
3548 | * struct scic_sds_controller object. | ||
3549 | * @timeout: The timeout for when the stop operation should report a failure. | ||
3550 | * | ||
3551 | * This method is called when the struct scic_sds_controller is in the ready state | ||
3552 | * stop handler is called. - Start the timeout timer - Transition to | ||
3553 | * SCI_BASE_CONTROLLER_STATE_STOPPING. enum sci_status SCI_SUCCESS | ||
3554 | */ | ||
3555 | static enum sci_status scic_sds_controller_ready_state_stop_handler( | ||
3556 | struct sci_base_controller *controller, | ||
3557 | u32 timeout) | ||
3558 | { | ||
3559 | struct scic_sds_controller *this_controller; | ||
3560 | |||
3561 | this_controller = (struct scic_sds_controller *)controller; | ||
3562 | |||
3563 | scic_cb_timer_start(this_controller, | ||
3564 | this_controller->timeout_timer, | ||
3565 | timeout); | ||
3566 | |||
3567 | sci_base_state_machine_change_state( | ||
3568 | scic_sds_controller_get_base_state_machine(this_controller), | ||
3569 | SCI_BASE_CONTROLLER_STATE_STOPPING | ||
3570 | ); | ||
3571 | |||
3572 | return SCI_SUCCESS; | ||
3573 | } | ||
3574 | |||
3575 | /** | ||
3576 | * | ||
3577 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3578 | * struct scic_sds_controller object. | ||
3579 | * @remote_device: This is struct sci_base_remote_device which is cast to a | ||
3580 | * struct scic_sds_remote_device object. | ||
3581 | * @io_request: This is the struct sci_base_request which is cast to a | ||
3582 | * SCIC_SDS_IO_REQUEST object. | ||
3583 | * @io_tag: This is the IO tag to be assigned to the IO request or | ||
3584 | * SCI_CONTROLLER_INVALID_IO_TAG. | ||
3585 | * | ||
3586 | * This method is called when the struct scic_sds_controller is in the ready state and | ||
3587 | * the start io handler is called. - Start the io request on the remote device | ||
3588 | * - if successful - assign the io_request to the io_request_table - post the | ||
3589 | * request to the hardware enum sci_status SCI_SUCCESS if the start io operation | ||
3590 | * succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could not be | ||
3591 | * allocated for the io request. SCI_FAILURE_INVALID_STATE if one or more | ||
3592 | * objects are not in a valid state to accept io requests. How does the io_tag | ||
3593 | * parameter get assigned to the io request? | ||
3594 | */ | ||
3595 | static enum sci_status scic_sds_controller_ready_state_start_io_handler( | ||
3596 | struct sci_base_controller *controller, | ||
3597 | struct sci_base_remote_device *remote_device, | ||
3598 | struct sci_base_request *io_request, | ||
3599 | u16 io_tag) | ||
3600 | { | ||
3601 | enum sci_status status; | ||
3602 | |||
3603 | struct scic_sds_controller *this_controller; | ||
3604 | struct scic_sds_request *the_request; | ||
3605 | struct scic_sds_remote_device *the_device; | ||
3606 | |||
3607 | this_controller = (struct scic_sds_controller *)controller; | ||
3608 | the_request = (struct scic_sds_request *)io_request; | ||
3609 | the_device = (struct scic_sds_remote_device *)remote_device; | ||
3610 | |||
3611 | status = scic_sds_remote_device_start_io(this_controller, the_device, the_request); | ||
3612 | |||
3613 | if (status == SCI_SUCCESS) { | ||
3614 | this_controller->io_request_table[ | ||
3615 | scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; | ||
3616 | |||
3617 | scic_sds_controller_post_request( | ||
3618 | this_controller, | ||
3619 | scic_sds_request_get_post_context(the_request) | ||
3620 | ); | ||
3621 | } | ||
3622 | |||
3623 | return status; | ||
3624 | } | ||
3625 | |||
3626 | /** | ||
3627 | * | ||
3628 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3629 | * struct scic_sds_controller object. | ||
3630 | * @remote_device: This is struct sci_base_remote_device which is cast to a | ||
3631 | * struct scic_sds_remote_device object. | ||
3632 | * @io_request: This is the struct sci_base_request which is cast to a | ||
3633 | * SCIC_SDS_IO_REQUEST object. | ||
3634 | * | ||
3635 | * This method is called when the struct scic_sds_controller is in the ready state and | ||
3636 | * the complete io handler is called. - Complete the io request on the remote | ||
3637 | * device - if successful - remove the io_request to the io_request_table | ||
3638 | * enum sci_status SCI_SUCCESS if the start io operation succeeds | ||
3639 | * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to | ||
3640 | * accept io requests. | ||
3641 | */ | ||
3642 | static enum sci_status scic_sds_controller_ready_state_complete_io_handler( | ||
3643 | struct sci_base_controller *controller, | ||
3644 | struct sci_base_remote_device *remote_device, | ||
3645 | struct sci_base_request *io_request) | ||
3646 | { | ||
3647 | u16 index; | ||
3648 | enum sci_status status; | ||
3649 | struct scic_sds_controller *this_controller; | ||
3650 | struct scic_sds_request *the_request; | ||
3651 | struct scic_sds_remote_device *the_device; | ||
3652 | |||
3653 | this_controller = (struct scic_sds_controller *)controller; | ||
3654 | the_request = (struct scic_sds_request *)io_request; | ||
3655 | the_device = (struct scic_sds_remote_device *)remote_device; | ||
3656 | |||
3657 | status = scic_sds_remote_device_complete_io( | ||
3658 | this_controller, the_device, the_request); | ||
3659 | |||
3660 | if (status == SCI_SUCCESS) { | ||
3661 | index = scic_sds_io_tag_get_index(the_request->io_tag); | ||
3662 | this_controller->io_request_table[index] = SCI_INVALID_HANDLE; | ||
3663 | } | ||
3664 | |||
3665 | return status; | ||
3666 | } | ||
3667 | |||
3668 | /** | ||
3669 | * | ||
3670 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3671 | * struct scic_sds_controller object. | ||
3672 | * @remote_device: This is struct sci_base_remote_device which is cast to a | ||
3673 | * struct scic_sds_remote_device object. | ||
3674 | * @io_request: This is the struct sci_base_request which is cast to a | ||
3675 | * SCIC_SDS_IO_REQUEST object. | ||
3676 | * | ||
3677 | * This method is called when the struct scic_sds_controller is in the ready state and | ||
3678 | * the continue io handler is called. enum sci_status | ||
3679 | */ | ||
3680 | static enum sci_status scic_sds_controller_ready_state_continue_io_handler( | ||
3681 | struct sci_base_controller *controller, | ||
3682 | struct sci_base_remote_device *remote_device, | ||
3683 | struct sci_base_request *io_request) | ||
3684 | { | ||
3685 | struct scic_sds_controller *this_controller; | ||
3686 | struct scic_sds_request *the_request; | ||
3687 | |||
3688 | the_request = (struct scic_sds_request *)io_request; | ||
3689 | this_controller = (struct scic_sds_controller *)controller; | ||
3690 | |||
3691 | this_controller->io_request_table[ | ||
3692 | scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; | ||
3693 | |||
3694 | scic_sds_controller_post_request( | ||
3695 | this_controller, | ||
3696 | scic_sds_request_get_post_context(the_request) | ||
3697 | ); | ||
3698 | |||
3699 | return SCI_SUCCESS; | ||
3700 | } | ||
3701 | |||
3702 | /** | ||
3703 | * | ||
3704 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3705 | * struct scic_sds_controller object. | ||
3706 | * @remote_device: This is struct sci_base_remote_device which is cast to a | ||
3707 | * struct scic_sds_remote_device object. | ||
3708 | * @io_request: This is the struct sci_base_request which is cast to a | ||
3709 | * SCIC_SDS_IO_REQUEST object. | ||
3710 | * @task_tag: This is the task tag to be assigned to the task request or | ||
3711 | * SCI_CONTROLLER_INVALID_IO_TAG. | ||
3712 | * | ||
3713 | * This method is called when the struct scic_sds_controller is in the ready state and | ||
3714 | * the start task handler is called. - The remote device is requested to start | ||
3715 | * the task request - if successful - assign the task to the io_request_table - | ||
3716 | * post the request to the SCU hardware enum sci_status SCI_SUCCESS if the start io | ||
3717 | * operation succeeds SCI_FAILURE_INSUFFICIENT_RESOURCES if the IO tag could | ||
3718 | * not be allocated for the io request. SCI_FAILURE_INVALID_STATE if one or | ||
3719 | * more objects are not in a valid state to accept io requests. How does the io | ||
3720 | * tag get assigned in this code path? | ||
3721 | */ | ||
3722 | static enum sci_status scic_sds_controller_ready_state_start_task_handler( | ||
3723 | struct sci_base_controller *controller, | ||
3724 | struct sci_base_remote_device *remote_device, | ||
3725 | struct sci_base_request *io_request, | ||
3726 | u16 task_tag) | ||
3727 | { | ||
3728 | struct scic_sds_controller *this_controller = (struct scic_sds_controller *) | ||
3729 | controller; | ||
3730 | struct scic_sds_request *the_request = (struct scic_sds_request *) | ||
3731 | io_request; | ||
3732 | struct scic_sds_remote_device *the_device = (struct scic_sds_remote_device *) | ||
3733 | remote_device; | ||
3734 | enum sci_status status; | ||
3735 | |||
3736 | status = scic_sds_remote_device_start_task( | ||
3737 | this_controller, the_device, the_request | ||
3738 | ); | ||
3739 | |||
3740 | if (status == SCI_SUCCESS) { | ||
3741 | this_controller->io_request_table[ | ||
3742 | scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; | ||
3743 | |||
3744 | scic_sds_controller_post_request( | ||
3745 | this_controller, | ||
3746 | scic_sds_request_get_post_context(the_request) | ||
3747 | ); | ||
3748 | } else if (status == SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS) { | ||
3749 | this_controller->io_request_table[ | ||
3750 | scic_sds_io_tag_get_index(the_request->io_tag)] = the_request; | ||
3751 | |||
3752 | /* | ||
3753 | * We will let framework know this task request started successfully, | ||
3754 | * although core is still woring on starting the request (to post tc when | ||
3755 | * RNC is resumed.) */ | ||
3756 | status = SCI_SUCCESS; | ||
3757 | } | ||
3758 | return status; | ||
3759 | } | ||
3760 | |||
3761 | /** | ||
3762 | * | ||
3763 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3764 | * struct scic_sds_controller object. | ||
3765 | * @remote_device: This is struct sci_base_remote_device which is cast to a | ||
3766 | * struct scic_sds_remote_device object. | ||
3767 | * @io_request: This is the struct sci_base_request which is cast to a | ||
3768 | * SCIC_SDS_IO_REQUEST object. | ||
3769 | * | ||
3770 | * This method is called when the struct scic_sds_controller is in the ready state and | ||
3771 | * the terminate request handler is called. - call the io request terminate | ||
3772 | * function - if successful - post the terminate request to the SCU hardware | ||
3773 | * enum sci_status SCI_SUCCESS if the start io operation succeeds | ||
3774 | * SCI_FAILURE_INVALID_STATE if one or more objects are not in a valid state to | ||
3775 | * accept io requests. | ||
3776 | */ | ||
3777 | static enum sci_status scic_sds_controller_ready_state_terminate_request_handler( | ||
3778 | struct sci_base_controller *controller, | ||
3779 | struct sci_base_remote_device *remote_device, | ||
3780 | struct sci_base_request *io_request) | ||
3781 | { | ||
3782 | struct scic_sds_controller *this_controller = (struct scic_sds_controller *) | ||
3783 | controller; | ||
3784 | struct scic_sds_request *the_request = (struct scic_sds_request *) | ||
3785 | io_request; | ||
3786 | enum sci_status status; | ||
3787 | |||
3788 | status = scic_sds_io_request_terminate(the_request); | ||
3789 | if (status == SCI_SUCCESS) { | ||
3790 | /* | ||
3791 | * Utilize the original post context command and or in the POST_TC_ABORT | ||
3792 | * request sub-type. */ | ||
3793 | scic_sds_controller_post_request( | ||
3794 | this_controller, | ||
3795 | scic_sds_request_get_post_context(the_request) | ||
3796 | | SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT | ||
3797 | ); | ||
3798 | } | ||
3799 | |||
3800 | return status; | ||
3801 | } | ||
3802 | |||
3803 | /** | ||
3804 | * | ||
3805 | * @controller: This is struct scic_sds_controller which receives the link up | ||
3806 | * notification. | ||
3807 | * @port: This is struct scic_sds_port with which the phy is associated. | ||
3808 | * @phy: This is the struct scic_sds_phy which has gone link up. | ||
3809 | * | ||
3810 | * This method is called when the struct scic_sds_controller is in the starting state | ||
3811 | * link up handler is called. This method will perform the following: - Stop | ||
3812 | * the phy timer - Start the next phy - Report the link up condition to the | ||
3813 | * port object none | ||
3814 | */ | ||
3815 | static void scic_sds_controller_ready_state_link_up_handler( | ||
3816 | struct scic_sds_controller *this_controller, | ||
3817 | struct scic_sds_port *port, | ||
3818 | struct scic_sds_phy *phy) | ||
3819 | { | ||
3820 | this_controller->port_agent.link_up_handler( | ||
3821 | this_controller, &this_controller->port_agent, port, phy | ||
3822 | ); | ||
3823 | } | ||
3824 | |||
3825 | /** | ||
3826 | * | ||
3827 | * @controller: This is struct scic_sds_controller which receives the link down | ||
3828 | * notification. | ||
3829 | * @port: This is struct scic_sds_port with which the phy is associated. | ||
3830 | * @phy: This is the struct scic_sds_phy which has gone link down. | ||
3831 | * | ||
3832 | * This method is called when the struct scic_sds_controller is in the starting state | ||
3833 | * link down handler is called. - Report the link down condition to the port | ||
3834 | * object none | ||
3835 | */ | ||
3836 | static void scic_sds_controller_ready_state_link_down_handler( | ||
3837 | struct scic_sds_controller *this_controller, | ||
3838 | struct scic_sds_port *port, | ||
3839 | struct scic_sds_phy *phy) | ||
3840 | { | ||
3841 | this_controller->port_agent.link_down_handler( | ||
3842 | this_controller, &this_controller->port_agent, port, phy | ||
3843 | ); | ||
3844 | } | ||
3845 | |||
3846 | /* | ||
3847 | * ***************************************************************************** | ||
3848 | * * STOPPING STATE HANDLERS | ||
3849 | * ***************************************************************************** */ | ||
3850 | |||
3851 | /** | ||
3852 | * | ||
3853 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3854 | * struct scic_sds_controller object. | ||
3855 | * @remote_device: This is struct sci_base_remote_device which is cast to a | ||
3856 | * struct scic_sds_remote_device object. | ||
3857 | * @io_request: This is the struct sci_base_request which is cast to a | ||
3858 | * SCIC_SDS_IO_REQUEST object. | ||
3859 | * | ||
3860 | * This method is called when the struct scic_sds_controller is in a stopping state | ||
3861 | * and the complete io handler is called. - This function is not yet | ||
3862 | * implemented enum sci_status SCI_FAILURE | ||
3863 | */ | ||
3864 | static enum sci_status scic_sds_controller_stopping_state_complete_io_handler( | ||
3865 | struct sci_base_controller *controller, | ||
3866 | struct sci_base_remote_device *remote_device, | ||
3867 | struct sci_base_request *io_request) | ||
3868 | { | ||
3869 | struct scic_sds_controller *this_controller; | ||
3870 | |||
3871 | this_controller = (struct scic_sds_controller *)controller; | ||
3872 | |||
3873 | /* / @todo Implement this function */ | ||
3874 | return SCI_FAILURE; | ||
3875 | } | ||
3876 | |||
3877 | /** | ||
3878 | * | ||
3879 | * @controller: This is struct sci_base_controller object which is cast into a | ||
3880 | * struct scic_sds_controller object. | ||
3881 | * @remote_device: This is struct sci_base_remote_device which is cast to a | ||
3882 | * struct scic_sds_remote_device object. | ||
3883 | * @io_request: This is the struct sci_base_request which is cast to a | ||
3884 | * SCIC_SDS_IO_REQUEST object. | ||
3885 | * | ||
3886 | * This method is called when the struct scic_sds_controller is in a stopping state | ||
3887 | * and the complete task handler is called. - This function is not yet | ||
3888 | * implemented enum sci_status SCI_FAILURE | ||
3889 | */ | ||
3890 | |||
3891 | /* | ||
3892 | * ***************************************************************************** | ||
3893 | * * STOPPED STATE HANDLERS | ||
3894 | * ***************************************************************************** */ | ||
3895 | |||
3896 | /* | ||
3897 | * ***************************************************************************** | ||
3898 | * * FAILED STATE HANDLERS | ||
3899 | * ***************************************************************************** */ | ||
3900 | |||
3901 | const struct scic_sds_controller_state_handler scic_sds_controller_state_handler_table[] = { | ||
3902 | [SCI_BASE_CONTROLLER_STATE_INITIAL] = { | ||
3903 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3904 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3905 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3906 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3907 | }, | ||
3908 | [SCI_BASE_CONTROLLER_STATE_RESET] = { | ||
3909 | .base.initialize = scic_sds_controller_reset_state_initialize_handler, | ||
3910 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3911 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3912 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3913 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3914 | }, | ||
3915 | [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = { | ||
3916 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3917 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3918 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3919 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3920 | }, | ||
3921 | [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = { | ||
3922 | .base.start = scic_sds_controller_initialized_state_start_handler, | ||
3923 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3924 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3925 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3926 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3927 | }, | ||
3928 | [SCI_BASE_CONTROLLER_STATE_STARTING] = { | ||
3929 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3930 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3931 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3932 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3933 | .link_up = scic_sds_controller_starting_state_link_up_handler, | ||
3934 | .link_down = scic_sds_controller_starting_state_link_down_handler | ||
3935 | }, | ||
3936 | [SCI_BASE_CONTROLLER_STATE_READY] = { | ||
3937 | .base.stop = scic_sds_controller_ready_state_stop_handler, | ||
3938 | .base.reset = scic_sds_controller_general_reset_handler, | ||
3939 | .base.start_io = scic_sds_controller_ready_state_start_io_handler, | ||
3940 | .base.complete_io = scic_sds_controller_ready_state_complete_io_handler, | ||
3941 | .base.continue_io = scic_sds_controller_ready_state_continue_io_handler, | ||
3942 | .base.start_task = scic_sds_controller_ready_state_start_task_handler, | ||
3943 | .base.complete_task = scic_sds_controller_ready_state_complete_io_handler, | ||
3944 | .terminate_request = scic_sds_controller_ready_state_terminate_request_handler, | ||
3945 | .link_up = scic_sds_controller_ready_state_link_up_handler, | ||
3946 | .link_down = scic_sds_controller_ready_state_link_down_handler | ||
3947 | }, | ||
3948 | [SCI_BASE_CONTROLLER_STATE_RESETTING] = { | ||
3949 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3950 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3951 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3952 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3953 | }, | ||
3954 | [SCI_BASE_CONTROLLER_STATE_STOPPING] = { | ||
3955 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3956 | .base.complete_io = scic_sds_controller_stopping_state_complete_io_handler, | ||
3957 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3958 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3959 | }, | ||
3960 | [SCI_BASE_CONTROLLER_STATE_STOPPED] = { | ||
3961 | .base.reset = scic_sds_controller_general_reset_handler, | ||
3962 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3963 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3964 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3965 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3966 | }, | ||
3967 | [SCI_BASE_CONTROLLER_STATE_FAILED] = { | ||
3968 | .base.reset = scic_sds_controller_general_reset_handler, | ||
3969 | .base.start_io = scic_sds_controller_default_start_operation_handler, | ||
3970 | .base.complete_io = scic_sds_controller_default_request_handler, | ||
3971 | .base.continue_io = scic_sds_controller_default_request_handler, | ||
3972 | .terminate_request = scic_sds_controller_default_request_handler, | ||
3973 | }, | ||
3974 | }; | ||
3975 | |||
3976 | /** | ||
3977 | * | ||
3978 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller | ||
3979 | * object. | ||
3980 | * | ||
3981 | * This method implements the actions taken by the struct scic_sds_controller on entry | ||
3982 | * to the SCI_BASE_CONTROLLER_STATE_INITIAL. - Set the state handlers to the | ||
3983 | * controllers initial state. none This function should initialze the | ||
3984 | * controller object. | ||
3985 | */ | ||
3986 | static void scic_sds_controller_initial_state_enter( | ||
3987 | struct sci_base_object *object) | ||
3988 | { | ||
3989 | struct scic_sds_controller *this_controller; | ||
3990 | |||
3991 | this_controller = (struct scic_sds_controller *)object; | ||
3992 | |||
3993 | sci_base_state_machine_change_state( | ||
3994 | &this_controller->parent.state_machine, SCI_BASE_CONTROLLER_STATE_RESET); | ||
3995 | } | ||
3996 | |||
3997 | /** | ||
3998 | * | ||
3999 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller | ||
4000 | * object. | ||
4001 | * | ||
4002 | * This method implements the actions taken by the struct scic_sds_controller on exit | ||
4003 | * from the SCI_BASE_CONTROLLER_STATE_STARTING. - This function stops the | ||
4004 | * controller starting timeout timer. none | ||
4005 | */ | ||
4006 | static void scic_sds_controller_starting_state_exit( | ||
4007 | struct sci_base_object *object) | ||
4008 | { | ||
4009 | struct scic_sds_controller *scic = (struct scic_sds_controller *)object; | ||
4010 | |||
4011 | scic_cb_timer_stop(scic, scic->timeout_timer); | ||
4012 | } | ||
4013 | |||
4014 | /** | ||
4015 | * | ||
4016 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller | ||
4017 | * object. | ||
4018 | * | ||
4019 | * This method implements the actions taken by the struct scic_sds_controller on entry | ||
4020 | * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the | ||
4021 | * controllers ready state. none | ||
4022 | */ | ||
4023 | static void scic_sds_controller_ready_state_enter( | ||
4024 | struct sci_base_object *object) | ||
4025 | { | ||
4026 | struct scic_sds_controller *this_controller; | ||
4027 | |||
4028 | this_controller = (struct scic_sds_controller *)object; | ||
4029 | |||
4030 | /* set the default interrupt coalescence number and timeout value. */ | ||
4031 | scic_controller_set_interrupt_coalescence( | ||
4032 | this_controller, 0x10, 250); | ||
4033 | } | ||
4034 | |||
4035 | /** | ||
4036 | * | ||
4037 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller | ||
4038 | * object. | ||
4039 | * | ||
4040 | * This method implements the actions taken by the struct scic_sds_controller on exit | ||
4041 | * from the SCI_BASE_CONTROLLER_STATE_READY. - This function does nothing. none | ||
4042 | */ | ||
4043 | static void scic_sds_controller_ready_state_exit( | ||
4044 | struct sci_base_object *object) | ||
4045 | { | ||
4046 | struct scic_sds_controller *this_controller; | ||
4047 | |||
4048 | this_controller = (struct scic_sds_controller *)object; | ||
4049 | |||
4050 | /* disable interrupt coalescence. */ | ||
4051 | scic_controller_set_interrupt_coalescence(this_controller, 0, 0); | ||
4052 | } | ||
4053 | |||
4054 | /** | ||
4055 | * | ||
4056 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller | ||
4057 | * object. | ||
4058 | * | ||
4059 | * This method implements the actions taken by the struct scic_sds_controller on entry | ||
4060 | * to the SCI_BASE_CONTROLLER_STATE_READY. - Set the state handlers to the | ||
4061 | * controllers ready state. - Stop the phys on this controller - Stop the ports | ||
4062 | * on this controller - Stop all of the remote devices on this controller none | ||
4063 | */ | ||
4064 | static void scic_sds_controller_stopping_state_enter( | ||
4065 | struct sci_base_object *object) | ||
4066 | { | ||
4067 | struct scic_sds_controller *this_controller; | ||
4068 | |||
4069 | this_controller = (struct scic_sds_controller *)object; | ||
4070 | |||
4071 | /* Stop all of the components for this controller */ | ||
4072 | scic_sds_controller_stop_phys(this_controller); | ||
4073 | scic_sds_controller_stop_ports(this_controller); | ||
4074 | scic_sds_controller_stop_devices(this_controller); | ||
4075 | } | ||
4076 | |||
4077 | /** | ||
4078 | * | ||
4079 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller | ||
4080 | * object. | ||
4081 | * | ||
4082 | * This method implements the actions taken by the struct scic_sds_controller on exit | ||
4083 | * from the SCI_BASE_CONTROLLER_STATE_STOPPING. - This function stops the | ||
4084 | * controller stopping timeout timer. none | ||
4085 | */ | ||
4086 | static void scic_sds_controller_stopping_state_exit( | ||
4087 | struct sci_base_object *object) | ||
4088 | { | ||
4089 | struct scic_sds_controller *this_controller; | ||
4090 | |||
4091 | this_controller = (struct scic_sds_controller *)object; | ||
4092 | |||
4093 | scic_cb_timer_stop(this_controller, this_controller->timeout_timer); | ||
4094 | } | ||
4095 | |||
4096 | /** | ||
4097 | * | ||
4098 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_controller | ||
4099 | * object. | ||
4100 | * | ||
4101 | * This method implements the actions taken by the struct scic_sds_controller on entry | ||
4102 | * to the SCI_BASE_CONTROLLER_STATE_RESETTING. - Set the state handlers to the | ||
4103 | * controllers resetting state. - Write to the SCU hardware reset register to | ||
4104 | * force a reset - Transition to the SCI_BASE_CONTROLLER_STATE_RESET none | ||
4105 | */ | ||
4106 | static void scic_sds_controller_resetting_state_enter( | ||
4107 | struct sci_base_object *object) | ||
4108 | { | ||
4109 | struct scic_sds_controller *this_controller; | ||
4110 | |||
4111 | this_controller = (struct scic_sds_controller *)object; | ||
4112 | |||
4113 | scic_sds_controller_reset_hardware(this_controller); | ||
4114 | |||
4115 | sci_base_state_machine_change_state( | ||
4116 | scic_sds_controller_get_base_state_machine(this_controller), | ||
4117 | SCI_BASE_CONTROLLER_STATE_RESET | ||
4118 | ); | ||
4119 | } | ||
4120 | |||
4121 | /* --------------------------------------------------------------------------- */ | ||
4122 | |||
4123 | const struct sci_base_state scic_sds_controller_state_table[] = { | ||
4124 | [SCI_BASE_CONTROLLER_STATE_INITIAL] = { | ||
4125 | .enter_state = scic_sds_controller_initial_state_enter, | ||
4126 | }, | ||
4127 | [SCI_BASE_CONTROLLER_STATE_RESET] = {}, | ||
4128 | [SCI_BASE_CONTROLLER_STATE_INITIALIZING] = {}, | ||
4129 | [SCI_BASE_CONTROLLER_STATE_INITIALIZED] = {}, | ||
4130 | [SCI_BASE_CONTROLLER_STATE_STARTING] = { | ||
4131 | .exit_state = scic_sds_controller_starting_state_exit, | ||
4132 | }, | ||
4133 | [SCI_BASE_CONTROLLER_STATE_READY] = { | ||
4134 | .enter_state = scic_sds_controller_ready_state_enter, | ||
4135 | .exit_state = scic_sds_controller_ready_state_exit, | ||
4136 | }, | ||
4137 | [SCI_BASE_CONTROLLER_STATE_RESETTING] = { | ||
4138 | .enter_state = scic_sds_controller_resetting_state_enter, | ||
4139 | }, | ||
4140 | [SCI_BASE_CONTROLLER_STATE_STOPPING] = { | ||
4141 | .enter_state = scic_sds_controller_stopping_state_enter, | ||
4142 | .exit_state = scic_sds_controller_stopping_state_exit, | ||
4143 | }, | ||
4144 | [SCI_BASE_CONTROLLER_STATE_STOPPED] = {}, | ||
4145 | [SCI_BASE_CONTROLLER_STATE_FAILED] = {} | ||
4146 | }; | ||
4147 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_controller.h b/drivers/scsi/isci/core/scic_sds_controller.h new file mode 100644 index 000000000000..afa45f9874a4 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_controller.h | |||
@@ -0,0 +1,706 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_CONTROLLER_H_ | ||
57 | #define _SCIC_SDS_CONTROLLER_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants and prototypes used for the | ||
61 | * core controller object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_pool.h" | ||
67 | #include "sci_controller_constants.h" | ||
68 | #include "sci_memory_descriptor_list.h" | ||
69 | #include "sci_base_controller.h" | ||
70 | #include "scic_config_parameters.h" | ||
71 | #include "scic_sds_port.h" | ||
72 | #include "scic_sds_phy.h" | ||
73 | #include "scic_sds_remote_node_table.h" | ||
74 | #include "scu_registers.h" | ||
75 | #include "scu_constants.h" | ||
76 | #include "scu_remote_node_context.h" | ||
77 | #include "scu_task_context.h" | ||
78 | #include "scu_unsolicited_frame.h" | ||
79 | #include "scic_sds_unsolicited_frame_control.h" | ||
80 | #include "scic_sds_port_configuration_agent.h" | ||
81 | #include "scic_sds_pci.h" | ||
82 | |||
83 | struct scic_sds_remote_device; | ||
84 | struct scic_sds_request; | ||
85 | struct scic_sds_controller; | ||
86 | |||
87 | |||
88 | #define SCU_COMPLETION_RAM_ALIGNMENT (64) | ||
89 | |||
90 | /** | ||
91 | * enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS - | ||
92 | * | ||
93 | * This enumeration depects the types of MDEs that are going to be created for | ||
94 | * the controller object. | ||
95 | */ | ||
96 | enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS { | ||
97 | /** | ||
98 | * Completion queue MDE entry | ||
99 | */ | ||
100 | SCU_MDE_COMPLETION_QUEUE, | ||
101 | |||
102 | /** | ||
103 | * Remote node context MDE entry | ||
104 | */ | ||
105 | SCU_MDE_REMOTE_NODE_CONTEXT, | ||
106 | |||
107 | /** | ||
108 | * Task context MDE entry | ||
109 | */ | ||
110 | SCU_MDE_TASK_CONTEXT, | ||
111 | |||
112 | /** | ||
113 | * Unsolicited frame buffer MDE entrys this is the start of the unsolicited | ||
114 | * frame buffer entries. | ||
115 | */ | ||
116 | SCU_MDE_UF_BUFFER, | ||
117 | |||
118 | SCU_MAX_MDES | ||
119 | }; | ||
120 | |||
121 | /** | ||
122 | * | ||
123 | * | ||
124 | * Allowed PORT configuration modes APC Automatic PORT configuration mode is | ||
125 | * defined by the OEM configuration parameters providing no PHY_MASK parameters | ||
126 | * for any PORT. i.e. There are no phys assigned to any of the ports at start. | ||
127 | * MPC Manual PORT configuration mode is defined by the OEM configuration | ||
128 | * parameters providing a PHY_MASK value for any PORT. It is assumed that any | ||
129 | * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned. | ||
130 | * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs | ||
131 | * being assigned is sufficient to declare manual PORT configuration. | ||
132 | */ | ||
133 | enum SCIC_PORT_CONFIGURATION_MODE { | ||
134 | SCIC_PORT_MANUAL_CONFIGURATION_MODE, | ||
135 | SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE | ||
136 | }; | ||
137 | |||
138 | /** | ||
139 | * struct scic_power_control - | ||
140 | * | ||
141 | * This structure defines the fields for managing power control for direct | ||
142 | * attached disk devices. | ||
143 | */ | ||
144 | struct scic_power_control { | ||
145 | /** | ||
146 | * This field is set when the power control timer is running and cleared when | ||
147 | * it is not. | ||
148 | */ | ||
149 | bool timer_started; | ||
150 | |||
151 | /** | ||
152 | * This field is the handle to the driver timer object. This timer is used to | ||
153 | * control when the directed attached disks can consume power. | ||
154 | */ | ||
155 | void *timer; | ||
156 | |||
157 | /** | ||
158 | * This field is used to keep track of how many phys are put into the | ||
159 | * requesters field. | ||
160 | */ | ||
161 | u8 phys_waiting; | ||
162 | |||
163 | /** | ||
164 | * This field is an array of phys that we are waiting on. The phys are direct | ||
165 | * mapped into requesters via struct scic_sds_phy.phy_index | ||
166 | */ | ||
167 | struct scic_sds_phy *requesters[SCI_MAX_PHYS]; | ||
168 | |||
169 | }; | ||
170 | |||
171 | /** | ||
172 | * struct scic_sds_controller - | ||
173 | * | ||
174 | * This structure represents the SCU contoller object. | ||
175 | */ | ||
176 | struct scic_sds_controller { | ||
177 | /** | ||
178 | * The struct sci_base_controller is the parent object for the struct scic_sds_controller | ||
179 | * object. | ||
180 | */ | ||
181 | struct sci_base_controller parent; | ||
182 | |||
183 | /** | ||
184 | * This field is the driver timer object handler used to time the controller | ||
185 | * object start and stop requests. | ||
186 | */ | ||
187 | void *timeout_timer; | ||
188 | |||
189 | /** | ||
190 | * This field contains the user parameters to be utilized for this | ||
191 | * core controller object. | ||
192 | */ | ||
193 | union scic_user_parameters user_parameters; | ||
194 | |||
195 | /** | ||
196 | * This field contains the OEM parameters to be utilized for this | ||
197 | * core controller object. | ||
198 | */ | ||
199 | union scic_oem_parameters oem_parameters; | ||
200 | |||
201 | /** | ||
202 | * This field contains the port configuration agent for this controller. | ||
203 | */ | ||
204 | struct scic_sds_port_configuration_agent port_agent; | ||
205 | |||
206 | /** | ||
207 | * This field is the array of port objects that are controlled by this | ||
208 | * controller object. There is one dummy port object also contained within | ||
209 | * this controller object. | ||
210 | */ | ||
211 | struct scic_sds_port port_table[SCI_MAX_PORTS + 1]; | ||
212 | |||
213 | /** | ||
214 | * This field is the array of phy objects that are controlled by this | ||
215 | * controller object. | ||
216 | */ | ||
217 | struct scic_sds_phy phy_table[SCI_MAX_PHYS]; | ||
218 | |||
219 | /** | ||
220 | * This field is the array of device objects that are currently constructed | ||
221 | * for this controller object. This table is used as a fast lookup of device | ||
222 | * objects that need to handle device completion notifications from the | ||
223 | * hardware. The table is RNi based. | ||
224 | */ | ||
225 | struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES]; | ||
226 | |||
227 | /** | ||
228 | * This field is the array of IO request objects that are currently active for | ||
229 | * this controller object. This table is used as a fast lookup of the io | ||
230 | * request object that need to handle completion queue notifications. The | ||
231 | * table is TCi based. | ||
232 | */ | ||
233 | struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS]; | ||
234 | |||
235 | /** | ||
236 | * This field is the free RNi data structure | ||
237 | */ | ||
238 | struct scic_remote_node_table available_remote_nodes; | ||
239 | |||
240 | /** | ||
241 | * This field is the TCi pool used to manage the task context index. | ||
242 | */ | ||
243 | SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS); | ||
244 | |||
245 | /** | ||
246 | * This filed is the struct scic_power_control data used to controll when direct | ||
247 | * attached devices can consume power. | ||
248 | */ | ||
249 | struct scic_power_control power_control; | ||
250 | |||
251 | /** | ||
252 | * This field is the array of sequence values for the IO Tag fields. Even | ||
253 | * though only 4 bits of the field is used for the sequence the sequence is 16 | ||
254 | * bits in size so the sequence can be bitwise or'd with the TCi to build the | ||
255 | * IO Tag value. | ||
256 | */ | ||
257 | u16 io_request_sequence[SCI_MAX_IO_REQUESTS]; | ||
258 | |||
259 | /** | ||
260 | * This field in the array of sequence values for the RNi. These are used | ||
261 | * to control io request build to io request start operations. The sequence | ||
262 | * value is recorded into an io request when it is built and is checked on | ||
263 | * the io request start operation to make sure that there was not a device | ||
264 | * hot plug between the build and start operation. | ||
265 | */ | ||
266 | u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES]; | ||
267 | |||
268 | /** | ||
269 | * This field is a pointer to the memory allocated by the driver for the task | ||
270 | * context table. This data is shared between the hardware and software. | ||
271 | */ | ||
272 | struct scu_task_context *task_context_table; | ||
273 | |||
274 | /** | ||
275 | * This field is a pointer to the memory allocated by the driver for the | ||
276 | * remote node context table. This table is shared between the hardware and | ||
277 | * software. | ||
278 | */ | ||
279 | union scu_remote_node_context *remote_node_context_table; | ||
280 | |||
281 | /** | ||
282 | * This field is the array of physical memory requiremets for this controller | ||
283 | * object. | ||
284 | */ | ||
285 | struct sci_physical_memory_descriptor memory_descriptors[SCU_MAX_MDES]; | ||
286 | |||
287 | /** | ||
288 | * This field is a pointer to the completion queue. This memory is | ||
289 | * written to by the hardware and read by the software. | ||
290 | */ | ||
291 | u32 *completion_queue; | ||
292 | |||
293 | /** | ||
294 | * This field is the software copy of the completion queue get pointer. The | ||
295 | * controller object writes this value to the hardware after processing the | ||
296 | * completion entries. | ||
297 | */ | ||
298 | u32 completion_queue_get; | ||
299 | |||
300 | /** | ||
301 | * This field is the minimum of the number of hardware supported port entries | ||
302 | * and the software requested port entries. | ||
303 | */ | ||
304 | u32 logical_port_entries; | ||
305 | |||
306 | /** | ||
307 | * This field is the minimum number of hardware supported completion queue | ||
308 | * entries and the software requested completion queue entries. | ||
309 | */ | ||
310 | u32 completion_queue_entries; | ||
311 | |||
312 | /** | ||
313 | * This field is the minimum number of hardware supported event entries and | ||
314 | * the software requested event entries. | ||
315 | */ | ||
316 | u32 completion_event_entries; | ||
317 | |||
318 | /** | ||
319 | * This field is the minimum number of devices supported by the hardware and | ||
320 | * the number of devices requested by the software. | ||
321 | */ | ||
322 | u32 remote_node_entries; | ||
323 | |||
324 | /** | ||
325 | * This field is the minimum number of IO requests supported by the hardware | ||
326 | * and the number of IO requests requested by the software. | ||
327 | */ | ||
328 | u32 task_context_entries; | ||
329 | |||
330 | /** | ||
331 | * This object contains all of the unsolicited frame specific | ||
332 | * data utilized by the core controller. | ||
333 | */ | ||
334 | struct scic_sds_unsolicited_frame_control uf_control; | ||
335 | |||
336 | /** | ||
337 | * This field records the fact that the controller has encountered a fatal | ||
338 | * error and must be reset. | ||
339 | */ | ||
340 | bool encountered_fatal_error; | ||
341 | |||
342 | /** | ||
343 | * This field specifies that the controller should ignore | ||
344 | * completion processing for non-fastpath events. This will | ||
345 | * cause the completions to be thrown away. | ||
346 | */ | ||
347 | bool restrict_completions; | ||
348 | |||
349 | /* Phy Startup Data */ | ||
350 | /** | ||
351 | * This field is the driver timer handle for controller phy request startup. | ||
352 | * On controller start the controller will start each PHY individually in | ||
353 | * order of phy index. | ||
354 | */ | ||
355 | void *phy_startup_timer; | ||
356 | |||
357 | /** | ||
358 | * This field is set when the phy_startup_timer is running and is cleared when | ||
359 | * the phy_startup_timer is stopped. | ||
360 | */ | ||
361 | bool phy_startup_timer_pending; | ||
362 | |||
363 | /** | ||
364 | * This field is the index of the next phy start. It is initialized to 0 and | ||
365 | * increments for each phy index that is started. | ||
366 | */ | ||
367 | u32 next_phy_to_start; | ||
368 | |||
369 | /** | ||
370 | * This field controlls the invalid link up notifications to the SCI_USER. If | ||
371 | * an invalid_link_up notification is reported a bit for the PHY index is set | ||
372 | * so further notifications are not made. Once the PHY object reports link up | ||
373 | * and is made part of a port then this bit for the PHY index is cleared. | ||
374 | */ | ||
375 | u8 invalid_phy_mask; | ||
376 | |||
377 | /* | ||
378 | * This field saves the current interrupt coalescing number of the controller. | ||
379 | */ | ||
380 | u16 interrupt_coalesce_number; | ||
381 | |||
382 | /* | ||
383 | * This field saves the current interrupt coalescing timeout value in microseconds. | ||
384 | */ | ||
385 | u32 interrupt_coalesce_timeout; | ||
386 | |||
387 | /** | ||
388 | * This field is a pointer to the memory mapped register space for the | ||
389 | * struct smu_registers. | ||
390 | */ | ||
391 | struct smu_registers __iomem *smu_registers; | ||
392 | |||
393 | /** | ||
394 | * This field is a pointer to the memory mapped register space for the | ||
395 | * struct scu_registers. | ||
396 | */ | ||
397 | struct scu_registers __iomem *scu_registers; | ||
398 | |||
399 | }; | ||
400 | |||
401 | typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *, | ||
402 | struct scic_sds_port *, | ||
403 | struct scic_sds_phy *); | ||
404 | /** | ||
405 | * struct scic_sds_controller_state_handler - | ||
406 | * | ||
407 | * This structure contains the SDS core specific definition for the state | ||
408 | * handlers. | ||
409 | */ | ||
410 | struct scic_sds_controller_state_handler { | ||
411 | struct sci_base_controller_state_handler base; | ||
412 | |||
413 | sci_base_controller_request_handler_t terminate_request; | ||
414 | scic_sds_controller_phy_handler_t link_up; | ||
415 | scic_sds_controller_phy_handler_t link_down; | ||
416 | }; | ||
417 | |||
418 | extern const struct scic_sds_controller_state_handler | ||
419 | scic_sds_controller_state_handler_table[]; | ||
420 | extern const struct sci_base_state scic_sds_controller_state_table[]; | ||
421 | |||
422 | /** | ||
423 | * INCREMENT_QUEUE_GET() - | ||
424 | * | ||
425 | * This macro will increment the specified index to and if the index wraps to 0 | ||
426 | * it will toggel the cycle bit. | ||
427 | */ | ||
428 | #define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \ | ||
429 | { \ | ||
430 | if ((index) + 1 == entry_count) { \ | ||
431 | (index) = 0; \ | ||
432 | (cycle) = (cycle) ^ (bit_toggle); \ | ||
433 | } else { \ | ||
434 | index = index + 1; \ | ||
435 | } \ | ||
436 | } | ||
437 | |||
438 | /** | ||
439 | * scic_sds_controller_get_base_state_machine() - | ||
440 | * | ||
441 | * This is a helper macro that gets the base state machine for the controller | ||
442 | * object | ||
443 | */ | ||
444 | #define scic_sds_controller_get_base_state_machine(this_controller) \ | ||
445 | (&(this_controller)->parent.state_machine) | ||
446 | |||
447 | /** | ||
448 | * scic_sds_controller_get_port_configuration_agent() - | ||
449 | * | ||
450 | * This is a helper macro to get the port configuration agent from the | ||
451 | * controller object. | ||
452 | */ | ||
453 | #define scic_sds_controller_get_port_configuration_agent(controller) \ | ||
454 | (&(controller)->port_agent) | ||
455 | |||
456 | /** | ||
457 | * smu_register_write() - | ||
458 | * | ||
459 | * This macro writes to the smu_register for this controller | ||
460 | */ | ||
461 | #define smu_register_write(controller, reg, value) \ | ||
462 | scic_sds_pci_write_smu_dword((controller), &(reg), (value)) | ||
463 | |||
464 | /** | ||
465 | * smu_register_read() - | ||
466 | * | ||
467 | * This macro reads the smu_register for this controller | ||
468 | */ | ||
469 | #define smu_register_read(controller, reg) \ | ||
470 | scic_sds_pci_read_smu_dword((controller), &(reg)) | ||
471 | |||
472 | /** | ||
473 | * scu_register_write() - | ||
474 | * | ||
475 | * This mcaro writes the scu_register for this controller | ||
476 | */ | ||
477 | #define scu_register_write(controller, reg, value) \ | ||
478 | scic_sds_pci_write_scu_dword((controller), &(reg), (value)) | ||
479 | |||
480 | /** | ||
481 | * scu_register_read() - | ||
482 | * | ||
483 | * This macro reads the scu_register for this controller | ||
484 | */ | ||
485 | #define scu_register_read(controller, reg) \ | ||
486 | scic_sds_pci_read_scu_dword((controller), &(reg)) | ||
487 | |||
488 | /** | ||
489 | * scic_sds_controller_get_protocol_engine_group() - | ||
490 | * | ||
491 | * This macro returns the protocol engine group for this controller object. | ||
492 | * Presently we only support protocol engine group 0 so just return that | ||
493 | */ | ||
494 | #define scic_sds_controller_get_protocol_engine_group(controller) 0 | ||
495 | |||
496 | /** | ||
497 | * scic_sds_io_tag_construct() - | ||
498 | * | ||
499 | * This macro constructs an IO tag from the sequence and index values. | ||
500 | */ | ||
501 | #define scic_sds_io_tag_construct(sequence, task_index) \ | ||
502 | ((sequence) << 12 | (task_index)) | ||
503 | |||
504 | /** | ||
505 | * scic_sds_io_tag_get_sequence() - | ||
506 | * | ||
507 | * This macro returns the IO sequence from the IO tag value. | ||
508 | */ | ||
509 | #define scic_sds_io_tag_get_sequence(io_tag) \ | ||
510 | (((io_tag) & 0xF000) >> 12) | ||
511 | |||
512 | /** | ||
513 | * scic_sds_io_tag_get_index() - | ||
514 | * | ||
515 | * This macro returns the TCi from the io tag value | ||
516 | */ | ||
517 | #define scic_sds_io_tag_get_index(io_tag) \ | ||
518 | ((io_tag) & 0x0FFF) | ||
519 | |||
520 | /** | ||
521 | * scic_sds_io_sequence_increment() - | ||
522 | * | ||
523 | * This is a helper macro to increment the io sequence count. We may find in | ||
524 | * the future that it will be faster to store the sequence count in such a way | ||
525 | * as we dont perform the shift operation to build io tag values so therefore | ||
526 | * need a way to incrment them correctly | ||
527 | */ | ||
528 | #define scic_sds_io_sequence_increment(value) \ | ||
529 | ((value) = (((value) + 1) & 0x000F)) | ||
530 | |||
531 | #define scic_sds_remote_device_node_count(device) \ | ||
532 | (\ | ||
533 | (\ | ||
534 | (device)->target_protocols.u.bits.attached_stp_target \ | ||
535 | && ((device)->is_direct_attached != true) \ | ||
536 | ) \ | ||
537 | ? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT \ | ||
538 | ) | ||
539 | |||
540 | /** | ||
541 | * scic_sds_controller_set_invalid_phy() - | ||
542 | * | ||
543 | * This macro will set the bit in the invalid phy mask for this controller | ||
544 | * object. This is used to control messages reported for invalid link up | ||
545 | * notifications. | ||
546 | */ | ||
547 | #define scic_sds_controller_set_invalid_phy(controller, phy) \ | ||
548 | ((controller)->invalid_phy_mask |= (1 << (phy)->phy_index)) | ||
549 | |||
550 | /** | ||
551 | * scic_sds_controller_clear_invalid_phy() - | ||
552 | * | ||
553 | * This macro will clear the bit in the invalid phy mask for this controller | ||
554 | * object. This is used to control messages reported for invalid link up | ||
555 | * notifications. | ||
556 | */ | ||
557 | #define scic_sds_controller_clear_invalid_phy(controller, phy) \ | ||
558 | ((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index)) | ||
559 | |||
560 | /* --------------------------------------------------------------------------- */ | ||
561 | |||
562 | u32 scic_sds_controller_get_object_size(void); | ||
563 | |||
564 | /* --------------------------------------------------------------------------- */ | ||
565 | |||
566 | |||
567 | /* --------------------------------------------------------------------------- */ | ||
568 | |||
569 | enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode( | ||
570 | struct scic_sds_controller *this_controller); | ||
571 | |||
572 | /* --------------------------------------------------------------------------- */ | ||
573 | |||
574 | void scic_sds_controller_post_request( | ||
575 | struct scic_sds_controller *this_controller, | ||
576 | u32 request); | ||
577 | |||
578 | /* --------------------------------------------------------------------------- */ | ||
579 | |||
580 | void scic_sds_controller_release_frame( | ||
581 | struct scic_sds_controller *this_controller, | ||
582 | u32 frame_index); | ||
583 | |||
584 | void scic_sds_controller_copy_sata_response( | ||
585 | void *response_buffer, | ||
586 | void *frame_header, | ||
587 | void *frame_buffer); | ||
588 | |||
589 | /* --------------------------------------------------------------------------- */ | ||
590 | |||
591 | enum sci_status scic_sds_controller_allocate_remote_node_context( | ||
592 | struct scic_sds_controller *this_controller, | ||
593 | struct scic_sds_remote_device *the_device, | ||
594 | u16 *node_id); | ||
595 | |||
596 | void scic_sds_controller_free_remote_node_context( | ||
597 | struct scic_sds_controller *this_controller, | ||
598 | struct scic_sds_remote_device *the_device, | ||
599 | u16 node_id); | ||
600 | |||
601 | union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer( | ||
602 | struct scic_sds_controller *this_controller, | ||
603 | u16 node_id); | ||
604 | |||
605 | /* --------------------------------------------------------------------------- */ | ||
606 | |||
607 | struct scic_sds_request *scic_sds_controller_get_io_request_from_tag( | ||
608 | struct scic_sds_controller *this_controller, | ||
609 | u16 io_tag); | ||
610 | |||
611 | |||
612 | struct scu_task_context *scic_sds_controller_get_task_context_buffer( | ||
613 | struct scic_sds_controller *this_controller, | ||
614 | u16 io_tag); | ||
615 | |||
616 | /* | ||
617 | * ***************************************************************************** | ||
618 | * * CORE CONTROLLER POWER CONTROL METHODS | ||
619 | * ***************************************************************************** */ | ||
620 | |||
621 | |||
622 | void scic_sds_controller_power_control_queue_insert( | ||
623 | struct scic_sds_controller *this_controller, | ||
624 | struct scic_sds_phy *the_phy); | ||
625 | |||
626 | void scic_sds_controller_power_control_queue_remove( | ||
627 | struct scic_sds_controller *this_controller, | ||
628 | struct scic_sds_phy *the_phy); | ||
629 | |||
630 | /* | ||
631 | * ***************************************************************************** | ||
632 | * * CORE CONTROLLER PHY MESSAGE PROCESSING | ||
633 | * ***************************************************************************** */ | ||
634 | |||
635 | void scic_sds_controller_link_up( | ||
636 | struct scic_sds_controller *this_controller, | ||
637 | struct scic_sds_port *the_port, | ||
638 | struct scic_sds_phy *the_phy); | ||
639 | |||
640 | void scic_sds_controller_link_down( | ||
641 | struct scic_sds_controller *this_controller, | ||
642 | struct scic_sds_port *the_port, | ||
643 | struct scic_sds_phy *the_phy); | ||
644 | |||
645 | /* | ||
646 | * ***************************************************************************** | ||
647 | * * CORE CONTROLLER PRIVATE METHODS | ||
648 | * ***************************************************************************** */ | ||
649 | |||
650 | enum sci_status scic_sds_controller_validate_memory_descriptor_table( | ||
651 | struct scic_sds_controller *this_controller); | ||
652 | |||
653 | void scic_sds_controller_ram_initialization( | ||
654 | struct scic_sds_controller *this_controller); | ||
655 | |||
656 | void scic_sds_controller_assign_task_entries( | ||
657 | struct scic_sds_controller *this_controller); | ||
658 | |||
659 | void scic_sds_controller_afe_initialization( | ||
660 | struct scic_sds_controller *this_controller); | ||
661 | |||
662 | void scic_sds_controller_enable_port_task_scheduler( | ||
663 | struct scic_sds_controller *this_controller); | ||
664 | |||
665 | void scic_sds_controller_initialize_completion_queue( | ||
666 | struct scic_sds_controller *this_controller); | ||
667 | |||
668 | void scic_sds_controller_initialize_unsolicited_frame_queue( | ||
669 | struct scic_sds_controller *this_controller); | ||
670 | |||
671 | void scic_sds_controller_phy_timer_stop( | ||
672 | struct scic_sds_controller *this_controller); | ||
673 | |||
674 | enum sci_status scic_sds_controller_start_next_phy( | ||
675 | struct scic_sds_controller *this_controller); | ||
676 | |||
677 | enum sci_status scic_sds_controller_stop_phys( | ||
678 | struct scic_sds_controller *this_controller); | ||
679 | |||
680 | enum sci_status scic_sds_controller_stop_ports( | ||
681 | struct scic_sds_controller *this_controller); | ||
682 | |||
683 | enum sci_status scic_sds_controller_stop_devices( | ||
684 | struct scic_sds_controller *this_controller); | ||
685 | |||
686 | void scic_sds_controller_copy_task_context( | ||
687 | struct scic_sds_controller *this_controller, | ||
688 | struct scic_sds_request *this_request); | ||
689 | |||
690 | void scic_sds_controller_timeout_handler( | ||
691 | struct scic_sds_controller *controller); | ||
692 | |||
693 | void scic_sds_controller_initialize_power_control( | ||
694 | struct scic_sds_controller *this_controller); | ||
695 | |||
696 | void scic_sds_controller_register_setup( | ||
697 | struct scic_sds_controller *this_controller); | ||
698 | |||
699 | void scic_sds_controller_reset_hardware( | ||
700 | struct scic_sds_controller *this_controller); | ||
701 | |||
702 | |||
703 | void scic_sds_controller_initialize_phy_startup( | ||
704 | struct scic_sds_controller *this_controller); | ||
705 | |||
706 | #endif /* _SCIC_SDS_CONTROLLER_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_controller_registers.h b/drivers/scsi/isci/core/scic_sds_controller_registers.h new file mode 100644 index 000000000000..b7bec92ee59c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_controller_registers.h | |||
@@ -0,0 +1,463 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_CONTROLLER_REGISTERS_H_ | ||
57 | #define _SCIC_SDS_CONTROLLER_REGISTERS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains macros used to perform the register reads/writes to the | ||
61 | * SCU hardware. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "scu_registers.h" | ||
67 | #include "scic_sds_controller.h" | ||
68 | |||
69 | /** | ||
70 | * scic_sds_controller_smu_register_read() - | ||
71 | * | ||
72 | * SMU_REGISTER_ACCESS_MACROS | ||
73 | */ | ||
74 | #define scic_sds_controller_smu_register_read(controller, reg) \ | ||
75 | smu_register_read(\ | ||
76 | (controller), \ | ||
77 | (controller)->smu_registers->reg \ | ||
78 | ) | ||
79 | |||
80 | #define scic_sds_controller_smu_register_write(controller, reg, value) \ | ||
81 | smu_register_write(\ | ||
82 | (controller), \ | ||
83 | (controller)->smu_registers->reg, \ | ||
84 | (value) \ | ||
85 | ) | ||
86 | |||
87 | /** | ||
88 | * scu_afe_register_write() - | ||
89 | * | ||
90 | * AFE_REGISTER_ACCESS_MACROS | ||
91 | */ | ||
92 | #define scu_afe_register_write(controller, reg, value) \ | ||
93 | scu_register_write(\ | ||
94 | (controller), \ | ||
95 | (controller)->scu_registers->afe.reg, \ | ||
96 | (value) \ | ||
97 | ) | ||
98 | |||
99 | #define scu_afe_txreg_write(controller, phy, reg, value) \ | ||
100 | scu_register_write(\ | ||
101 | (controller), \ | ||
102 | (controller)->scu_registers->afe.scu_afe_xcvr[phy].reg,\ | ||
103 | (value) \ | ||
104 | ) | ||
105 | |||
106 | #define scu_afe_register_read(controller, reg) \ | ||
107 | scu_register_read(\ | ||
108 | (controller), \ | ||
109 | (controller)->scu_registers->afe.reg \ | ||
110 | ) | ||
111 | |||
112 | /** | ||
113 | * scu_controller_viit_register_write() - | ||
114 | * | ||
115 | * VIIT_REGISTER_ACCESS_MACROS | ||
116 | */ | ||
117 | #define scu_controller_viit_register_write(controller, index, reg, value) \ | ||
118 | scu_register_write(\ | ||
119 | (controller), \ | ||
120 | (controller)->scu_registers->peg0.viit[index].reg, \ | ||
121 | value \ | ||
122 | ) | ||
123 | |||
124 | /* | ||
125 | * ***************************************************************************** | ||
126 | * * SMU REGISTERS | ||
127 | * ***************************************************************************** */ | ||
128 | |||
129 | /** | ||
130 | * SMU_PCP_WRITE() - | ||
131 | * | ||
132 | * struct smu_registers | ||
133 | */ | ||
134 | #define SMU_PCP_WRITE(controller, value) \ | ||
135 | scic_sds_controller_smu_register_write(\ | ||
136 | controller, post_context_port, value \ | ||
137 | ) | ||
138 | |||
139 | #define SMU_TCR_READ(controller, value) \ | ||
140 | scic_sds_controller_smu_register_read(\ | ||
141 | controller, task_context_range \ | ||
142 | ) | ||
143 | |||
144 | #define SMU_TCR_WRITE(controller, value) \ | ||
145 | scic_sds_controller_smu_register_write(\ | ||
146 | controller, task_context_range, value \ | ||
147 | ) | ||
148 | |||
149 | #define SMU_HTTBAR_WRITE(controller, address) \ | ||
150 | { \ | ||
151 | scic_sds_controller_smu_register_write(\ | ||
152 | controller, \ | ||
153 | host_task_table_lower, \ | ||
154 | lower_32_bits(address) \ | ||
155 | ); \ | ||
156 | scic_sds_controller_smu_register_write(\ | ||
157 | controller, \ | ||
158 | host_task_table_upper, \ | ||
159 | upper_32_bits(address) \ | ||
160 | ); \ | ||
161 | } | ||
162 | |||
163 | #define SMU_CQBAR_WRITE(controller, address) \ | ||
164 | { \ | ||
165 | scic_sds_controller_smu_register_write(\ | ||
166 | controller, \ | ||
167 | completion_queue_lower, \ | ||
168 | lower_32_bits(address) \ | ||
169 | ); \ | ||
170 | scic_sds_controller_smu_register_write(\ | ||
171 | controller, \ | ||
172 | completion_queue_upper, \ | ||
173 | upper_32_bits(address) \ | ||
174 | ); \ | ||
175 | } | ||
176 | |||
177 | #define SMU_CQGR_WRITE(controller, value) \ | ||
178 | scic_sds_controller_smu_register_write(\ | ||
179 | controller, completion_queue_get, value \ | ||
180 | ) | ||
181 | |||
182 | #define SMU_CQGR_READ(controller, value) \ | ||
183 | scic_sds_controller_smu_register_read(\ | ||
184 | controller, completion_queue_get \ | ||
185 | ) | ||
186 | |||
187 | #define SMU_CQPR_WRITE(controller, value) \ | ||
188 | scic_sds_controller_smu_register_write(\ | ||
189 | controller, completion_queue_put, value \ | ||
190 | ) | ||
191 | |||
192 | #define SMU_RNCBAR_WRITE(controller, address) \ | ||
193 | { \ | ||
194 | scic_sds_controller_smu_register_write(\ | ||
195 | controller, \ | ||
196 | remote_node_context_lower, \ | ||
197 | lower_32_bits(address) \ | ||
198 | ); \ | ||
199 | scic_sds_controller_smu_register_write(\ | ||
200 | controller, \ | ||
201 | remote_node_context_upper, \ | ||
202 | upper_32_bits(address) \ | ||
203 | ); \ | ||
204 | } | ||
205 | |||
206 | #define SMU_AMR_READ(controller) \ | ||
207 | scic_sds_controller_smu_register_read(\ | ||
208 | controller, address_modifier \ | ||
209 | ) | ||
210 | |||
211 | #define SMU_IMR_READ(controller) \ | ||
212 | scic_sds_controller_smu_register_read(\ | ||
213 | controller, interrupt_mask \ | ||
214 | ) | ||
215 | |||
216 | #define SMU_IMR_WRITE(controller, mask) \ | ||
217 | scic_sds_controller_smu_register_write(\ | ||
218 | controller, interrupt_mask, mask \ | ||
219 | ) | ||
220 | |||
221 | #define SMU_ISR_READ(controller) \ | ||
222 | scic_sds_controller_smu_register_read(\ | ||
223 | controller, interrupt_status \ | ||
224 | ) | ||
225 | |||
226 | #define SMU_ISR_WRITE(controller, status) \ | ||
227 | scic_sds_controller_smu_register_write(\ | ||
228 | controller, interrupt_status, status \ | ||
229 | ) | ||
230 | |||
231 | #define SMU_ICC_READ(controller) \ | ||
232 | scic_sds_controller_smu_register_read(\ | ||
233 | controller, interrupt_coalesce_control \ | ||
234 | ) | ||
235 | |||
236 | #define SMU_ICC_WRITE(controller, value) \ | ||
237 | scic_sds_controller_smu_register_write(\ | ||
238 | controller, interrupt_coalesce_control, value \ | ||
239 | ) | ||
240 | |||
241 | #define SMU_CQC_WRITE(controller, value) \ | ||
242 | scic_sds_controller_smu_register_write(\ | ||
243 | controller, completion_queue_control, value \ | ||
244 | ) | ||
245 | |||
246 | #define SMU_SMUSRCR_WRITE(controller, value) \ | ||
247 | scic_sds_controller_smu_register_write(\ | ||
248 | controller, soft_reset_control, value \ | ||
249 | ) | ||
250 | |||
251 | #define SMU_TCA_WRITE(controller, index, value) \ | ||
252 | scic_sds_controller_smu_register_write(\ | ||
253 | controller, task_context_assignment[index], value \ | ||
254 | ) | ||
255 | |||
256 | #define SMU_TCA_READ(controller, index) \ | ||
257 | scic_sds_controller_smu_register_read(\ | ||
258 | controller, task_context_assignment[index] \ | ||
259 | ) | ||
260 | |||
261 | #define SMU_DCC_READ(controller) \ | ||
262 | scic_sds_controller_smu_register_read(\ | ||
263 | controller, device_context_capacity \ | ||
264 | ) | ||
265 | |||
266 | #define SMU_DFC_READ(controller) \ | ||
267 | scic_sds_controller_smu_register_read(\ | ||
268 | controller, device_function_capacity \ | ||
269 | ) | ||
270 | |||
271 | #define SMU_SMUCSR_READ(controller) \ | ||
272 | scic_sds_controller_smu_register_read(\ | ||
273 | controller, control_status \ | ||
274 | ) | ||
275 | |||
276 | #define SMU_CQPR_READ(controller) \ | ||
277 | scic_sds_controller_smu_register_read(\ | ||
278 | controller, completion_queue_put \ | ||
279 | ) | ||
280 | |||
281 | |||
282 | /** | ||
283 | * scic_sds_controller_scu_register_read() - | ||
284 | * | ||
285 | * SCU_REGISTER_ACCESS_MACROS | ||
286 | */ | ||
287 | #define scic_sds_controller_scu_register_read(controller, reg) \ | ||
288 | scu_register_read(\ | ||
289 | (controller), \ | ||
290 | (controller)->scu_registers->reg \ | ||
291 | ) | ||
292 | |||
293 | #define scic_sds_controller_scu_register_write(controller, reg, value) \ | ||
294 | scu_register_write(\ | ||
295 | (controller), \ | ||
296 | (controller)->scu_registers->reg, \ | ||
297 | (value) \ | ||
298 | ) | ||
299 | |||
300 | |||
301 | /* | ||
302 | * **************************************************************************** | ||
303 | * * SCU SDMA REGISTERS | ||
304 | * **************************************************************************** */ | ||
305 | |||
306 | /** | ||
307 | * scu_sdma_register_read() - | ||
308 | * | ||
309 | * SCU_SDMA_REGISTER_ACCESS_MACROS | ||
310 | */ | ||
311 | #define scu_sdma_register_read(controller, reg) \ | ||
312 | scu_register_read(\ | ||
313 | (controller), \ | ||
314 | (controller)->scu_registers->sdma.reg \ | ||
315 | ) | ||
316 | |||
317 | #define scu_sdma_register_write(controller, reg, value) \ | ||
318 | scu_register_write(\ | ||
319 | (controller), \ | ||
320 | (controller)->scu_registers->sdma.reg, \ | ||
321 | (value) \ | ||
322 | ) | ||
323 | |||
324 | /** | ||
325 | * SCU_PUFATHAR_WRITE() - | ||
326 | * | ||
327 | * struct scu_sdma_registers | ||
328 | */ | ||
329 | #define SCU_PUFATHAR_WRITE(controller, address) \ | ||
330 | { \ | ||
331 | scu_sdma_register_write(\ | ||
332 | controller, \ | ||
333 | uf_address_table_lower, \ | ||
334 | lower_32_bits(address) \ | ||
335 | ); \ | ||
336 | scu_sdma_register_write(\ | ||
337 | controller, \ | ||
338 | uf_address_table_upper, \ | ||
339 | upper_32_bits(address) \ | ||
340 | ); \ | ||
341 | } | ||
342 | |||
343 | #define SCU_UFHBAR_WRITE(controller, address) \ | ||
344 | { \ | ||
345 | scu_sdma_register_write(\ | ||
346 | controller, \ | ||
347 | uf_header_base_address_lower, \ | ||
348 | lower_32_bits(address) \ | ||
349 | ); \ | ||
350 | scu_sdma_register_write(\ | ||
351 | controller, \ | ||
352 | uf_header_base_address_upper, \ | ||
353 | upper_32_bits(address) \ | ||
354 | ); \ | ||
355 | } | ||
356 | |||
357 | #define SCU_UFQC_READ(controller) \ | ||
358 | scu_sdma_register_read(\ | ||
359 | controller, \ | ||
360 | unsolicited_frame_queue_control \ | ||
361 | ) | ||
362 | |||
363 | #define SCU_UFQC_WRITE(controller, value) \ | ||
364 | scu_sdma_register_write(\ | ||
365 | controller, \ | ||
366 | unsolicited_frame_queue_control, \ | ||
367 | value \ | ||
368 | ) | ||
369 | |||
370 | #define SCU_UFQPP_READ(controller) \ | ||
371 | scu_sdma_register_read(\ | ||
372 | controller, \ | ||
373 | unsolicited_frame_put_pointer \ | ||
374 | ) | ||
375 | |||
376 | #define SCU_UFQPP_WRITE(controller, value) \ | ||
377 | scu_sdma_register_write(\ | ||
378 | controller, \ | ||
379 | unsolicited_frame_put_pointer, \ | ||
380 | value \ | ||
381 | ) | ||
382 | |||
383 | #define SCU_UFQGP_WRITE(controller, value) \ | ||
384 | scu_sdma_register_write(\ | ||
385 | controller, \ | ||
386 | unsolicited_frame_get_pointer, \ | ||
387 | value \ | ||
388 | ) | ||
389 | |||
390 | #define SCU_PDMACR_READ(controller) \ | ||
391 | scu_sdma_register_read(\ | ||
392 | controller, \ | ||
393 | pdma_configuration \ | ||
394 | ) | ||
395 | |||
396 | #define SCU_PDMACR_WRITE(controller, value) \ | ||
397 | scu_sdma_register_write(\ | ||
398 | controller, \ | ||
399 | pdma_configuration, \ | ||
400 | value \ | ||
401 | ) | ||
402 | |||
403 | #define SCU_CDMACR_READ(controller) \ | ||
404 | scu_sdma_register_read(\ | ||
405 | controller, \ | ||
406 | cdma_configuration \ | ||
407 | ) | ||
408 | |||
409 | #define SCU_CDMACR_WRITE(controller, value) \ | ||
410 | scu_sdma_register_write(\ | ||
411 | controller, \ | ||
412 | cdma_configuration, \ | ||
413 | value \ | ||
414 | ) | ||
415 | |||
416 | /* | ||
417 | * ***************************************************************************** | ||
418 | * * SCU Port Task Scheduler Group Registers | ||
419 | * ***************************************************************************** */ | ||
420 | |||
421 | /** | ||
422 | * scu_ptsg_register_read() - | ||
423 | * | ||
424 | * SCU_PTSG_REGISTER_ACCESS_MACROS | ||
425 | */ | ||
426 | #define scu_ptsg_register_read(controller, reg) \ | ||
427 | scu_register_read(\ | ||
428 | (controller), \ | ||
429 | (controller)->scu_registers->peg0.ptsg.reg \ | ||
430 | ) | ||
431 | |||
432 | #define scu_ptsg_register_write(controller, reg, value) \ | ||
433 | scu_register_write(\ | ||
434 | (controller), \ | ||
435 | (controller)->scu_registers->peg0.ptsg.reg, \ | ||
436 | (value) \ | ||
437 | ) | ||
438 | |||
439 | /** | ||
440 | * SCU_PTSGCR_READ() - | ||
441 | * | ||
442 | * SCU_PTSG_REGISTERS | ||
443 | */ | ||
444 | #define SCU_PTSGCR_READ(controller) \ | ||
445 | scu_ptsg_register_read(\ | ||
446 | (controller), \ | ||
447 | control \ | ||
448 | ) | ||
449 | |||
450 | #define SCU_PTSGCR_WRITE(controller, value) \ | ||
451 | scu_ptsg_register_write(\ | ||
452 | (controller), \ | ||
453 | control, \ | ||
454 | value \ | ||
455 | ) | ||
456 | |||
457 | #define SCU_PTSGRTC_READ(controller) \ | ||
458 | scu_ptsg_register_read(\ | ||
459 | contoller, \ | ||
460 | real_time_clock \ | ||
461 | ) | ||
462 | |||
463 | #endif /* _SCIC_SDS_CONTROLLER_REGISTERS_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_pci.h b/drivers/scsi/isci/core/scic_sds_pci.h new file mode 100644 index 000000000000..21326777acc6 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_pci.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_PCI_H_ | ||
57 | #define _SCIC_SDS_PCI_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the prototypes/macros utilized in writing out PCI data | ||
61 | * for the SCI core. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include <asm/io.h> | ||
67 | #include "sci_types.h" | ||
68 | |||
69 | struct scic_sds_controller; | ||
70 | |||
71 | void scic_sds_pci_bar_initialization(struct scic_sds_controller *scic); | ||
72 | |||
73 | /* for debug we separate scu and smu accesses and require a controller */ | ||
74 | static inline u32 scic_sds_pci_read_smu_dword(struct scic_sds_controller *scic, void __iomem *addr) | ||
75 | { | ||
76 | return readl(addr); | ||
77 | } | ||
78 | |||
79 | static inline void scic_sds_pci_write_smu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value) | ||
80 | { | ||
81 | writel(value, addr); | ||
82 | } | ||
83 | |||
84 | static inline u32 scic_sds_pci_read_scu_dword(struct scic_sds_controller *scic, void __iomem *addr) | ||
85 | { | ||
86 | return readl(addr); | ||
87 | } | ||
88 | |||
89 | static inline void scic_sds_pci_write_scu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value) | ||
90 | { | ||
91 | writel(value, addr); | ||
92 | } | ||
93 | |||
94 | |||
95 | #endif /* _SCIC_SDS_PCI_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c new file mode 100644 index 000000000000..7d012b571b5b --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_phy.c | |||
@@ -0,0 +1,2807 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "intel_ata.h" | ||
57 | #include "intel_sata.h" | ||
58 | #include "sci_base_state.h" | ||
59 | #include "sci_base_state_machine.h" | ||
60 | #include "scic_phy.h" | ||
61 | #include "scic_sds_controller.h" | ||
62 | #include "scic_sds_phy.h" | ||
63 | #include "scic_sds_phy_registers.h" | ||
64 | #include "scic_sds_port.h" | ||
65 | #include "scic_user_callback.h" | ||
66 | #include "sci_environment.h" | ||
67 | #include "sci_util.h" | ||
68 | #include "scu_event_codes.h" | ||
69 | |||
70 | #define SCIC_SDS_PHY_MIN_TIMER_COUNT (SCI_MAX_PHYS) | ||
71 | #define SCIC_SDS_PHY_MAX_TIMER_COUNT (SCI_MAX_PHYS) | ||
72 | |||
73 | /* Maximum arbitration wait time in micro-seconds */ | ||
74 | #define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700) | ||
75 | |||
76 | /* | ||
77 | * ***************************************************************************** | ||
78 | * * SCIC SDS PHY Internal Methods | ||
79 | * ***************************************************************************** */ | ||
80 | |||
81 | /** | ||
82 | * This method will initialize the phy link layer registers | ||
83 | * @this_phy: | ||
84 | * @link_layer_registers: | ||
85 | * | ||
86 | * enum sci_status | ||
87 | */ | ||
88 | static enum sci_status scic_sds_phy_link_layer_initialization( | ||
89 | struct scic_sds_phy *this_phy, | ||
90 | struct scu_link_layer_registers *link_layer_registers) | ||
91 | { | ||
92 | u32 phy_configuration; | ||
93 | struct sas_capabilities phy_capabilities; | ||
94 | u32 parity_check = 0; | ||
95 | u32 parity_count = 0; | ||
96 | u32 link_layer_control; | ||
97 | |||
98 | this_phy->link_layer_registers = link_layer_registers; | ||
99 | |||
100 | /* Set our IDENTIFY frame data */ | ||
101 | #define SCI_END_DEVICE 0x01 | ||
102 | |||
103 | SCU_SAS_TIID_WRITE( | ||
104 | this_phy, | ||
105 | (SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) | ||
106 | | SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) | ||
107 | | SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) | ||
108 | | SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) | ||
109 | | SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE)) | ||
110 | ); | ||
111 | |||
112 | /* Write the device SAS Address */ | ||
113 | SCU_SAS_TIDNH_WRITE(this_phy, 0xFEDCBA98); | ||
114 | SCU_SAS_TIDNL_WRITE(this_phy, this_phy->phy_index); | ||
115 | |||
116 | /* Write the source SAS Address */ | ||
117 | SCU_SAS_TISSAH_WRITE( | ||
118 | this_phy, | ||
119 | this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ | ||
120 | this_phy->phy_index].sas_address.high | ||
121 | ); | ||
122 | SCU_SAS_TISSAL_WRITE( | ||
123 | this_phy, | ||
124 | this_phy->owning_port->owning_controller->oem_parameters.sds1.phys[ | ||
125 | this_phy->phy_index].sas_address.low | ||
126 | ); | ||
127 | |||
128 | /* Clear and Set the PHY Identifier */ | ||
129 | SCU_SAS_TIPID_WRITE(this_phy, 0x00000000); | ||
130 | SCU_SAS_TIPID_WRITE(this_phy, SCU_SAS_TIPID_GEN_VALUE(ID, this_phy->phy_index)); | ||
131 | |||
132 | /* Change the initial state of the phy configuration register */ | ||
133 | phy_configuration = SCU_SAS_PCFG_READ(this_phy); | ||
134 | |||
135 | /* Hold OOB state machine in reset */ | ||
136 | phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); | ||
137 | SCU_SAS_PCFG_WRITE(this_phy, phy_configuration); | ||
138 | |||
139 | /* Configure the SNW capabilities */ | ||
140 | phy_capabilities.u.all = 0; | ||
141 | phy_capabilities.u.bits.start = 1; | ||
142 | phy_capabilities.u.bits.gen3_without_ssc_supported = 1; | ||
143 | phy_capabilities.u.bits.gen2_without_ssc_supported = 1; | ||
144 | phy_capabilities.u.bits.gen1_without_ssc_supported = 1; | ||
145 | if (this_phy->owning_port->owning_controller->oem_parameters.sds1. | ||
146 | controller.do_enable_ssc == true) { | ||
147 | phy_capabilities.u.bits.gen3_with_ssc_supported = 1; | ||
148 | phy_capabilities.u.bits.gen2_with_ssc_supported = 1; | ||
149 | phy_capabilities.u.bits.gen1_with_ssc_supported = 1; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * The SAS specification indicates that the phy_capabilities that | ||
154 | * are transmitted shall have an even parity. Calculate the parity. */ | ||
155 | parity_check = phy_capabilities.u.all; | ||
156 | while (parity_check != 0) { | ||
157 | if (parity_check & 0x1) | ||
158 | parity_count++; | ||
159 | parity_check >>= 1; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * If parity indicates there are an odd number of bits set, then | ||
164 | * set the parity bit to 1 in the phy capabilities. */ | ||
165 | if ((parity_count % 2) != 0) | ||
166 | phy_capabilities.u.bits.parity = 1; | ||
167 | |||
168 | SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all); | ||
169 | |||
170 | /* Set the enable spinup period but disable the ability to send notify enable spinup */ | ||
171 | SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, 0x33)); | ||
172 | |||
173 | #if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) || defined(CONFIG_PBG_HBA_BETA) | ||
174 | /* / @todo Provide a way to write this register correctly */ | ||
175 | scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x02108421); | ||
176 | #else | ||
177 | /* / @todo Provide a way to write this register correctly */ | ||
178 | scu_link_layer_register_write(this_phy, afe_lookup_table_control, 0x0e739ce7); | ||
179 | #endif | ||
180 | |||
181 | link_layer_control = SCU_SAS_LLCTL_GEN_VAL( | ||
182 | NO_OUTBOUND_TASK_TIMEOUT, | ||
183 | (u8)this_phy->owning_port->owning_controller-> | ||
184 | user_parameters.sds1.no_outbound_task_timeout | ||
185 | ); | ||
186 | |||
187 | /* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 */ | ||
188 | /* #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 */ | ||
189 | #define COMPILED_MAX_LINK_RATE SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 | ||
190 | |||
191 | if (this_phy->owning_port->owning_controller->user_parameters.sds1. | ||
192 | phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN3_SPEED) { | ||
193 | link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( | ||
194 | MAX_LINK_RATE, COMPILED_MAX_LINK_RATE | ||
195 | ); | ||
196 | } else if (this_phy->owning_port->owning_controller->user_parameters.sds1. | ||
197 | phys[this_phy->phy_index].max_speed_generation == SCIC_SDS_PARM_GEN2_SPEED) { | ||
198 | link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( | ||
199 | MAX_LINK_RATE, | ||
200 | min( | ||
201 | SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2, | ||
202 | COMPILED_MAX_LINK_RATE) | ||
203 | ); | ||
204 | } else { | ||
205 | link_layer_control |= SCU_SAS_LLCTL_GEN_VAL( | ||
206 | MAX_LINK_RATE, | ||
207 | min( | ||
208 | SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1, | ||
209 | COMPILED_MAX_LINK_RATE) | ||
210 | ); | ||
211 | } | ||
212 | |||
213 | scu_link_layer_register_write( | ||
214 | this_phy, link_layer_control, link_layer_control | ||
215 | ); | ||
216 | |||
217 | /* | ||
218 | * Program the max ARB time for the PHY to 700us so we inter-operate with | ||
219 | * the PMC expander which shuts down PHYs if the expander PHY generates too | ||
220 | * many breaks. This time value will guarantee that the initiator PHY will | ||
221 | * generate the break. */ | ||
222 | #if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) | ||
223 | scu_link_layer_register_write( | ||
224 | this_phy, | ||
225 | maximum_arbitration_wait_timer_timeout, | ||
226 | SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME | ||
227 | ); | ||
228 | #endif /* defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) */ | ||
229 | |||
230 | /* | ||
231 | * Set the link layer hang detection to 500ms (0x1F4) from its default | ||
232 | * value of 128ms. Max value is 511 ms. */ | ||
233 | scu_link_layer_register_write( | ||
234 | this_phy, link_layer_hang_detection_timeout, 0x1F4 | ||
235 | ); | ||
236 | |||
237 | /* We can exit the initial state to the stopped state */ | ||
238 | sci_base_state_machine_change_state( | ||
239 | scic_sds_phy_get_base_state_machine(this_phy), | ||
240 | SCI_BASE_PHY_STATE_STOPPED | ||
241 | ); | ||
242 | |||
243 | return SCI_SUCCESS; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * This function will handle the sata SIGNATURE FIS timeout condition. It will | ||
248 | * restart the starting substate machine since we dont know what has actually | ||
249 | * happening. | ||
250 | */ | ||
251 | static void scic_sds_phy_sata_timeout(void *phy) | ||
252 | { | ||
253 | struct scic_sds_phy *sci_phy = phy; | ||
254 | |||
255 | dev_dbg(sciphy_to_dev(sci_phy), | ||
256 | "%s: SCIC SDS Phy 0x%p did not receive signature fis before " | ||
257 | "timeout.\n", | ||
258 | __func__, | ||
259 | sci_phy); | ||
260 | |||
261 | sci_base_state_machine_stop( | ||
262 | scic_sds_phy_get_starting_substate_machine(sci_phy)); | ||
263 | |||
264 | sci_base_state_machine_change_state( | ||
265 | scic_sds_phy_get_base_state_machine(sci_phy), | ||
266 | SCI_BASE_PHY_STATE_STARTING | ||
267 | ); | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * ***************************************************************************** | ||
272 | * * SCIC SDS PHY External Methods | ||
273 | * ***************************************************************************** */ | ||
274 | |||
275 | /** | ||
276 | * This method returns the object size for a phy object. | ||
277 | * | ||
278 | * u32 | ||
279 | */ | ||
280 | |||
281 | /** | ||
282 | * This method returns the minimum number of timers required for a phy object. | ||
283 | * | ||
284 | * u32 | ||
285 | */ | ||
286 | |||
287 | /** | ||
288 | * This method returns the maximum number of timers required for a phy object. | ||
289 | * | ||
290 | * u32 | ||
291 | */ | ||
292 | |||
293 | #ifdef SCIC_DEBUG_ENABLED | ||
294 | /** | ||
295 | * scic_sds_phy_observe_state_change() - | ||
296 | * @our_observer: | ||
297 | * | ||
298 | * Debug code to record the state transitions in the phy | ||
299 | */ | ||
300 | void scic_sds_phy_observe_state_change( | ||
301 | struct sci_base_observer *our_observer, | ||
302 | struct sci_base_subject *the_subject) | ||
303 | { | ||
304 | struct scic_sds_phy *this_phy; | ||
305 | struct sci_base_state_machine *the_state_machine; | ||
306 | |||
307 | u8 transition_requestor; | ||
308 | u32 base_state_id; | ||
309 | u32 starting_substate_id; | ||
310 | |||
311 | the_state_machine = (struct sci_base_state_machine *)the_subject; | ||
312 | this_phy = (struct scic_sds_phy *)the_state_machine->state_machine_owner; | ||
313 | |||
314 | if (the_state_machine == &this_phy->parent.state_machine) { | ||
315 | transition_requestor = 0x01; | ||
316 | } else if (the_state_machine == &this_phy->starting_substate_machine) { | ||
317 | transition_requestor = 0x02; | ||
318 | } else { | ||
319 | transition_requestor = 0xFF; | ||
320 | } | ||
321 | |||
322 | base_state_id = | ||
323 | sci_base_state_machine_get_state(&this_phy->parent.state_machine); | ||
324 | starting_substate_id = | ||
325 | sci_base_state_machine_get_state(&this_phy->starting_substate_machine); | ||
326 | |||
327 | this_phy->state_record.state_transition_table[ | ||
328 | this_phy->state_record.index++] = ((transition_requestor << 24) | ||
329 | | ((u8)base_state_id << 8) | ||
330 | | ((u8)starting_substate_id)); | ||
331 | |||
332 | this_phy->state_record.index = | ||
333 | this_phy->state_record.index & (MAX_STATE_TRANSITION_RECORD - 1); | ||
334 | |||
335 | } | ||
336 | #endif /* SCIC_DEBUG_ENABLED */ | ||
337 | |||
338 | #ifdef SCIC_DEBUG_ENABLED | ||
339 | /** | ||
340 | * scic_sds_phy_initialize_state_recording() - | ||
341 | * | ||
342 | * This method initializes the state record debug information for the phy | ||
343 | * object. The state machines for the phy object must be constructed before | ||
344 | * this function is called. | ||
345 | */ | ||
346 | void scic_sds_phy_initialize_state_recording( | ||
347 | struct scic_sds_phy *this_phy) | ||
348 | { | ||
349 | this_phy->state_record.index = 0; | ||
350 | |||
351 | sci_base_observer_initialize( | ||
352 | &this_phy->state_record.base_state_observer, | ||
353 | scic_sds_phy_observe_state_change, | ||
354 | &this_phy->parent.state_machine.parent | ||
355 | ); | ||
356 | |||
357 | sci_base_observer_initialize( | ||
358 | &this_phy->state_record.starting_state_observer, | ||
359 | scic_sds_phy_observe_state_change, | ||
360 | &this_phy->starting_substate_machine.parent | ||
361 | ); | ||
362 | } | ||
363 | #endif /* SCIC_DEBUG_ENABLED */ | ||
364 | |||
365 | /** | ||
366 | * This method will construct the struct scic_sds_phy object | ||
367 | * @this_phy: | ||
368 | * @owning_port: | ||
369 | * @phy_index: | ||
370 | * | ||
371 | */ | ||
372 | void scic_sds_phy_construct( | ||
373 | struct scic_sds_phy *this_phy, | ||
374 | struct scic_sds_port *owning_port, | ||
375 | u8 phy_index) | ||
376 | { | ||
377 | /* | ||
378 | * Call the base constructor first | ||
379 | */ | ||
380 | sci_base_phy_construct( | ||
381 | &this_phy->parent, | ||
382 | scic_sds_phy_state_table | ||
383 | ); | ||
384 | |||
385 | /* Copy the rest of the input data to our locals */ | ||
386 | this_phy->owning_port = owning_port; | ||
387 | this_phy->phy_index = phy_index; | ||
388 | this_phy->bcn_received_while_port_unassigned = false; | ||
389 | this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; | ||
390 | this_phy->link_layer_registers = NULL; | ||
391 | this_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; | ||
392 | |||
393 | /* Clear out the identification buffer data */ | ||
394 | memset(&this_phy->phy_type, 0, sizeof(this_phy->phy_type)); | ||
395 | |||
396 | /* Initialize the the substate machines */ | ||
397 | sci_base_state_machine_construct( | ||
398 | &this_phy->starting_substate_machine, | ||
399 | &this_phy->parent.parent, | ||
400 | scic_sds_phy_starting_substates, | ||
401 | SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL | ||
402 | ); | ||
403 | |||
404 | #ifdef SCIC_DEBUG_ENABLED | ||
405 | scic_sds_phy_initialize_state_recording(this_phy); | ||
406 | #endif /* SCIC_DEBUG_ENABLED */ | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * This method returns the port currently containing this phy. If the phy is | ||
411 | * currently contained by the dummy port, then the phy is considered to not | ||
412 | * be part of a port. | ||
413 | * @this_phy: This parameter specifies the phy for which to retrieve the | ||
414 | * containing port. | ||
415 | * | ||
416 | * This method returns a handle to a port that contains the supplied phy. | ||
417 | * SCI_INVALID_HANDLE This value is returned if the phy is not part of a real | ||
418 | * port (i.e. it's contained in the dummy port). !SCI_INVALID_HANDLE All other | ||
419 | * values indicate a handle/pointer to the port containing the phy. | ||
420 | */ | ||
421 | struct scic_sds_port *scic_sds_phy_get_port( | ||
422 | struct scic_sds_phy *this_phy) | ||
423 | { | ||
424 | if (scic_sds_port_get_index(this_phy->owning_port) == SCIC_SDS_DUMMY_PORT) | ||
425 | return SCI_INVALID_HANDLE; | ||
426 | |||
427 | return this_phy->owning_port; | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * This method will assign a port to the phy object. | ||
432 | * @out]: this_phy This parameter specifies the phy for which to assign a port | ||
433 | * object. | ||
434 | * | ||
435 | * | ||
436 | */ | ||
437 | void scic_sds_phy_set_port( | ||
438 | struct scic_sds_phy *this_phy, | ||
439 | struct scic_sds_port *the_port) | ||
440 | { | ||
441 | this_phy->owning_port = the_port; | ||
442 | |||
443 | if (this_phy->bcn_received_while_port_unassigned) { | ||
444 | this_phy->bcn_received_while_port_unassigned = false; | ||
445 | scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | /** | ||
450 | * This method will initialize the constructed phy | ||
451 | * @sci_phy: | ||
452 | * @link_layer_registers: | ||
453 | * | ||
454 | * enum sci_status | ||
455 | */ | ||
456 | enum sci_status scic_sds_phy_initialize( | ||
457 | struct scic_sds_phy *sci_phy, | ||
458 | struct scu_link_layer_registers *link_layer_registers) | ||
459 | { | ||
460 | /* Create the SIGNATURE FIS Timeout timer for this phy */ | ||
461 | sci_phy->sata_timeout_timer = scic_cb_timer_create( | ||
462 | scic_sds_phy_get_controller(sci_phy), | ||
463 | scic_sds_phy_sata_timeout, | ||
464 | sci_phy | ||
465 | ); | ||
466 | |||
467 | /* Perofrm the initialization of the PE hardware */ | ||
468 | scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers); | ||
469 | |||
470 | /* | ||
471 | * There is nothing that needs to be done in this state just | ||
472 | * transition to the stopped state. */ | ||
473 | sci_base_state_machine_change_state( | ||
474 | scic_sds_phy_get_base_state_machine(sci_phy), | ||
475 | SCI_BASE_PHY_STATE_STOPPED | ||
476 | ); | ||
477 | |||
478 | return SCI_SUCCESS; | ||
479 | } | ||
480 | |||
481 | |||
482 | /** | ||
483 | * | ||
484 | * @this_phy: The phy object to be suspended. | ||
485 | * | ||
486 | * This function will perform the register reads/writes to suspend the SCU | ||
487 | * hardware protocol engine. none | ||
488 | */ | ||
489 | void scic_sds_phy_suspend( | ||
490 | struct scic_sds_phy *this_phy) | ||
491 | { | ||
492 | u32 scu_sas_pcfg_value; | ||
493 | |||
494 | scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); | ||
495 | |||
496 | scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); | ||
497 | |||
498 | SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); | ||
499 | } | ||
500 | |||
501 | /** | ||
502 | * | ||
503 | * @this_phy: The phy object to resume. | ||
504 | * | ||
505 | * This function will perform the register reads/writes required to resume the | ||
506 | * SCU hardware protocol engine. none | ||
507 | */ | ||
508 | void scic_sds_phy_resume( | ||
509 | struct scic_sds_phy *this_phy) | ||
510 | { | ||
511 | u32 scu_sas_pcfg_value; | ||
512 | |||
513 | scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); | ||
514 | |||
515 | scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE); | ||
516 | |||
517 | SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); | ||
518 | } | ||
519 | |||
520 | /** | ||
521 | * This method returns the local sas address assigned to this phy. | ||
522 | * @this_phy: This parameter specifies the phy for which to retrieve the local | ||
523 | * SAS address. | ||
524 | * @sas_address: This parameter specifies the location into which to copy the | ||
525 | * local SAS address. | ||
526 | * | ||
527 | */ | ||
528 | void scic_sds_phy_get_sas_address( | ||
529 | struct scic_sds_phy *this_phy, | ||
530 | struct sci_sas_address *sas_address) | ||
531 | { | ||
532 | sas_address->high = SCU_SAS_TISSAH_READ(this_phy); | ||
533 | sas_address->low = SCU_SAS_TISSAL_READ(this_phy); | ||
534 | } | ||
535 | |||
536 | /** | ||
537 | * This method returns the remote end-point (i.e. attached) sas address | ||
538 | * assigned to this phy. | ||
539 | * @this_phy: This parameter specifies the phy for which to retrieve the remote | ||
540 | * end-point SAS address. | ||
541 | * @sas_address: This parameter specifies the location into which to copy the | ||
542 | * remote end-point SAS address. | ||
543 | * | ||
544 | */ | ||
545 | void scic_sds_phy_get_attached_sas_address( | ||
546 | struct scic_sds_phy *this_phy, | ||
547 | struct sci_sas_address *sas_address) | ||
548 | { | ||
549 | sas_address->high | ||
550 | = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.high; | ||
551 | sas_address->low | ||
552 | = this_phy->phy_type.sas.identify_address_frame_buffer.sas_address.low; | ||
553 | } | ||
554 | |||
555 | /** | ||
556 | * This method returns the supported protocols assigned to this phy | ||
557 | * @this_phy: | ||
558 | * | ||
559 | * | ||
560 | */ | ||
561 | void scic_sds_phy_get_protocols( | ||
562 | struct scic_sds_phy *this_phy, | ||
563 | struct sci_sas_identify_address_frame_protocols *protocols) | ||
564 | { | ||
565 | protocols->u.all = (u16)(SCU_SAS_TIID_READ(this_phy) & 0x0000FFFF); | ||
566 | } | ||
567 | |||
568 | /** | ||
569 | * | ||
570 | * @this_phy: The parameter is the phy object for which the attached phy | ||
571 | * protcols are to be returned. | ||
572 | * | ||
573 | * This method returns the supported protocols for the attached phy. If this | ||
574 | * is a SAS phy the protocols are returned from the identify address frame. If | ||
575 | * this is a SATA phy then protocols are made up and the target phy is an STP | ||
576 | * target phy. The caller will get the entire set of bits for the protocol | ||
577 | * value. | ||
578 | */ | ||
579 | void scic_sds_phy_get_attached_phy_protocols( | ||
580 | struct scic_sds_phy *this_phy, | ||
581 | struct sci_sas_identify_address_frame_protocols *protocols) | ||
582 | { | ||
583 | protocols->u.all = 0; | ||
584 | |||
585 | if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { | ||
586 | protocols->u.all = | ||
587 | this_phy->phy_type.sas.identify_address_frame_buffer.protocols.u.all; | ||
588 | } else if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { | ||
589 | protocols->u.bits.stp_target = 1; | ||
590 | } | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * ***************************************************************************** | ||
595 | * * SCIC SDS PHY Handler Redirects | ||
596 | * ***************************************************************************** */ | ||
597 | |||
598 | /** | ||
599 | * This method will attempt to start the phy object. This request is only valid | ||
600 | * when the phy is in the stopped state | ||
601 | * @this_phy: | ||
602 | * | ||
603 | * enum sci_status | ||
604 | */ | ||
605 | enum sci_status scic_sds_phy_start( | ||
606 | struct scic_sds_phy *this_phy) | ||
607 | { | ||
608 | return this_phy->state_handlers->parent.start_handler(&this_phy->parent); | ||
609 | } | ||
610 | |||
611 | /** | ||
612 | * This method will attempt to stop the phy object. | ||
613 | * @this_phy: | ||
614 | * | ||
615 | * enum sci_status SCI_SUCCESS if the phy is going to stop SCI_INVALID_STATE if the | ||
616 | * phy is not in a valid state to stop | ||
617 | */ | ||
618 | enum sci_status scic_sds_phy_stop( | ||
619 | struct scic_sds_phy *this_phy) | ||
620 | { | ||
621 | return this_phy->state_handlers->parent.stop_handler(&this_phy->parent); | ||
622 | } | ||
623 | |||
624 | /** | ||
625 | * This method will attempt to reset the phy. This request is only valid when | ||
626 | * the phy is in an ready state | ||
627 | * @this_phy: | ||
628 | * | ||
629 | * enum sci_status | ||
630 | */ | ||
631 | enum sci_status scic_sds_phy_reset( | ||
632 | struct scic_sds_phy *this_phy) | ||
633 | { | ||
634 | return this_phy->state_handlers->parent.reset_handler( | ||
635 | &this_phy->parent | ||
636 | ); | ||
637 | } | ||
638 | |||
639 | /** | ||
640 | * This method will process the event code received. | ||
641 | * @this_phy: | ||
642 | * @event_code: | ||
643 | * | ||
644 | * enum sci_status | ||
645 | */ | ||
646 | enum sci_status scic_sds_phy_event_handler( | ||
647 | struct scic_sds_phy *this_phy, | ||
648 | u32 event_code) | ||
649 | { | ||
650 | return this_phy->state_handlers->event_handler(this_phy, event_code); | ||
651 | } | ||
652 | |||
653 | /** | ||
654 | * This method will process the frame index received. | ||
655 | * @this_phy: | ||
656 | * @frame_index: | ||
657 | * | ||
658 | * enum sci_status | ||
659 | */ | ||
660 | enum sci_status scic_sds_phy_frame_handler( | ||
661 | struct scic_sds_phy *this_phy, | ||
662 | u32 frame_index) | ||
663 | { | ||
664 | return this_phy->state_handlers->frame_handler(this_phy, frame_index); | ||
665 | } | ||
666 | |||
667 | /** | ||
668 | * This method will give the phy permission to consume power | ||
669 | * @this_phy: | ||
670 | * | ||
671 | * enum sci_status | ||
672 | */ | ||
673 | enum sci_status scic_sds_phy_consume_power_handler( | ||
674 | struct scic_sds_phy *this_phy) | ||
675 | { | ||
676 | return this_phy->state_handlers->consume_power_handler(this_phy); | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * ***************************************************************************** | ||
681 | * * SCIC PHY Public Methods | ||
682 | * ***************************************************************************** */ | ||
683 | |||
684 | |||
685 | enum sci_status scic_sas_phy_get_properties( | ||
686 | struct scic_sds_phy *sci_phy, | ||
687 | struct scic_sas_phy_properties *properties) | ||
688 | { | ||
689 | if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { | ||
690 | memcpy( | ||
691 | &properties->received_iaf, | ||
692 | &sci_phy->phy_type.sas.identify_address_frame_buffer, | ||
693 | sizeof(struct sci_sas_identify_address_frame) | ||
694 | ); | ||
695 | |||
696 | properties->received_capabilities.u.all | ||
697 | = SCU_SAS_RECPHYCAP_READ(sci_phy); | ||
698 | |||
699 | return SCI_SUCCESS; | ||
700 | } | ||
701 | |||
702 | return SCI_FAILURE; | ||
703 | } | ||
704 | |||
705 | |||
706 | enum sci_status scic_sata_phy_get_properties( | ||
707 | struct scic_sds_phy *sci_phy, | ||
708 | struct scic_sata_phy_properties *properties) | ||
709 | { | ||
710 | if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) { | ||
711 | memcpy( | ||
712 | &properties->signature_fis, | ||
713 | &sci_phy->phy_type.sata.signature_fis_buffer, | ||
714 | sizeof(struct sata_fis_reg_d2h) | ||
715 | ); | ||
716 | |||
717 | /* / @todo add support for port selectors. */ | ||
718 | properties->is_port_selector_present = false; | ||
719 | |||
720 | return SCI_SUCCESS; | ||
721 | } | ||
722 | |||
723 | return SCI_FAILURE; | ||
724 | } | ||
725 | |||
726 | /* | ||
727 | * ***************************************************************************** | ||
728 | * * SCIC SDS PHY HELPER FUNCTIONS | ||
729 | * ***************************************************************************** */ | ||
730 | |||
731 | |||
732 | /** | ||
733 | * | ||
734 | * @this_phy: The phy object that received SAS PHY DETECTED. | ||
735 | * | ||
736 | * This method continues the link training for the phy as if it were a SAS PHY | ||
737 | * instead of a SATA PHY. This is done because the completion queue had a SAS | ||
738 | * PHY DETECTED event when the state machine was expecting a SATA PHY event. | ||
739 | * none | ||
740 | */ | ||
741 | static void scic_sds_phy_start_sas_link_training( | ||
742 | struct scic_sds_phy *this_phy) | ||
743 | { | ||
744 | u32 phy_control; | ||
745 | |||
746 | phy_control = SCU_SAS_PCFG_READ(this_phy); | ||
747 | phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD); | ||
748 | SCU_SAS_PCFG_WRITE(this_phy, phy_control); | ||
749 | |||
750 | sci_base_state_machine_change_state( | ||
751 | &this_phy->starting_substate_machine, | ||
752 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN | ||
753 | ); | ||
754 | |||
755 | this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS; | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * | ||
760 | * @this_phy: The phy object that received a SATA SPINUP HOLD event | ||
761 | * | ||
762 | * This method continues the link training for the phy as if it were a SATA PHY | ||
763 | * instead of a SAS PHY. This is done because the completion queue had a SATA | ||
764 | * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none | ||
765 | */ | ||
766 | static void scic_sds_phy_start_sata_link_training( | ||
767 | struct scic_sds_phy *this_phy) | ||
768 | { | ||
769 | sci_base_state_machine_change_state( | ||
770 | &this_phy->starting_substate_machine, | ||
771 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER | ||
772 | ); | ||
773 | |||
774 | this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; | ||
775 | } | ||
776 | |||
777 | /** | ||
778 | * This method performs processing common to all protocols upon completion of | ||
779 | * link training. | ||
780 | * @this_phy: This parameter specifies the phy object for which link training | ||
781 | * has completed. | ||
782 | * @max_link_rate: This parameter specifies the maximum link rate to be | ||
783 | * associated with this phy. | ||
784 | * @next_state: This parameter specifies the next state for the phy's starting | ||
785 | * sub-state machine. | ||
786 | * | ||
787 | */ | ||
788 | static void scic_sds_phy_complete_link_training( | ||
789 | struct scic_sds_phy *this_phy, | ||
790 | enum sci_sas_link_rate max_link_rate, | ||
791 | u32 next_state) | ||
792 | { | ||
793 | this_phy->max_negotiated_speed = max_link_rate; | ||
794 | |||
795 | sci_base_state_machine_change_state( | ||
796 | scic_sds_phy_get_starting_substate_machine(this_phy), next_state | ||
797 | ); | ||
798 | } | ||
799 | |||
800 | /** | ||
801 | * | ||
802 | * @this_phy: The struct scic_sds_phy object to restart. | ||
803 | * | ||
804 | * This method restarts the struct scic_sds_phy objects base state machine in the | ||
805 | * starting state from any starting substate. none | ||
806 | */ | ||
807 | static void scic_sds_phy_restart_starting_state( | ||
808 | struct scic_sds_phy *this_phy) | ||
809 | { | ||
810 | /* Stop the current substate machine */ | ||
811 | sci_base_state_machine_stop( | ||
812 | scic_sds_phy_get_starting_substate_machine(this_phy) | ||
813 | ); | ||
814 | |||
815 | /* Re-enter the base state machine starting state */ | ||
816 | sci_base_state_machine_change_state( | ||
817 | scic_sds_phy_get_base_state_machine(this_phy), | ||
818 | SCI_BASE_PHY_STATE_STARTING | ||
819 | ); | ||
820 | } | ||
821 | |||
822 | /* | ||
823 | * ***************************************************************************** | ||
824 | * * SCIC SDS PHY EVENT_HANDLERS | ||
825 | * ***************************************************************************** */ | ||
826 | |||
827 | /** | ||
828 | * | ||
829 | * @phy: This struct scic_sds_phy object which has received an event. | ||
830 | * @event_code: This is the event code which the phy object is to decode. | ||
831 | * | ||
832 | * This method is called when an event notification is received for the phy | ||
833 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - | ||
834 | * decode the event - sas phy detected causes a state transition to the wait | ||
835 | * for speed event notification. - any other events log a warning message and | ||
836 | * set a failure status enum sci_status SCI_SUCCESS on any valid event notification | ||
837 | * SCI_FAILURE on any unexpected event notifation | ||
838 | */ | ||
839 | static enum sci_status scic_sds_phy_starting_substate_await_ossp_event_handler( | ||
840 | struct scic_sds_phy *this_phy, | ||
841 | u32 event_code) | ||
842 | { | ||
843 | u32 result = SCI_SUCCESS; | ||
844 | |||
845 | switch (scu_get_event_code(event_code)) { | ||
846 | case SCU_EVENT_SAS_PHY_DETECTED: | ||
847 | scic_sds_phy_start_sas_link_training(this_phy); | ||
848 | this_phy->is_in_link_training = true; | ||
849 | break; | ||
850 | |||
851 | case SCU_EVENT_SATA_SPINUP_HOLD: | ||
852 | scic_sds_phy_start_sata_link_training(this_phy); | ||
853 | this_phy->is_in_link_training = true; | ||
854 | break; | ||
855 | |||
856 | default: | ||
857 | dev_warn(sciphy_to_dev(this_phy), | ||
858 | "%s: PHY starting substate machine received " | ||
859 | "unexpected event_code %x\n", | ||
860 | __func__, | ||
861 | event_code); | ||
862 | |||
863 | result = SCI_FAILURE; | ||
864 | break; | ||
865 | } | ||
866 | |||
867 | return result; | ||
868 | } | ||
869 | |||
870 | /** | ||
871 | * | ||
872 | * @phy: This struct scic_sds_phy object which has received an event. | ||
873 | * @event_code: This is the event code which the phy object is to decode. | ||
874 | * | ||
875 | * This method is called when an event notification is received for the phy | ||
876 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - | ||
877 | * decode the event - sas phy detected returns us back to this state. - speed | ||
878 | * event detected causes a state transition to the wait for iaf. - identify | ||
879 | * timeout is an un-expected event and the state machine is restarted. - link | ||
880 | * failure events restart the starting state machine - any other events log a | ||
881 | * warning message and set a failure status enum sci_status SCI_SUCCESS on any valid | ||
882 | * event notification SCI_FAILURE on any unexpected event notifation | ||
883 | */ | ||
884 | static enum sci_status scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler( | ||
885 | struct scic_sds_phy *this_phy, | ||
886 | u32 event_code) | ||
887 | { | ||
888 | u32 result = SCI_SUCCESS; | ||
889 | |||
890 | switch (scu_get_event_code(event_code)) { | ||
891 | case SCU_EVENT_SAS_PHY_DETECTED: | ||
892 | /* | ||
893 | * Why is this being reported again by the controller? | ||
894 | * We would re-enter this state so just stay here */ | ||
895 | break; | ||
896 | |||
897 | case SCU_EVENT_SAS_15: | ||
898 | case SCU_EVENT_SAS_15_SSC: | ||
899 | scic_sds_phy_complete_link_training( | ||
900 | this_phy, SCI_SAS_150_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF | ||
901 | ); | ||
902 | break; | ||
903 | |||
904 | case SCU_EVENT_SAS_30: | ||
905 | case SCU_EVENT_SAS_30_SSC: | ||
906 | scic_sds_phy_complete_link_training( | ||
907 | this_phy, SCI_SAS_300_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF | ||
908 | ); | ||
909 | break; | ||
910 | |||
911 | case SCU_EVENT_SAS_60: | ||
912 | case SCU_EVENT_SAS_60_SSC: | ||
913 | scic_sds_phy_complete_link_training( | ||
914 | this_phy, SCI_SAS_600_GB, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF | ||
915 | ); | ||
916 | break; | ||
917 | |||
918 | case SCU_EVENT_SATA_SPINUP_HOLD: | ||
919 | /* | ||
920 | * We were doing SAS PHY link training and received a SATA PHY event | ||
921 | * continue OOB/SN as if this were a SATA PHY */ | ||
922 | scic_sds_phy_start_sata_link_training(this_phy); | ||
923 | break; | ||
924 | |||
925 | case SCU_EVENT_LINK_FAILURE: | ||
926 | /* Link failure change state back to the starting state */ | ||
927 | scic_sds_phy_restart_starting_state(this_phy); | ||
928 | break; | ||
929 | |||
930 | default: | ||
931 | dev_warn(sciphy_to_dev(this_phy), | ||
932 | "%s: PHY starting substate machine received " | ||
933 | "unexpected event_code %x\n", | ||
934 | __func__, | ||
935 | event_code); | ||
936 | |||
937 | result = SCI_FAILURE; | ||
938 | break; | ||
939 | } | ||
940 | |||
941 | return result; | ||
942 | } | ||
943 | |||
944 | /** | ||
945 | * | ||
946 | * @phy: This struct scic_sds_phy object which has received an event. | ||
947 | * @event_code: This is the event code which the phy object is to decode. | ||
948 | * | ||
949 | * This method is called when an event notification is received for the phy | ||
950 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - | ||
951 | * decode the event - sas phy detected event backs up the state machine to the | ||
952 | * await speed notification. - identify timeout is an un-expected event and the | ||
953 | * state machine is restarted. - link failure events restart the starting state | ||
954 | * machine - any other events log a warning message and set a failure status | ||
955 | * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any | ||
956 | * unexpected event notifation | ||
957 | */ | ||
958 | static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_event_handler( | ||
959 | struct scic_sds_phy *this_phy, | ||
960 | u32 event_code) | ||
961 | { | ||
962 | u32 result = SCI_SUCCESS; | ||
963 | |||
964 | switch (scu_get_event_code(event_code)) { | ||
965 | case SCU_EVENT_SAS_PHY_DETECTED: | ||
966 | /* Backup the state machine */ | ||
967 | scic_sds_phy_start_sas_link_training(this_phy); | ||
968 | break; | ||
969 | |||
970 | case SCU_EVENT_SATA_SPINUP_HOLD: | ||
971 | /* | ||
972 | * We were doing SAS PHY link training and received a SATA PHY event | ||
973 | * continue OOB/SN as if this were a SATA PHY */ | ||
974 | scic_sds_phy_start_sata_link_training(this_phy); | ||
975 | break; | ||
976 | |||
977 | case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT: | ||
978 | case SCU_EVENT_LINK_FAILURE: | ||
979 | case SCU_EVENT_HARD_RESET_RECEIVED: | ||
980 | /* Start the oob/sn state machine over again */ | ||
981 | scic_sds_phy_restart_starting_state(this_phy); | ||
982 | break; | ||
983 | |||
984 | default: | ||
985 | dev_warn(sciphy_to_dev(this_phy), | ||
986 | "%s: PHY starting substate machine received " | ||
987 | "unexpected event_code %x\n", | ||
988 | __func__, | ||
989 | event_code); | ||
990 | |||
991 | result = SCI_FAILURE; | ||
992 | break; | ||
993 | } | ||
994 | |||
995 | return result; | ||
996 | } | ||
997 | |||
998 | /** | ||
999 | * | ||
1000 | * @phy: This struct scic_sds_phy object which has received an event. | ||
1001 | * @event_code: This is the event code which the phy object is to decode. | ||
1002 | * | ||
1003 | * This method is called when an event notification is received for the phy | ||
1004 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_POWER. - | ||
1005 | * decode the event - link failure events restart the starting state machine - | ||
1006 | * any other events log a warning message and set a failure status enum sci_status | ||
1007 | * SCI_SUCCESS on a link failure event SCI_FAILURE on any unexpected event | ||
1008 | * notifation | ||
1009 | */ | ||
1010 | static enum sci_status scic_sds_phy_starting_substate_await_sas_power_event_handler( | ||
1011 | struct scic_sds_phy *this_phy, | ||
1012 | u32 event_code) | ||
1013 | { | ||
1014 | u32 result = SCI_SUCCESS; | ||
1015 | |||
1016 | switch (scu_get_event_code(event_code)) { | ||
1017 | case SCU_EVENT_LINK_FAILURE: | ||
1018 | /* Link failure change state back to the starting state */ | ||
1019 | scic_sds_phy_restart_starting_state(this_phy); | ||
1020 | break; | ||
1021 | |||
1022 | default: | ||
1023 | dev_warn(sciphy_to_dev(this_phy), | ||
1024 | "%s: PHY starting substate machine received unexpected " | ||
1025 | "event_code %x\n", | ||
1026 | __func__, | ||
1027 | event_code); | ||
1028 | |||
1029 | result = SCI_FAILURE; | ||
1030 | break; | ||
1031 | } | ||
1032 | |||
1033 | return result; | ||
1034 | } | ||
1035 | |||
1036 | /** | ||
1037 | * | ||
1038 | * @phy: This struct scic_sds_phy object which has received an event. | ||
1039 | * @event_code: This is the event code which the phy object is to decode. | ||
1040 | * | ||
1041 | * This method is called when an event notification is received for the phy | ||
1042 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - | ||
1043 | * decode the event - link failure events restart the starting state machine - | ||
1044 | * sata spinup hold events are ignored since they are expected - any other | ||
1045 | * events log a warning message and set a failure status enum sci_status SCI_SUCCESS | ||
1046 | * on a link failure event SCI_FAILURE on any unexpected event notifation | ||
1047 | */ | ||
1048 | static enum sci_status scic_sds_phy_starting_substate_await_sata_power_event_handler( | ||
1049 | struct scic_sds_phy *this_phy, | ||
1050 | u32 event_code) | ||
1051 | { | ||
1052 | u32 result = SCI_SUCCESS; | ||
1053 | |||
1054 | switch (scu_get_event_code(event_code)) { | ||
1055 | case SCU_EVENT_LINK_FAILURE: | ||
1056 | /* Link failure change state back to the starting state */ | ||
1057 | scic_sds_phy_restart_starting_state(this_phy); | ||
1058 | break; | ||
1059 | |||
1060 | case SCU_EVENT_SATA_SPINUP_HOLD: | ||
1061 | /* These events are received every 10ms and are expected while in this state */ | ||
1062 | break; | ||
1063 | |||
1064 | case SCU_EVENT_SAS_PHY_DETECTED: | ||
1065 | /* | ||
1066 | * There has been a change in the phy type before OOB/SN for the | ||
1067 | * SATA finished start down the SAS link traning path. */ | ||
1068 | scic_sds_phy_start_sas_link_training(this_phy); | ||
1069 | break; | ||
1070 | |||
1071 | default: | ||
1072 | dev_warn(sciphy_to_dev(this_phy), | ||
1073 | "%s: PHY starting substate machine received " | ||
1074 | "unexpected event_code %x\n", | ||
1075 | __func__, | ||
1076 | event_code); | ||
1077 | |||
1078 | result = SCI_FAILURE; | ||
1079 | break; | ||
1080 | } | ||
1081 | |||
1082 | return result; | ||
1083 | } | ||
1084 | |||
1085 | /** | ||
1086 | * | ||
1087 | * @phy: This struct scic_sds_phy object which has received an event. | ||
1088 | * @event_code: This is the event code which the phy object is to decode. | ||
1089 | * | ||
1090 | * This method is called when an event notification is received for the phy | ||
1091 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - | ||
1092 | * decode the event - link failure events restart the starting state machine - | ||
1093 | * sata spinup hold events are ignored since they are expected - sata phy | ||
1094 | * detected event change to the wait speed event - any other events log a | ||
1095 | * warning message and set a failure status enum sci_status SCI_SUCCESS on a link | ||
1096 | * failure event SCI_FAILURE on any unexpected event notifation | ||
1097 | */ | ||
1098 | static enum sci_status scic_sds_phy_starting_substate_await_sata_phy_event_handler( | ||
1099 | struct scic_sds_phy *this_phy, | ||
1100 | u32 event_code) | ||
1101 | { | ||
1102 | u32 result = SCI_SUCCESS; | ||
1103 | |||
1104 | switch (scu_get_event_code(event_code)) { | ||
1105 | case SCU_EVENT_LINK_FAILURE: | ||
1106 | /* Link failure change state back to the starting state */ | ||
1107 | scic_sds_phy_restart_starting_state(this_phy); | ||
1108 | break; | ||
1109 | |||
1110 | case SCU_EVENT_SATA_SPINUP_HOLD: | ||
1111 | /* | ||
1112 | * These events might be received since we dont know how many may be in | ||
1113 | * the completion queue while waiting for power */ | ||
1114 | break; | ||
1115 | |||
1116 | case SCU_EVENT_SATA_PHY_DETECTED: | ||
1117 | this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA; | ||
1118 | |||
1119 | /* We have received the SATA PHY notification change state */ | ||
1120 | sci_base_state_machine_change_state( | ||
1121 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1122 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN | ||
1123 | ); | ||
1124 | break; | ||
1125 | |||
1126 | case SCU_EVENT_SAS_PHY_DETECTED: | ||
1127 | /* | ||
1128 | * There has been a change in the phy type before OOB/SN for the | ||
1129 | * SATA finished start down the SAS link traning path. */ | ||
1130 | scic_sds_phy_start_sas_link_training(this_phy); | ||
1131 | break; | ||
1132 | |||
1133 | default: | ||
1134 | dev_warn(sciphy_to_dev(this_phy), | ||
1135 | "%s: PHY starting substate machine received " | ||
1136 | "unexpected event_code %x\n", | ||
1137 | __func__, | ||
1138 | event_code); | ||
1139 | |||
1140 | result = SCI_FAILURE; | ||
1141 | break; | ||
1142 | } | ||
1143 | |||
1144 | return result; | ||
1145 | } | ||
1146 | |||
1147 | /** | ||
1148 | * | ||
1149 | * @phy: This struct scic_sds_phy object which has received an event. | ||
1150 | * @event_code: This is the event code which the phy object is to decode. | ||
1151 | * | ||
1152 | * This method is called when an event notification is received for the phy | ||
1153 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. | ||
1154 | * - decode the event - sata phy detected returns us back to this state. - | ||
1155 | * speed event detected causes a state transition to the wait for signature. - | ||
1156 | * link failure events restart the starting state machine - any other events | ||
1157 | * log a warning message and set a failure status enum sci_status SCI_SUCCESS on any | ||
1158 | * valid event notification SCI_FAILURE on any unexpected event notifation | ||
1159 | */ | ||
1160 | static enum sci_status scic_sds_phy_starting_substate_await_sata_speed_event_handler( | ||
1161 | struct scic_sds_phy *this_phy, | ||
1162 | u32 event_code) | ||
1163 | { | ||
1164 | u32 result = SCI_SUCCESS; | ||
1165 | |||
1166 | switch (scu_get_event_code(event_code)) { | ||
1167 | case SCU_EVENT_SATA_PHY_DETECTED: | ||
1168 | /* | ||
1169 | * The hardware reports multiple SATA PHY detected events | ||
1170 | * ignore the extras */ | ||
1171 | break; | ||
1172 | |||
1173 | case SCU_EVENT_SATA_15: | ||
1174 | case SCU_EVENT_SATA_15_SSC: | ||
1175 | scic_sds_phy_complete_link_training( | ||
1176 | this_phy, | ||
1177 | SCI_SAS_150_GB, | ||
1178 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF | ||
1179 | ); | ||
1180 | break; | ||
1181 | |||
1182 | case SCU_EVENT_SATA_30: | ||
1183 | case SCU_EVENT_SATA_30_SSC: | ||
1184 | scic_sds_phy_complete_link_training( | ||
1185 | this_phy, | ||
1186 | SCI_SAS_300_GB, | ||
1187 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF | ||
1188 | ); | ||
1189 | break; | ||
1190 | |||
1191 | case SCU_EVENT_SATA_60: | ||
1192 | case SCU_EVENT_SATA_60_SSC: | ||
1193 | scic_sds_phy_complete_link_training( | ||
1194 | this_phy, | ||
1195 | SCI_SAS_600_GB, | ||
1196 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF | ||
1197 | ); | ||
1198 | break; | ||
1199 | |||
1200 | case SCU_EVENT_LINK_FAILURE: | ||
1201 | /* Link failure change state back to the starting state */ | ||
1202 | scic_sds_phy_restart_starting_state(this_phy); | ||
1203 | break; | ||
1204 | |||
1205 | case SCU_EVENT_SAS_PHY_DETECTED: | ||
1206 | /* | ||
1207 | * There has been a change in the phy type before OOB/SN for the | ||
1208 | * SATA finished start down the SAS link traning path. */ | ||
1209 | scic_sds_phy_start_sas_link_training(this_phy); | ||
1210 | break; | ||
1211 | |||
1212 | default: | ||
1213 | dev_warn(sciphy_to_dev(this_phy), | ||
1214 | "%s: PHY starting substate machine received " | ||
1215 | "unexpected event_code %x\n", | ||
1216 | __func__, | ||
1217 | event_code); | ||
1218 | |||
1219 | result = SCI_FAILURE; | ||
1220 | break; | ||
1221 | } | ||
1222 | |||
1223 | return result; | ||
1224 | } | ||
1225 | |||
1226 | /** | ||
1227 | * | ||
1228 | * @phy: This struct scic_sds_phy object which has received an event. | ||
1229 | * @event_code: This is the event code which the phy object is to decode. | ||
1230 | * | ||
1231 | * This method is called when an event notification is received for the phy | ||
1232 | * object when in the state SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - | ||
1233 | * decode the event - sas phy detected event backs up the state machine to the | ||
1234 | * await speed notification. - identify timeout is an un-expected event and the | ||
1235 | * state machine is restarted. - link failure events restart the starting state | ||
1236 | * machine - any other events log a warning message and set a failure status | ||
1237 | * enum sci_status SCI_SUCCESS on any valid event notification SCI_FAILURE on any | ||
1238 | * unexpected event notifation | ||
1239 | */ | ||
1240 | static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_event_handler( | ||
1241 | struct scic_sds_phy *this_phy, | ||
1242 | u32 event_code) | ||
1243 | { | ||
1244 | u32 result = SCI_SUCCESS; | ||
1245 | |||
1246 | switch (scu_get_event_code(event_code)) { | ||
1247 | case SCU_EVENT_SATA_PHY_DETECTED: | ||
1248 | /* Backup the state machine */ | ||
1249 | sci_base_state_machine_change_state( | ||
1250 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1251 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN | ||
1252 | ); | ||
1253 | break; | ||
1254 | |||
1255 | case SCU_EVENT_LINK_FAILURE: | ||
1256 | /* Link failure change state back to the starting state */ | ||
1257 | scic_sds_phy_restart_starting_state(this_phy); | ||
1258 | break; | ||
1259 | |||
1260 | default: | ||
1261 | dev_warn(sciphy_to_dev(this_phy), | ||
1262 | "%s: PHY starting substate machine received " | ||
1263 | "unexpected event_code %x\n", | ||
1264 | __func__, | ||
1265 | event_code); | ||
1266 | |||
1267 | result = SCI_FAILURE; | ||
1268 | break; | ||
1269 | } | ||
1270 | |||
1271 | return result; | ||
1272 | } | ||
1273 | |||
1274 | |||
1275 | /* | ||
1276 | * ***************************************************************************** | ||
1277 | * * SCIC SDS PHY FRAME_HANDLERS | ||
1278 | * ***************************************************************************** */ | ||
1279 | |||
1280 | /** | ||
1281 | * | ||
1282 | * @phy: This is struct scic_sds_phy object which is being requested to decode the | ||
1283 | * frame data. | ||
1284 | * @frame_index: This is the index of the unsolicited frame which was received | ||
1285 | * for this phy. | ||
1286 | * | ||
1287 | * This method decodes the unsolicited frame when the struct scic_sds_phy is in the | ||
1288 | * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Get the UF Header - If the UF | ||
1289 | * is an IAF - Copy IAF data to local phy object IAF data buffer. - Change | ||
1290 | * starting substate to wait power. - else - log warning message of unexpected | ||
1291 | * unsolicted frame - release frame buffer enum sci_status SCI_SUCCESS | ||
1292 | */ | ||
1293 | static enum sci_status scic_sds_phy_starting_substate_await_iaf_uf_frame_handler( | ||
1294 | struct scic_sds_phy *this_phy, | ||
1295 | u32 frame_index) | ||
1296 | { | ||
1297 | enum sci_status result; | ||
1298 | u32 *frame_words; | ||
1299 | struct sci_sas_identify_address_frame *identify_frame; | ||
1300 | |||
1301 | result = scic_sds_unsolicited_frame_control_get_header( | ||
1302 | &(scic_sds_phy_get_controller(this_phy)->uf_control), | ||
1303 | frame_index, | ||
1304 | (void **)&frame_words); | ||
1305 | |||
1306 | if (result != SCI_SUCCESS) { | ||
1307 | return result; | ||
1308 | } | ||
1309 | |||
1310 | frame_words[0] = SCIC_SWAP_DWORD(frame_words[0]); | ||
1311 | identify_frame = (struct sci_sas_identify_address_frame *)frame_words; | ||
1312 | |||
1313 | if (identify_frame->address_frame_type == 0) { | ||
1314 | /* | ||
1315 | * Byte swap the rest of the frame so we can make | ||
1316 | * a copy of the buffer */ | ||
1317 | frame_words[1] = SCIC_SWAP_DWORD(frame_words[1]); | ||
1318 | frame_words[2] = SCIC_SWAP_DWORD(frame_words[2]); | ||
1319 | frame_words[3] = SCIC_SWAP_DWORD(frame_words[3]); | ||
1320 | frame_words[4] = SCIC_SWAP_DWORD(frame_words[4]); | ||
1321 | frame_words[5] = SCIC_SWAP_DWORD(frame_words[5]); | ||
1322 | |||
1323 | memcpy( | ||
1324 | &this_phy->phy_type.sas.identify_address_frame_buffer, | ||
1325 | identify_frame, | ||
1326 | sizeof(struct sci_sas_identify_address_frame) | ||
1327 | ); | ||
1328 | |||
1329 | if (identify_frame->protocols.u.bits.smp_target) { | ||
1330 | /* | ||
1331 | * We got the IAF for an expander PHY go to the final state since | ||
1332 | * there are no power requirements for expander phys. */ | ||
1333 | sci_base_state_machine_change_state( | ||
1334 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1335 | SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL | ||
1336 | ); | ||
1337 | } else { | ||
1338 | /* We got the IAF we can now go to the await spinup semaphore state */ | ||
1339 | sci_base_state_machine_change_state( | ||
1340 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1341 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER | ||
1342 | ); | ||
1343 | } | ||
1344 | |||
1345 | result = SCI_SUCCESS; | ||
1346 | } else | ||
1347 | dev_warn(sciphy_to_dev(this_phy), | ||
1348 | "%s: PHY starting substate machine received " | ||
1349 | "unexpected frame id %x\n", | ||
1350 | __func__, | ||
1351 | frame_index); | ||
1352 | |||
1353 | /* Regardless of the result release this frame since we are done with it */ | ||
1354 | scic_sds_controller_release_frame( | ||
1355 | scic_sds_phy_get_controller(this_phy), frame_index | ||
1356 | ); | ||
1357 | |||
1358 | return result; | ||
1359 | } | ||
1360 | |||
1361 | /** | ||
1362 | * | ||
1363 | * @phy: This is struct scic_sds_phy object which is being requested to decode the | ||
1364 | * frame data. | ||
1365 | * @frame_index: This is the index of the unsolicited frame which was received | ||
1366 | * for this phy. | ||
1367 | * | ||
1368 | * This method decodes the unsolicited frame when the struct scic_sds_phy is in the | ||
1369 | * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Get the UF Header - If | ||
1370 | * the UF is an SIGNATURE FIS - Copy IAF data to local phy object SIGNATURE FIS | ||
1371 | * data buffer. - else - log warning message of unexpected unsolicted frame - | ||
1372 | * release frame buffer enum sci_status SCI_SUCCESS Must decode the SIGNATURE FIS | ||
1373 | * data | ||
1374 | */ | ||
1375 | static enum sci_status scic_sds_phy_starting_substate_await_sig_fis_frame_handler( | ||
1376 | struct scic_sds_phy *this_phy, | ||
1377 | u32 frame_index) | ||
1378 | { | ||
1379 | enum sci_status result; | ||
1380 | u32 *frame_words; | ||
1381 | struct sata_fis_header *fis_frame_header; | ||
1382 | u32 *fis_frame_data; | ||
1383 | |||
1384 | result = scic_sds_unsolicited_frame_control_get_header( | ||
1385 | &(scic_sds_phy_get_controller(this_phy)->uf_control), | ||
1386 | frame_index, | ||
1387 | (void **)&frame_words); | ||
1388 | |||
1389 | if (result != SCI_SUCCESS) { | ||
1390 | return result; | ||
1391 | } | ||
1392 | |||
1393 | fis_frame_header = (struct sata_fis_header *)frame_words; | ||
1394 | |||
1395 | if ( | ||
1396 | (fis_frame_header->fis_type == SATA_FIS_TYPE_REGD2H) | ||
1397 | && !(fis_frame_header->status & ATA_STATUS_REG_BSY_BIT) | ||
1398 | ) { | ||
1399 | scic_sds_unsolicited_frame_control_get_buffer( | ||
1400 | &(scic_sds_phy_get_controller(this_phy)->uf_control), | ||
1401 | frame_index, | ||
1402 | (void **)&fis_frame_data | ||
1403 | ); | ||
1404 | |||
1405 | scic_sds_controller_copy_sata_response( | ||
1406 | &this_phy->phy_type.sata.signature_fis_buffer, | ||
1407 | frame_words, | ||
1408 | fis_frame_data | ||
1409 | ); | ||
1410 | |||
1411 | /* We got the IAF we can now go to the await spinup semaphore state */ | ||
1412 | sci_base_state_machine_change_state( | ||
1413 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1414 | SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL | ||
1415 | ); | ||
1416 | |||
1417 | result = SCI_SUCCESS; | ||
1418 | } else | ||
1419 | dev_warn(sciphy_to_dev(this_phy), | ||
1420 | "%s: PHY starting substate machine received " | ||
1421 | "unexpected frame id %x\n", | ||
1422 | __func__, | ||
1423 | frame_index); | ||
1424 | |||
1425 | /* Regardless of the result release this frame since we are done with it */ | ||
1426 | scic_sds_controller_release_frame( | ||
1427 | scic_sds_phy_get_controller(this_phy), frame_index | ||
1428 | ); | ||
1429 | |||
1430 | return result; | ||
1431 | } | ||
1432 | |||
1433 | /* | ||
1434 | * ***************************************************************************** | ||
1435 | * * SCIC SDS PHY POWER_HANDLERS | ||
1436 | * ***************************************************************************** */ | ||
1437 | |||
1438 | /** | ||
1439 | * | ||
1440 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
1441 | * object. | ||
1442 | * | ||
1443 | * This method is called by the struct scic_sds_controller when the phy object is | ||
1444 | * granted power. - The notify enable spinups are turned on for this phy object | ||
1445 | * - The phy state machine is transitioned to the | ||
1446 | * SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. enum sci_status SCI_SUCCESS | ||
1447 | */ | ||
1448 | static enum sci_status scic_sds_phy_starting_substate_await_sas_power_consume_power_handler( | ||
1449 | struct scic_sds_phy *this_phy) | ||
1450 | { | ||
1451 | u32 enable_spinup; | ||
1452 | |||
1453 | enable_spinup = SCU_SAS_ENSPINUP_READ(this_phy); | ||
1454 | enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE); | ||
1455 | SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup); | ||
1456 | |||
1457 | /* Change state to the final state this substate machine has run to completion */ | ||
1458 | sci_base_state_machine_change_state( | ||
1459 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1460 | SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL | ||
1461 | ); | ||
1462 | |||
1463 | return SCI_SUCCESS; | ||
1464 | } | ||
1465 | |||
1466 | /** | ||
1467 | * | ||
1468 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
1469 | * object. | ||
1470 | * | ||
1471 | * This method is called by the struct scic_sds_controller when the phy object is | ||
1472 | * granted power. - The phy state machine is transitioned to the | ||
1473 | * SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. enum sci_status SCI_SUCCESS | ||
1474 | */ | ||
1475 | static enum sci_status scic_sds_phy_starting_substate_await_sata_power_consume_power_handler( | ||
1476 | struct scic_sds_phy *this_phy) | ||
1477 | { | ||
1478 | u32 scu_sas_pcfg_value; | ||
1479 | |||
1480 | /* Release the spinup hold state and reset the OOB state machine */ | ||
1481 | scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); | ||
1482 | scu_sas_pcfg_value &= | ||
1483 | ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE)); | ||
1484 | scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET); | ||
1485 | SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); | ||
1486 | |||
1487 | /* Now restart the OOB operation */ | ||
1488 | scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); | ||
1489 | scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); | ||
1490 | SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); | ||
1491 | |||
1492 | /* Change state to the final state this substate machine has run to completion */ | ||
1493 | sci_base_state_machine_change_state( | ||
1494 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1495 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN | ||
1496 | ); | ||
1497 | |||
1498 | return SCI_SUCCESS; | ||
1499 | } | ||
1500 | |||
1501 | /* --------------------------------------------------------------------------- */ | ||
1502 | |||
1503 | struct scic_sds_phy_state_handler | ||
1504 | scic_sds_phy_starting_substate_handler_table[SCIC_SDS_PHY_STARTING_MAX_SUBSTATES] = | ||
1505 | { | ||
1506 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL */ | ||
1507 | { | ||
1508 | { | ||
1509 | scic_sds_phy_default_start_handler, | ||
1510 | scic_sds_phy_default_stop_handler, | ||
1511 | scic_sds_phy_default_reset_handler, | ||
1512 | scic_sds_phy_default_destroy_handler | ||
1513 | }, | ||
1514 | scic_sds_phy_default_frame_handler, | ||
1515 | scic_sds_phy_default_event_handler, | ||
1516 | scic_sds_phy_default_consume_power_handler | ||
1517 | }, | ||
1518 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN */ | ||
1519 | { | ||
1520 | { | ||
1521 | scic_sds_phy_default_start_handler, | ||
1522 | scic_sds_phy_default_stop_handler, | ||
1523 | scic_sds_phy_default_reset_handler, | ||
1524 | scic_sds_phy_default_destroy_handler | ||
1525 | }, | ||
1526 | scic_sds_phy_default_frame_handler, | ||
1527 | scic_sds_phy_starting_substate_await_ossp_event_handler, | ||
1528 | scic_sds_phy_default_consume_power_handler | ||
1529 | }, | ||
1530 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN */ | ||
1531 | { | ||
1532 | { | ||
1533 | scic_sds_phy_default_start_handler, | ||
1534 | scic_sds_phy_default_stop_handler, | ||
1535 | scic_sds_phy_default_reset_handler, | ||
1536 | scic_sds_phy_default_destroy_handler | ||
1537 | }, | ||
1538 | scic_sds_phy_default_frame_handler, | ||
1539 | scic_sds_phy_starting_substate_await_sas_phy_speed_event_handler, | ||
1540 | scic_sds_phy_default_consume_power_handler | ||
1541 | }, | ||
1542 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF */ | ||
1543 | { | ||
1544 | { | ||
1545 | scic_sds_phy_default_start_handler, | ||
1546 | scic_sds_phy_default_stop_handler, | ||
1547 | scic_sds_phy_default_reset_handler, | ||
1548 | scic_sds_phy_default_destroy_handler | ||
1549 | }, | ||
1550 | scic_sds_phy_starting_substate_await_iaf_uf_frame_handler, | ||
1551 | scic_sds_phy_starting_substate_await_iaf_uf_event_handler, | ||
1552 | scic_sds_phy_default_consume_power_handler | ||
1553 | }, | ||
1554 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER */ | ||
1555 | { | ||
1556 | { | ||
1557 | scic_sds_phy_default_start_handler, | ||
1558 | scic_sds_phy_default_stop_handler, | ||
1559 | scic_sds_phy_default_reset_handler, | ||
1560 | scic_sds_phy_default_destroy_handler | ||
1561 | }, | ||
1562 | scic_sds_phy_default_frame_handler, | ||
1563 | scic_sds_phy_starting_substate_await_sas_power_event_handler, | ||
1564 | scic_sds_phy_starting_substate_await_sas_power_consume_power_handler | ||
1565 | }, | ||
1566 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, */ | ||
1567 | { | ||
1568 | { | ||
1569 | scic_sds_phy_default_start_handler, | ||
1570 | scic_sds_phy_default_stop_handler, | ||
1571 | scic_sds_phy_default_reset_handler, | ||
1572 | scic_sds_phy_default_destroy_handler | ||
1573 | }, | ||
1574 | scic_sds_phy_default_frame_handler, | ||
1575 | scic_sds_phy_starting_substate_await_sata_power_event_handler, | ||
1576 | scic_sds_phy_starting_substate_await_sata_power_consume_power_handler | ||
1577 | }, | ||
1578 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, */ | ||
1579 | { | ||
1580 | { | ||
1581 | scic_sds_phy_default_start_handler, | ||
1582 | scic_sds_phy_default_stop_handler, | ||
1583 | scic_sds_phy_default_reset_handler, | ||
1584 | scic_sds_phy_default_destroy_handler | ||
1585 | }, | ||
1586 | scic_sds_phy_default_frame_handler, | ||
1587 | scic_sds_phy_starting_substate_await_sata_phy_event_handler, | ||
1588 | scic_sds_phy_default_consume_power_handler | ||
1589 | }, | ||
1590 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, */ | ||
1591 | { | ||
1592 | { | ||
1593 | scic_sds_phy_default_start_handler, | ||
1594 | scic_sds_phy_default_stop_handler, | ||
1595 | scic_sds_phy_default_reset_handler, | ||
1596 | scic_sds_phy_default_destroy_handler | ||
1597 | }, | ||
1598 | scic_sds_phy_default_frame_handler, | ||
1599 | scic_sds_phy_starting_substate_await_sata_speed_event_handler, | ||
1600 | scic_sds_phy_default_consume_power_handler | ||
1601 | }, | ||
1602 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, */ | ||
1603 | { | ||
1604 | { | ||
1605 | scic_sds_phy_default_start_handler, | ||
1606 | scic_sds_phy_default_stop_handler, | ||
1607 | scic_sds_phy_default_reset_handler, | ||
1608 | scic_sds_phy_default_destroy_handler | ||
1609 | }, | ||
1610 | scic_sds_phy_starting_substate_await_sig_fis_frame_handler, | ||
1611 | scic_sds_phy_starting_substate_await_sig_fis_event_handler, | ||
1612 | scic_sds_phy_default_consume_power_handler | ||
1613 | }, | ||
1614 | /* SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL */ | ||
1615 | { | ||
1616 | { | ||
1617 | scic_sds_phy_default_start_handler, | ||
1618 | scic_sds_phy_default_stop_handler, | ||
1619 | scic_sds_phy_default_reset_handler, | ||
1620 | scic_sds_phy_default_destroy_handler | ||
1621 | }, | ||
1622 | scic_sds_phy_default_frame_handler, | ||
1623 | scic_sds_phy_default_event_handler, | ||
1624 | scic_sds_phy_default_consume_power_handler | ||
1625 | } | ||
1626 | }; | ||
1627 | |||
1628 | /** | ||
1629 | * scic_sds_phy_set_starting_substate_handlers() - | ||
1630 | * | ||
1631 | * This macro sets the starting substate handlers by state_id | ||
1632 | */ | ||
1633 | #define scic_sds_phy_set_starting_substate_handlers(phy, state_id) \ | ||
1634 | scic_sds_phy_set_state_handlers(\ | ||
1635 | (phy), \ | ||
1636 | &scic_sds_phy_starting_substate_handler_table[(state_id)] \ | ||
1637 | ) | ||
1638 | |||
1639 | /* | ||
1640 | * **************************************************************************** | ||
1641 | * * PHY STARTING SUBSTATE METHODS | ||
1642 | * **************************************************************************** */ | ||
1643 | |||
1644 | /** | ||
1645 | * | ||
1646 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1647 | * | ||
1648 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1649 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL. - The initial state | ||
1650 | * handlers are put in place for the struct scic_sds_phy object. - The state is | ||
1651 | * changed to the wait phy type event notification. none | ||
1652 | */ | ||
1653 | static void scic_sds_phy_starting_initial_substate_enter( | ||
1654 | struct sci_base_object *object) | ||
1655 | { | ||
1656 | struct scic_sds_phy *this_phy; | ||
1657 | |||
1658 | this_phy = (struct scic_sds_phy *)object; | ||
1659 | |||
1660 | scic_sds_phy_set_starting_substate_handlers( | ||
1661 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL); | ||
1662 | |||
1663 | /* This is just an temporary state go off to the starting state */ | ||
1664 | sci_base_state_machine_change_state( | ||
1665 | scic_sds_phy_get_starting_substate_machine(this_phy), | ||
1666 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN | ||
1667 | ); | ||
1668 | } | ||
1669 | |||
1670 | /** | ||
1671 | * | ||
1672 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1673 | * | ||
1674 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1675 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_PHY_TYPE_EN. - Set the | ||
1676 | * struct scic_sds_phy object state handlers for this state. none | ||
1677 | */ | ||
1678 | static void scic_sds_phy_starting_await_ossp_en_substate_enter( | ||
1679 | struct sci_base_object *object) | ||
1680 | { | ||
1681 | struct scic_sds_phy *this_phy; | ||
1682 | |||
1683 | this_phy = (struct scic_sds_phy *)object; | ||
1684 | |||
1685 | scic_sds_phy_set_starting_substate_handlers( | ||
1686 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN | ||
1687 | ); | ||
1688 | } | ||
1689 | |||
1690 | /** | ||
1691 | * | ||
1692 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1693 | * | ||
1694 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1695 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SPEED_EN. - Set the | ||
1696 | * struct scic_sds_phy object state handlers for this state. none | ||
1697 | */ | ||
1698 | static void scic_sds_phy_starting_await_sas_speed_en_substate_enter( | ||
1699 | struct sci_base_object *object) | ||
1700 | { | ||
1701 | struct scic_sds_phy *this_phy; | ||
1702 | |||
1703 | this_phy = (struct scic_sds_phy *)object; | ||
1704 | |||
1705 | scic_sds_phy_set_starting_substate_handlers( | ||
1706 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN | ||
1707 | ); | ||
1708 | } | ||
1709 | |||
1710 | /** | ||
1711 | * | ||
1712 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1713 | * | ||
1714 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1715 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF. - Set the | ||
1716 | * struct scic_sds_phy object state handlers for this state. none | ||
1717 | */ | ||
1718 | static void scic_sds_phy_starting_await_iaf_uf_substate_enter( | ||
1719 | struct sci_base_object *object) | ||
1720 | { | ||
1721 | struct scic_sds_phy *this_phy; | ||
1722 | |||
1723 | this_phy = (struct scic_sds_phy *)object; | ||
1724 | |||
1725 | scic_sds_phy_set_starting_substate_handlers( | ||
1726 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF | ||
1727 | ); | ||
1728 | } | ||
1729 | |||
1730 | /** | ||
1731 | * | ||
1732 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1733 | * | ||
1734 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1735 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Set the | ||
1736 | * struct scic_sds_phy object state handlers for this state. - Add this phy object to | ||
1737 | * the power control queue none | ||
1738 | */ | ||
1739 | static void scic_sds_phy_starting_await_sas_power_substate_enter( | ||
1740 | struct sci_base_object *object) | ||
1741 | { | ||
1742 | struct scic_sds_phy *this_phy; | ||
1743 | |||
1744 | this_phy = (struct scic_sds_phy *)object; | ||
1745 | |||
1746 | scic_sds_phy_set_starting_substate_handlers( | ||
1747 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER | ||
1748 | ); | ||
1749 | |||
1750 | scic_sds_controller_power_control_queue_insert( | ||
1751 | scic_sds_phy_get_controller(this_phy), | ||
1752 | this_phy | ||
1753 | ); | ||
1754 | } | ||
1755 | |||
1756 | /** | ||
1757 | * | ||
1758 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1759 | * | ||
1760 | * This method will perform the actions required by the struct scic_sds_phy on exiting | ||
1761 | * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER. - Remove the | ||
1762 | * struct scic_sds_phy object from the power control queue. none | ||
1763 | */ | ||
1764 | static void scic_sds_phy_starting_await_sas_power_substate_exit( | ||
1765 | struct sci_base_object *object) | ||
1766 | { | ||
1767 | struct scic_sds_phy *this_phy; | ||
1768 | |||
1769 | this_phy = (struct scic_sds_phy *)object; | ||
1770 | |||
1771 | scic_sds_controller_power_control_queue_remove( | ||
1772 | scic_sds_phy_get_controller(this_phy), this_phy | ||
1773 | ); | ||
1774 | } | ||
1775 | |||
1776 | /** | ||
1777 | * | ||
1778 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1779 | * | ||
1780 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1781 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Set the | ||
1782 | * struct scic_sds_phy object state handlers for this state. - Add this phy object to | ||
1783 | * the power control queue none | ||
1784 | */ | ||
1785 | static void scic_sds_phy_starting_await_sata_power_substate_enter( | ||
1786 | struct sci_base_object *object) | ||
1787 | { | ||
1788 | struct scic_sds_phy *this_phy; | ||
1789 | |||
1790 | this_phy = (struct scic_sds_phy *)object; | ||
1791 | |||
1792 | scic_sds_phy_set_starting_substate_handlers( | ||
1793 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER | ||
1794 | ); | ||
1795 | |||
1796 | scic_sds_controller_power_control_queue_insert( | ||
1797 | scic_sds_phy_get_controller(this_phy), | ||
1798 | this_phy | ||
1799 | ); | ||
1800 | } | ||
1801 | |||
1802 | /** | ||
1803 | * | ||
1804 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1805 | * | ||
1806 | * This method will perform the actions required by the struct scic_sds_phy on exiting | ||
1807 | * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER. - Remove the | ||
1808 | * struct scic_sds_phy object from the power control queue. none | ||
1809 | */ | ||
1810 | static void scic_sds_phy_starting_await_sata_power_substate_exit( | ||
1811 | struct sci_base_object *object) | ||
1812 | { | ||
1813 | struct scic_sds_phy *this_phy; | ||
1814 | |||
1815 | this_phy = (struct scic_sds_phy *)object; | ||
1816 | |||
1817 | scic_sds_controller_power_control_queue_remove( | ||
1818 | scic_sds_phy_get_controller(this_phy), | ||
1819 | this_phy | ||
1820 | ); | ||
1821 | } | ||
1822 | |||
1823 | /** | ||
1824 | * | ||
1825 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1826 | * | ||
1827 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1828 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN. - Set the | ||
1829 | * struct scic_sds_phy object state handlers for this state. none | ||
1830 | */ | ||
1831 | static void scic_sds_phy_starting_await_sata_phy_substate_enter( | ||
1832 | struct sci_base_object *object) | ||
1833 | { | ||
1834 | struct scic_sds_phy *this_phy; | ||
1835 | |||
1836 | this_phy = (struct scic_sds_phy *)object; | ||
1837 | |||
1838 | scic_sds_phy_set_starting_substate_handlers( | ||
1839 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN | ||
1840 | ); | ||
1841 | |||
1842 | scic_cb_timer_start( | ||
1843 | scic_sds_phy_get_controller(this_phy), | ||
1844 | this_phy->sata_timeout_timer, | ||
1845 | SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT | ||
1846 | ); | ||
1847 | } | ||
1848 | |||
1849 | /** | ||
1850 | * | ||
1851 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1852 | * | ||
1853 | * This method will perform the actions required by the struct scic_sds_phy on exiting | ||
1854 | * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer | ||
1855 | * that was started on entry to await sata phy event notification none | ||
1856 | */ | ||
1857 | static void scic_sds_phy_starting_await_sata_phy_substate_exit( | ||
1858 | struct sci_base_object *object) | ||
1859 | { | ||
1860 | struct scic_sds_phy *this_phy; | ||
1861 | |||
1862 | this_phy = (struct scic_sds_phy *)object; | ||
1863 | |||
1864 | scic_cb_timer_stop( | ||
1865 | scic_sds_phy_get_controller(this_phy), | ||
1866 | this_phy->sata_timeout_timer | ||
1867 | ); | ||
1868 | } | ||
1869 | |||
1870 | /** | ||
1871 | * | ||
1872 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1873 | * | ||
1874 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1875 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - Set the | ||
1876 | * struct scic_sds_phy object state handlers for this state. none | ||
1877 | */ | ||
1878 | static void scic_sds_phy_starting_await_sata_speed_substate_enter( | ||
1879 | struct sci_base_object *object) | ||
1880 | { | ||
1881 | struct scic_sds_phy *this_phy; | ||
1882 | |||
1883 | this_phy = (struct scic_sds_phy *)object; | ||
1884 | |||
1885 | scic_sds_phy_set_starting_substate_handlers( | ||
1886 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN | ||
1887 | ); | ||
1888 | |||
1889 | scic_cb_timer_start( | ||
1890 | scic_sds_phy_get_controller(this_phy), | ||
1891 | this_phy->sata_timeout_timer, | ||
1892 | SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT | ||
1893 | ); | ||
1894 | } | ||
1895 | |||
1896 | /** | ||
1897 | * | ||
1898 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1899 | * | ||
1900 | * This method will perform the actions required by the struct scic_sds_phy on exiting | ||
1901 | * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN. - stop the timer | ||
1902 | * that was started on entry to await sata phy event notification none | ||
1903 | */ | ||
1904 | static void scic_sds_phy_starting_await_sata_speed_substate_exit( | ||
1905 | struct sci_base_object *object) | ||
1906 | { | ||
1907 | struct scic_sds_phy *this_phy; | ||
1908 | |||
1909 | this_phy = (struct scic_sds_phy *)object; | ||
1910 | |||
1911 | scic_cb_timer_stop( | ||
1912 | scic_sds_phy_get_controller(this_phy), | ||
1913 | this_phy->sata_timeout_timer | ||
1914 | ); | ||
1915 | } | ||
1916 | |||
1917 | /** | ||
1918 | * | ||
1919 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1920 | * | ||
1921 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1922 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Set the | ||
1923 | * struct scic_sds_phy object state handlers for this state. - Start the SIGNATURE FIS | ||
1924 | * timeout timer none | ||
1925 | */ | ||
1926 | static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter( | ||
1927 | struct sci_base_object *object) | ||
1928 | { | ||
1929 | bool continue_to_ready_state; | ||
1930 | struct scic_sds_phy *this_phy; | ||
1931 | |||
1932 | this_phy = (struct scic_sds_phy *)object; | ||
1933 | |||
1934 | scic_sds_phy_set_starting_substate_handlers( | ||
1935 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF | ||
1936 | ); | ||
1937 | |||
1938 | continue_to_ready_state = scic_sds_port_link_detected( | ||
1939 | this_phy->owning_port, | ||
1940 | this_phy | ||
1941 | ); | ||
1942 | |||
1943 | if (continue_to_ready_state) { | ||
1944 | /* | ||
1945 | * Clear the PE suspend condition so we can actually receive SIG FIS | ||
1946 | * The hardware will not respond to the XRDY until the PE suspend | ||
1947 | * condition is cleared. */ | ||
1948 | scic_sds_phy_resume(this_phy); | ||
1949 | |||
1950 | scic_cb_timer_start( | ||
1951 | scic_sds_phy_get_controller(this_phy), | ||
1952 | this_phy->sata_timeout_timer, | ||
1953 | SCIC_SDS_SIGNATURE_FIS_TIMEOUT | ||
1954 | ); | ||
1955 | } else { | ||
1956 | this_phy->is_in_link_training = false; | ||
1957 | } | ||
1958 | } | ||
1959 | |||
1960 | /** | ||
1961 | * | ||
1962 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1963 | * | ||
1964 | * This method will perform the actions required by the struct scic_sds_phy on exiting | ||
1965 | * the SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF. - Stop the SIGNATURE | ||
1966 | * FIS timeout timer. none | ||
1967 | */ | ||
1968 | static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit( | ||
1969 | struct sci_base_object *object) | ||
1970 | { | ||
1971 | struct scic_sds_phy *this_phy; | ||
1972 | |||
1973 | this_phy = (struct scic_sds_phy *)object; | ||
1974 | |||
1975 | scic_cb_timer_stop( | ||
1976 | scic_sds_phy_get_controller(this_phy), | ||
1977 | this_phy->sata_timeout_timer | ||
1978 | ); | ||
1979 | } | ||
1980 | |||
1981 | /** | ||
1982 | * | ||
1983 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
1984 | * | ||
1985 | * This method will perform the actions required by the struct scic_sds_phy on | ||
1986 | * entering the SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL. - Set the struct scic_sds_phy | ||
1987 | * object state handlers for this state. - Change base state machine to the | ||
1988 | * ready state. none | ||
1989 | */ | ||
1990 | static void scic_sds_phy_starting_final_substate_enter( | ||
1991 | struct sci_base_object *object) | ||
1992 | { | ||
1993 | struct scic_sds_phy *this_phy; | ||
1994 | |||
1995 | this_phy = (struct scic_sds_phy *)object; | ||
1996 | |||
1997 | scic_sds_phy_set_starting_substate_handlers( | ||
1998 | this_phy, SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL | ||
1999 | ); | ||
2000 | |||
2001 | /* | ||
2002 | * State machine has run to completion so exit out and change | ||
2003 | * the base state machine to the ready state */ | ||
2004 | sci_base_state_machine_change_state( | ||
2005 | scic_sds_phy_get_base_state_machine(this_phy), | ||
2006 | SCI_BASE_PHY_STATE_READY); | ||
2007 | } | ||
2008 | |||
2009 | /* --------------------------------------------------------------------------- */ | ||
2010 | |||
2011 | const struct sci_base_state scic_sds_phy_starting_substates[] = { | ||
2012 | [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = { | ||
2013 | .enter_state = scic_sds_phy_starting_initial_substate_enter, | ||
2014 | }, | ||
2015 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { | ||
2016 | .enter_state = scic_sds_phy_starting_await_ossp_en_substate_enter, | ||
2017 | }, | ||
2018 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { | ||
2019 | .enter_state = scic_sds_phy_starting_await_sas_speed_en_substate_enter, | ||
2020 | }, | ||
2021 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { | ||
2022 | .enter_state = scic_sds_phy_starting_await_iaf_uf_substate_enter, | ||
2023 | }, | ||
2024 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = { | ||
2025 | .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter, | ||
2026 | .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit, | ||
2027 | }, | ||
2028 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = { | ||
2029 | .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter, | ||
2030 | .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit | ||
2031 | }, | ||
2032 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = { | ||
2033 | .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter, | ||
2034 | .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit | ||
2035 | }, | ||
2036 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = { | ||
2037 | .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter, | ||
2038 | .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit | ||
2039 | }, | ||
2040 | [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = { | ||
2041 | .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter, | ||
2042 | .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit | ||
2043 | }, | ||
2044 | [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = { | ||
2045 | .enter_state = scic_sds_phy_starting_final_substate_enter, | ||
2046 | } | ||
2047 | }; | ||
2048 | |||
2049 | /* | ||
2050 | * *************************************************************************** | ||
2051 | * * DEFAULT HANDLERS | ||
2052 | * *************************************************************************** */ | ||
2053 | |||
2054 | /** | ||
2055 | * | ||
2056 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2057 | * object. | ||
2058 | * | ||
2059 | * This is the default method for phy a start request. It will report a | ||
2060 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2061 | */ | ||
2062 | enum sci_status scic_sds_phy_default_start_handler( | ||
2063 | struct sci_base_phy *phy) | ||
2064 | { | ||
2065 | struct scic_sds_phy *this_phy; | ||
2066 | |||
2067 | this_phy = (struct scic_sds_phy *)phy; | ||
2068 | |||
2069 | dev_warn(sciphy_to_dev(this_phy), | ||
2070 | "%s: SCIC Phy 0x%p requested to start from invalid " | ||
2071 | "state %d\n", | ||
2072 | __func__, | ||
2073 | this_phy, | ||
2074 | sci_base_state_machine_get_state( | ||
2075 | &this_phy->parent.state_machine)); | ||
2076 | |||
2077 | return SCI_FAILURE_INVALID_STATE; | ||
2078 | |||
2079 | } | ||
2080 | |||
2081 | /** | ||
2082 | * | ||
2083 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2084 | * object. | ||
2085 | * | ||
2086 | * This is the default method for phy a stop request. It will report a warning | ||
2087 | * and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2088 | */ | ||
2089 | enum sci_status scic_sds_phy_default_stop_handler( | ||
2090 | struct sci_base_phy *phy) | ||
2091 | { | ||
2092 | struct scic_sds_phy *this_phy; | ||
2093 | |||
2094 | this_phy = (struct scic_sds_phy *)phy; | ||
2095 | |||
2096 | dev_warn(sciphy_to_dev(this_phy), | ||
2097 | "%s: SCIC Phy 0x%p requested to stop from invalid " | ||
2098 | "state %d\n", | ||
2099 | __func__, | ||
2100 | this_phy, | ||
2101 | sci_base_state_machine_get_state( | ||
2102 | &this_phy->parent.state_machine)); | ||
2103 | |||
2104 | return SCI_FAILURE_INVALID_STATE; | ||
2105 | } | ||
2106 | |||
2107 | /** | ||
2108 | * | ||
2109 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2110 | * object. | ||
2111 | * | ||
2112 | * This is the default method for phy a reset request. It will report a | ||
2113 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2114 | */ | ||
2115 | enum sci_status scic_sds_phy_default_reset_handler( | ||
2116 | struct sci_base_phy *phy) | ||
2117 | { | ||
2118 | struct scic_sds_phy *this_phy; | ||
2119 | |||
2120 | this_phy = (struct scic_sds_phy *)phy; | ||
2121 | |||
2122 | dev_warn(sciphy_to_dev(this_phy), | ||
2123 | "%s: SCIC Phy 0x%p requested to reset from invalid state " | ||
2124 | "%d\n", | ||
2125 | __func__, | ||
2126 | this_phy, | ||
2127 | sci_base_state_machine_get_state( | ||
2128 | &this_phy->parent.state_machine)); | ||
2129 | |||
2130 | return SCI_FAILURE_INVALID_STATE; | ||
2131 | } | ||
2132 | |||
2133 | /** | ||
2134 | * | ||
2135 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2136 | * object. | ||
2137 | * | ||
2138 | * This is the default method for phy a destruct request. It will report a | ||
2139 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2140 | */ | ||
2141 | enum sci_status scic_sds_phy_default_destroy_handler( | ||
2142 | struct sci_base_phy *phy) | ||
2143 | { | ||
2144 | struct scic_sds_phy *this_phy; | ||
2145 | |||
2146 | this_phy = (struct scic_sds_phy *)phy; | ||
2147 | |||
2148 | /* / @todo Implement something for the default */ | ||
2149 | dev_warn(sciphy_to_dev(this_phy), | ||
2150 | "%s: SCIC Phy 0x%p requested to destroy from invalid " | ||
2151 | "state %d\n", | ||
2152 | __func__, | ||
2153 | this_phy, | ||
2154 | sci_base_state_machine_get_state( | ||
2155 | &this_phy->parent.state_machine)); | ||
2156 | |||
2157 | return SCI_FAILURE_INVALID_STATE; | ||
2158 | } | ||
2159 | |||
2160 | /** | ||
2161 | * | ||
2162 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2163 | * object. | ||
2164 | * @frame_index: This is the frame index that was received from the SCU | ||
2165 | * hardware. | ||
2166 | * | ||
2167 | * This is the default method for a phy frame handling request. It will report | ||
2168 | * a warning, release the frame and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2169 | */ | ||
2170 | enum sci_status scic_sds_phy_default_frame_handler( | ||
2171 | struct scic_sds_phy *this_phy, | ||
2172 | u32 frame_index) | ||
2173 | { | ||
2174 | dev_warn(sciphy_to_dev(this_phy), | ||
2175 | "%s: SCIC Phy 0x%p received unexpected frame data %d " | ||
2176 | "while in state %d\n", | ||
2177 | __func__, | ||
2178 | this_phy, | ||
2179 | frame_index, | ||
2180 | sci_base_state_machine_get_state( | ||
2181 | &this_phy->parent.state_machine)); | ||
2182 | |||
2183 | scic_sds_controller_release_frame( | ||
2184 | scic_sds_phy_get_controller(this_phy), frame_index); | ||
2185 | |||
2186 | return SCI_FAILURE_INVALID_STATE; | ||
2187 | } | ||
2188 | |||
2189 | /** | ||
2190 | * | ||
2191 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2192 | * object. | ||
2193 | * @event_code: This is the event code that was received from the SCU hardware. | ||
2194 | * | ||
2195 | * This is the default method for a phy event handler. It will report a | ||
2196 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2197 | */ | ||
2198 | enum sci_status scic_sds_phy_default_event_handler( | ||
2199 | struct scic_sds_phy *this_phy, | ||
2200 | u32 event_code) | ||
2201 | { | ||
2202 | dev_warn(sciphy_to_dev(this_phy), | ||
2203 | "%s: SCIC Phy 0x%p received unexpected event status %x " | ||
2204 | "while in state %d\n", | ||
2205 | __func__, | ||
2206 | this_phy, | ||
2207 | event_code, | ||
2208 | sci_base_state_machine_get_state( | ||
2209 | &this_phy->parent.state_machine)); | ||
2210 | |||
2211 | return SCI_FAILURE_INVALID_STATE; | ||
2212 | } | ||
2213 | |||
2214 | /** | ||
2215 | * | ||
2216 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2217 | * object. | ||
2218 | * | ||
2219 | * This is the default method for a phy consume power handler. It will report | ||
2220 | * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2221 | */ | ||
2222 | enum sci_status scic_sds_phy_default_consume_power_handler( | ||
2223 | struct scic_sds_phy *this_phy) | ||
2224 | { | ||
2225 | dev_warn(sciphy_to_dev(this_phy), | ||
2226 | "%s: SCIC Phy 0x%p given unexpected permission to consume " | ||
2227 | "power while in state %d\n", | ||
2228 | __func__, | ||
2229 | this_phy, | ||
2230 | sci_base_state_machine_get_state( | ||
2231 | &this_phy->parent.state_machine)); | ||
2232 | |||
2233 | return SCI_FAILURE_INVALID_STATE; | ||
2234 | } | ||
2235 | |||
2236 | /* | ||
2237 | * ****************************************************************************** | ||
2238 | * * PHY STOPPED STATE HANDLERS | ||
2239 | * ****************************************************************************** */ | ||
2240 | |||
2241 | /** | ||
2242 | * | ||
2243 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2244 | * object. | ||
2245 | * | ||
2246 | * This method takes the struct scic_sds_phy from a stopped state and attempts to | ||
2247 | * start it. - The phy state machine is transitioned to the | ||
2248 | * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS | ||
2249 | */ | ||
2250 | static enum sci_status scic_sds_phy_stopped_state_start_handler( | ||
2251 | struct sci_base_phy *phy) | ||
2252 | { | ||
2253 | struct scic_sds_phy *this_phy; | ||
2254 | |||
2255 | this_phy = (struct scic_sds_phy *)phy; | ||
2256 | |||
2257 | sci_base_state_machine_change_state( | ||
2258 | scic_sds_phy_get_base_state_machine(this_phy), | ||
2259 | SCI_BASE_PHY_STATE_STARTING | ||
2260 | ); | ||
2261 | |||
2262 | return SCI_SUCCESS; | ||
2263 | } | ||
2264 | |||
2265 | /** | ||
2266 | * | ||
2267 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2268 | * object. | ||
2269 | * | ||
2270 | * This method takes the struct scic_sds_phy from a stopped state and destroys it. - | ||
2271 | * This function takes no action. Shouldnt this function transition the | ||
2272 | * struct sci_base_phy::state_machine to the SCI_BASE_PHY_STATE_FINAL? enum sci_status | ||
2273 | * SCI_SUCCESS | ||
2274 | */ | ||
2275 | static enum sci_status scic_sds_phy_stopped_state_destroy_handler( | ||
2276 | struct sci_base_phy *phy) | ||
2277 | { | ||
2278 | struct scic_sds_phy *this_phy; | ||
2279 | |||
2280 | this_phy = (struct scic_sds_phy *)phy; | ||
2281 | |||
2282 | /* / @todo what do we actually need to do here? */ | ||
2283 | return SCI_SUCCESS; | ||
2284 | } | ||
2285 | |||
2286 | /* | ||
2287 | * ****************************************************************************** | ||
2288 | * * PHY STARTING STATE HANDLERS | ||
2289 | * ****************************************************************************** */ | ||
2290 | |||
2291 | /* All of these state handlers are mapped to the starting sub-state machine */ | ||
2292 | |||
2293 | /* | ||
2294 | * ****************************************************************************** | ||
2295 | * * PHY READY STATE HANDLERS | ||
2296 | * ****************************************************************************** */ | ||
2297 | |||
2298 | /** | ||
2299 | * | ||
2300 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2301 | * object. | ||
2302 | * | ||
2303 | * This method takes the struct scic_sds_phy from a ready state and attempts to stop | ||
2304 | * it. - The phy state machine is transitioned to the | ||
2305 | * SCI_BASE_PHY_STATE_STOPPED. enum sci_status SCI_SUCCESS | ||
2306 | */ | ||
2307 | static enum sci_status scic_sds_phy_ready_state_stop_handler( | ||
2308 | struct sci_base_phy *phy) | ||
2309 | { | ||
2310 | struct scic_sds_phy *this_phy; | ||
2311 | |||
2312 | this_phy = (struct scic_sds_phy *)phy; | ||
2313 | |||
2314 | sci_base_state_machine_change_state( | ||
2315 | scic_sds_phy_get_base_state_machine(this_phy), | ||
2316 | SCI_BASE_PHY_STATE_STOPPED | ||
2317 | ); | ||
2318 | |||
2319 | return SCI_SUCCESS; | ||
2320 | } | ||
2321 | |||
2322 | /** | ||
2323 | * | ||
2324 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2325 | * object. | ||
2326 | * | ||
2327 | * This method takes the struct scic_sds_phy from a ready state and attempts to reset | ||
2328 | * it. - The phy state machine is transitioned to the | ||
2329 | * SCI_BASE_PHY_STATE_STARTING. enum sci_status SCI_SUCCESS | ||
2330 | */ | ||
2331 | static enum sci_status scic_sds_phy_ready_state_reset_handler( | ||
2332 | struct sci_base_phy *phy) | ||
2333 | { | ||
2334 | struct scic_sds_phy *this_phy; | ||
2335 | |||
2336 | this_phy = (struct scic_sds_phy *)phy; | ||
2337 | |||
2338 | sci_base_state_machine_change_state( | ||
2339 | scic_sds_phy_get_base_state_machine(this_phy), | ||
2340 | SCI_BASE_PHY_STATE_RESETTING | ||
2341 | ); | ||
2342 | |||
2343 | return SCI_SUCCESS; | ||
2344 | } | ||
2345 | |||
2346 | /** | ||
2347 | * | ||
2348 | * @phy: This is the struct scic_sds_phy object which has received the event. | ||
2349 | * | ||
2350 | * This method request the struct scic_sds_phy handle the received event. The only | ||
2351 | * event that we are interested in while in the ready state is the link failure | ||
2352 | * event. - decoded event is a link failure - transition the struct scic_sds_phy back | ||
2353 | * to the SCI_BASE_PHY_STATE_STARTING state. - any other event recived will | ||
2354 | * report a warning message enum sci_status SCI_SUCCESS if the event received is a | ||
2355 | * link failure SCI_FAILURE_INVALID_STATE for any other event received. | ||
2356 | */ | ||
2357 | static enum sci_status scic_sds_phy_ready_state_event_handler( | ||
2358 | struct scic_sds_phy *this_phy, | ||
2359 | u32 event_code) | ||
2360 | { | ||
2361 | enum sci_status result = SCI_FAILURE; | ||
2362 | |||
2363 | switch (scu_get_event_code(event_code)) { | ||
2364 | case SCU_EVENT_LINK_FAILURE: | ||
2365 | /* Link failure change state back to the starting state */ | ||
2366 | sci_base_state_machine_change_state( | ||
2367 | scic_sds_phy_get_base_state_machine(this_phy), | ||
2368 | SCI_BASE_PHY_STATE_STARTING | ||
2369 | ); | ||
2370 | |||
2371 | result = SCI_SUCCESS; | ||
2372 | break; | ||
2373 | |||
2374 | case SCU_EVENT_BROADCAST_CHANGE: | ||
2375 | /* Broadcast change received. Notify the port. */ | ||
2376 | if (scic_sds_phy_get_port(this_phy) != SCI_INVALID_HANDLE) | ||
2377 | scic_sds_port_broadcast_change_received(this_phy->owning_port, this_phy); | ||
2378 | else | ||
2379 | this_phy->bcn_received_while_port_unassigned = true; | ||
2380 | break; | ||
2381 | |||
2382 | default: | ||
2383 | dev_warn(sciphy_to_dev(this_phy), | ||
2384 | "%sP SCIC PHY 0x%p ready state machine received " | ||
2385 | "unexpected event_code %x\n", | ||
2386 | __func__, | ||
2387 | this_phy, | ||
2388 | event_code); | ||
2389 | |||
2390 | result = SCI_FAILURE_INVALID_STATE; | ||
2391 | break; | ||
2392 | } | ||
2393 | |||
2394 | return result; | ||
2395 | } | ||
2396 | |||
2397 | /* --------------------------------------------------------------------------- */ | ||
2398 | |||
2399 | /** | ||
2400 | * | ||
2401 | * @this_phy: This is the struct scic_sds_phy object which is receiving the event. | ||
2402 | * @event_code: This is the event code to be processed. | ||
2403 | * | ||
2404 | * This is the resetting state event handler. enum sci_status | ||
2405 | * SCI_FAILURE_INVALID_STATE | ||
2406 | */ | ||
2407 | static enum sci_status scic_sds_phy_resetting_state_event_handler( | ||
2408 | struct scic_sds_phy *this_phy, | ||
2409 | u32 event_code) | ||
2410 | { | ||
2411 | enum sci_status result = SCI_FAILURE; | ||
2412 | |||
2413 | switch (scu_get_event_code(event_code)) { | ||
2414 | case SCU_EVENT_HARD_RESET_TRANSMITTED: | ||
2415 | /* Link failure change state back to the starting state */ | ||
2416 | sci_base_state_machine_change_state( | ||
2417 | scic_sds_phy_get_base_state_machine(this_phy), | ||
2418 | SCI_BASE_PHY_STATE_STARTING | ||
2419 | ); | ||
2420 | |||
2421 | result = SCI_SUCCESS; | ||
2422 | break; | ||
2423 | |||
2424 | default: | ||
2425 | dev_warn(sciphy_to_dev(this_phy), | ||
2426 | "%s: SCIC PHY 0x%p resetting state machine received " | ||
2427 | "unexpected event_code %x\n", | ||
2428 | __func__, | ||
2429 | this_phy, | ||
2430 | event_code); | ||
2431 | |||
2432 | result = SCI_FAILURE_INVALID_STATE; | ||
2433 | break; | ||
2434 | } | ||
2435 | |||
2436 | return result; | ||
2437 | } | ||
2438 | |||
2439 | /* --------------------------------------------------------------------------- */ | ||
2440 | |||
2441 | struct scic_sds_phy_state_handler | ||
2442 | scic_sds_phy_state_handler_table[SCI_BASE_PHY_MAX_STATES] = | ||
2443 | { | ||
2444 | /* SCI_BASE_PHY_STATE_INITIAL */ | ||
2445 | { | ||
2446 | { | ||
2447 | scic_sds_phy_default_start_handler, | ||
2448 | scic_sds_phy_default_stop_handler, | ||
2449 | scic_sds_phy_default_reset_handler, | ||
2450 | scic_sds_phy_default_destroy_handler | ||
2451 | }, | ||
2452 | scic_sds_phy_default_frame_handler, | ||
2453 | scic_sds_phy_default_event_handler, | ||
2454 | scic_sds_phy_default_consume_power_handler | ||
2455 | }, | ||
2456 | /* SCI_BASE_PHY_STATE_STOPPED */ | ||
2457 | { | ||
2458 | { | ||
2459 | scic_sds_phy_stopped_state_start_handler, | ||
2460 | scic_sds_phy_default_stop_handler, | ||
2461 | scic_sds_phy_default_reset_handler, | ||
2462 | scic_sds_phy_stopped_state_destroy_handler | ||
2463 | }, | ||
2464 | scic_sds_phy_default_frame_handler, | ||
2465 | scic_sds_phy_default_event_handler, | ||
2466 | scic_sds_phy_default_consume_power_handler | ||
2467 | }, | ||
2468 | /* SCI_BASE_PHY_STATE_STARTING */ | ||
2469 | { | ||
2470 | { | ||
2471 | scic_sds_phy_default_start_handler, | ||
2472 | scic_sds_phy_default_stop_handler, | ||
2473 | scic_sds_phy_default_reset_handler, | ||
2474 | scic_sds_phy_default_destroy_handler | ||
2475 | }, | ||
2476 | scic_sds_phy_default_frame_handler, | ||
2477 | scic_sds_phy_default_event_handler, | ||
2478 | scic_sds_phy_default_consume_power_handler | ||
2479 | }, | ||
2480 | /* SCI_BASE_PHY_STATE_READY */ | ||
2481 | { | ||
2482 | { | ||
2483 | scic_sds_phy_default_start_handler, | ||
2484 | scic_sds_phy_ready_state_stop_handler, | ||
2485 | scic_sds_phy_ready_state_reset_handler, | ||
2486 | scic_sds_phy_default_destroy_handler | ||
2487 | }, | ||
2488 | scic_sds_phy_default_frame_handler, | ||
2489 | scic_sds_phy_ready_state_event_handler, | ||
2490 | scic_sds_phy_default_consume_power_handler | ||
2491 | }, | ||
2492 | /* SCI_BASE_PHY_STATE_RESETTING */ | ||
2493 | { | ||
2494 | { | ||
2495 | scic_sds_phy_default_start_handler, | ||
2496 | scic_sds_phy_default_stop_handler, | ||
2497 | scic_sds_phy_default_reset_handler, | ||
2498 | scic_sds_phy_default_destroy_handler | ||
2499 | }, | ||
2500 | scic_sds_phy_default_frame_handler, | ||
2501 | scic_sds_phy_resetting_state_event_handler, | ||
2502 | scic_sds_phy_default_consume_power_handler | ||
2503 | }, | ||
2504 | /* SCI_BASE_PHY_STATE_FINAL */ | ||
2505 | { | ||
2506 | { | ||
2507 | scic_sds_phy_default_start_handler, | ||
2508 | scic_sds_phy_default_stop_handler, | ||
2509 | scic_sds_phy_default_reset_handler, | ||
2510 | scic_sds_phy_default_destroy_handler | ||
2511 | }, | ||
2512 | scic_sds_phy_default_frame_handler, | ||
2513 | scic_sds_phy_default_event_handler, | ||
2514 | scic_sds_phy_default_consume_power_handler | ||
2515 | } | ||
2516 | }; | ||
2517 | |||
2518 | /* | ||
2519 | * **************************************************************************** | ||
2520 | * * PHY STATE PRIVATE METHODS | ||
2521 | * **************************************************************************** */ | ||
2522 | |||
2523 | /** | ||
2524 | * | ||
2525 | * @this_phy: This is the struct scic_sds_phy object to stop. | ||
2526 | * | ||
2527 | * This method will stop the struct scic_sds_phy object. This does not reset the | ||
2528 | * protocol engine it just suspends it and places it in a state where it will | ||
2529 | * not cause the end device to power up. none | ||
2530 | */ | ||
2531 | static void scu_link_layer_stop_protocol_engine( | ||
2532 | struct scic_sds_phy *this_phy) | ||
2533 | { | ||
2534 | u32 scu_sas_pcfg_value; | ||
2535 | u32 enable_spinup_value; | ||
2536 | |||
2537 | /* Suspend the protocol engine and place it in a sata spinup hold state */ | ||
2538 | scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); | ||
2539 | scu_sas_pcfg_value |= ( | ||
2540 | SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | ||
2541 | | SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) | ||
2542 | | SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | ||
2543 | ); | ||
2544 | SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); | ||
2545 | |||
2546 | /* Disable the notify enable spinup primitives */ | ||
2547 | enable_spinup_value = SCU_SAS_ENSPINUP_READ(this_phy); | ||
2548 | enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE); | ||
2549 | SCU_SAS_ENSPINUP_WRITE(this_phy, enable_spinup_value); | ||
2550 | } | ||
2551 | |||
2552 | /** | ||
2553 | * | ||
2554 | * | ||
2555 | * This method will start the OOB/SN state machine for this struct scic_sds_phy object. | ||
2556 | */ | ||
2557 | static void scu_link_layer_start_oob( | ||
2558 | struct scic_sds_phy *this_phy) | ||
2559 | { | ||
2560 | u32 scu_sas_pcfg_value; | ||
2561 | |||
2562 | scu_sas_pcfg_value = SCU_SAS_PCFG_READ(this_phy); | ||
2563 | scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); | ||
2564 | scu_sas_pcfg_value &= | ||
2565 | ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) | SCU_SAS_PCFG_GEN_BIT(HARD_RESET)); | ||
2566 | |||
2567 | SCU_SAS_PCFG_WRITE(this_phy, scu_sas_pcfg_value); | ||
2568 | } | ||
2569 | |||
2570 | /** | ||
2571 | * | ||
2572 | * | ||
2573 | * This method will transmit a hard reset request on the specified phy. The SCU | ||
2574 | * hardware requires that we reset the OOB state machine and set the hard reset | ||
2575 | * bit in the phy configuration register. We then must start OOB over with the | ||
2576 | * hard reset bit set. | ||
2577 | */ | ||
2578 | static void scu_link_layer_tx_hard_reset( | ||
2579 | struct scic_sds_phy *this_phy) | ||
2580 | { | ||
2581 | u32 phy_configuration_value; | ||
2582 | |||
2583 | /* | ||
2584 | * SAS Phys must wait for the HARD_RESET_TX event notification to transition | ||
2585 | * to the starting state. */ | ||
2586 | phy_configuration_value = SCU_SAS_PCFG_READ(this_phy); | ||
2587 | phy_configuration_value |= | ||
2588 | (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) | SCU_SAS_PCFG_GEN_BIT(OOB_RESET)); | ||
2589 | SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); | ||
2590 | |||
2591 | /* Now take the OOB state machine out of reset */ | ||
2592 | phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE); | ||
2593 | phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET); | ||
2594 | SCU_SAS_PCFG_WRITE(this_phy, phy_configuration_value); | ||
2595 | } | ||
2596 | |||
2597 | /* | ||
2598 | * **************************************************************************** | ||
2599 | * * PHY BASE STATE METHODS | ||
2600 | * **************************************************************************** */ | ||
2601 | |||
2602 | /** | ||
2603 | * | ||
2604 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
2605 | * | ||
2606 | * This method will perform the actions required by the struct scic_sds_phy on | ||
2607 | * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state | ||
2608 | * handlers for the phy object base state machine initial state. none | ||
2609 | */ | ||
2610 | static void scic_sds_phy_initial_state_enter( | ||
2611 | struct sci_base_object *object) | ||
2612 | { | ||
2613 | struct scic_sds_phy *this_phy; | ||
2614 | |||
2615 | this_phy = (struct scic_sds_phy *)object; | ||
2616 | |||
2617 | scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED); | ||
2618 | } | ||
2619 | |||
2620 | /** | ||
2621 | * | ||
2622 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
2623 | * | ||
2624 | * This method will perform the actions required by the struct scic_sds_phy on | ||
2625 | * entering the SCI_BASE_PHY_STATE_INITIAL. - This function sets the state | ||
2626 | * handlers for the phy object base state machine initial state. - The SCU | ||
2627 | * hardware is requested to stop the protocol engine. none | ||
2628 | */ | ||
2629 | static void scic_sds_phy_stopped_state_enter( | ||
2630 | struct sci_base_object *object) | ||
2631 | { | ||
2632 | struct scic_sds_phy *this_phy; | ||
2633 | |||
2634 | this_phy = (struct scic_sds_phy *)object; | ||
2635 | |||
2636 | /* / @todo We need to get to the controller to place this PE in a reset state */ | ||
2637 | |||
2638 | scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STOPPED); | ||
2639 | |||
2640 | scu_link_layer_stop_protocol_engine(this_phy); | ||
2641 | } | ||
2642 | |||
2643 | /** | ||
2644 | * | ||
2645 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
2646 | * | ||
2647 | * This method will perform the actions required by the struct scic_sds_phy on | ||
2648 | * entering the SCI_BASE_PHY_STATE_STARTING. - This function sets the state | ||
2649 | * handlers for the phy object base state machine starting state. - The SCU | ||
2650 | * hardware is requested to start OOB/SN on this protocl engine. - The phy | ||
2651 | * starting substate machine is started. - If the previous state was the ready | ||
2652 | * state then the struct scic_sds_controller is informed that the phy has gone link | ||
2653 | * down. none | ||
2654 | */ | ||
2655 | static void scic_sds_phy_starting_state_enter( | ||
2656 | struct sci_base_object *object) | ||
2657 | { | ||
2658 | struct scic_sds_phy *this_phy; | ||
2659 | |||
2660 | this_phy = (struct scic_sds_phy *)object; | ||
2661 | |||
2662 | scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_STARTING); | ||
2663 | |||
2664 | scu_link_layer_stop_protocol_engine(this_phy); | ||
2665 | scu_link_layer_start_oob(this_phy); | ||
2666 | |||
2667 | /* We don't know what kind of phy we are going to be just yet */ | ||
2668 | this_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN; | ||
2669 | this_phy->bcn_received_while_port_unassigned = false; | ||
2670 | |||
2671 | /* Change over to the starting substate machine to continue */ | ||
2672 | sci_base_state_machine_start(&this_phy->starting_substate_machine); | ||
2673 | |||
2674 | if (this_phy->parent.state_machine.previous_state_id | ||
2675 | == SCI_BASE_PHY_STATE_READY) { | ||
2676 | scic_sds_controller_link_down( | ||
2677 | scic_sds_phy_get_controller(this_phy), | ||
2678 | scic_sds_phy_get_port(this_phy), | ||
2679 | this_phy | ||
2680 | ); | ||
2681 | } | ||
2682 | } | ||
2683 | |||
2684 | /** | ||
2685 | * | ||
2686 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
2687 | * | ||
2688 | * This method will perform the actions required by the struct scic_sds_phy on | ||
2689 | * entering the SCI_BASE_PHY_STATE_READY. - This function sets the state | ||
2690 | * handlers for the phy object base state machine ready state. - The SCU | ||
2691 | * hardware protocol engine is resumed. - The struct scic_sds_controller is informed | ||
2692 | * that the phy object has gone link up. none | ||
2693 | */ | ||
2694 | static void scic_sds_phy_ready_state_enter( | ||
2695 | struct sci_base_object *object) | ||
2696 | { | ||
2697 | struct scic_sds_phy *this_phy; | ||
2698 | |||
2699 | this_phy = (struct scic_sds_phy *)object; | ||
2700 | |||
2701 | scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_READY); | ||
2702 | |||
2703 | scic_sds_controller_link_up( | ||
2704 | scic_sds_phy_get_controller(this_phy), | ||
2705 | scic_sds_phy_get_port(this_phy), | ||
2706 | this_phy | ||
2707 | ); | ||
2708 | } | ||
2709 | |||
2710 | /** | ||
2711 | * | ||
2712 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
2713 | * | ||
2714 | * This method will perform the actions required by the struct scic_sds_phy on exiting | ||
2715 | * the SCI_BASE_PHY_STATE_INITIAL. This function suspends the SCU hardware | ||
2716 | * protocol engine represented by this struct scic_sds_phy object. none | ||
2717 | */ | ||
2718 | static void scic_sds_phy_ready_state_exit( | ||
2719 | struct sci_base_object *object) | ||
2720 | { | ||
2721 | struct scic_sds_phy *this_phy; | ||
2722 | |||
2723 | this_phy = (struct scic_sds_phy *)object; | ||
2724 | |||
2725 | scic_sds_phy_suspend(this_phy); | ||
2726 | } | ||
2727 | |||
2728 | /** | ||
2729 | * | ||
2730 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
2731 | * | ||
2732 | * This method will perform the actions required by the struct scic_sds_phy on | ||
2733 | * entering the SCI_BASE_PHY_STATE_RESETTING. - This function sets the state | ||
2734 | * handlers for the phy object base state machine resetting state. none | ||
2735 | */ | ||
2736 | static void scic_sds_phy_resetting_state_enter( | ||
2737 | struct sci_base_object *object) | ||
2738 | { | ||
2739 | struct scic_sds_phy *this_phy; | ||
2740 | |||
2741 | this_phy = (struct scic_sds_phy *)object; | ||
2742 | |||
2743 | scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_RESETTING); | ||
2744 | |||
2745 | /* | ||
2746 | * The phy is being reset, therefore deactivate it from the port. | ||
2747 | * In the resetting state we don't notify the user regarding | ||
2748 | * link up and link down notifications. */ | ||
2749 | scic_sds_port_deactivate_phy(this_phy->owning_port, this_phy, false); | ||
2750 | |||
2751 | if (this_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) { | ||
2752 | scu_link_layer_tx_hard_reset(this_phy); | ||
2753 | } else { | ||
2754 | /* | ||
2755 | * The SCU does not need to have a descrete reset state so just go back to | ||
2756 | * the starting state. */ | ||
2757 | sci_base_state_machine_change_state( | ||
2758 | &this_phy->parent.state_machine, | ||
2759 | SCI_BASE_PHY_STATE_STARTING | ||
2760 | ); | ||
2761 | } | ||
2762 | } | ||
2763 | |||
2764 | /** | ||
2765 | * | ||
2766 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_phy object. | ||
2767 | * | ||
2768 | * This method will perform the actions required by the struct scic_sds_phy on | ||
2769 | * entering the SCI_BASE_PHY_STATE_FINAL. - This function sets the state | ||
2770 | * handlers for the phy object base state machine final state. none | ||
2771 | */ | ||
2772 | static void scic_sds_phy_final_state_enter( | ||
2773 | struct sci_base_object *object) | ||
2774 | { | ||
2775 | struct scic_sds_phy *this_phy; | ||
2776 | |||
2777 | this_phy = (struct scic_sds_phy *)object; | ||
2778 | |||
2779 | scic_sds_phy_set_base_state_handlers(this_phy, SCI_BASE_PHY_STATE_FINAL); | ||
2780 | |||
2781 | /* Nothing to do here */ | ||
2782 | } | ||
2783 | |||
2784 | /* --------------------------------------------------------------------------- */ | ||
2785 | |||
2786 | const struct sci_base_state scic_sds_phy_state_table[] = { | ||
2787 | [SCI_BASE_PHY_STATE_INITIAL] = { | ||
2788 | .enter_state = scic_sds_phy_initial_state_enter, | ||
2789 | }, | ||
2790 | [SCI_BASE_PHY_STATE_STOPPED] = { | ||
2791 | .enter_state = scic_sds_phy_stopped_state_enter, | ||
2792 | }, | ||
2793 | [SCI_BASE_PHY_STATE_STARTING] = { | ||
2794 | .enter_state = scic_sds_phy_starting_state_enter, | ||
2795 | }, | ||
2796 | [SCI_BASE_PHY_STATE_READY] = { | ||
2797 | .enter_state = scic_sds_phy_ready_state_enter, | ||
2798 | .exit_state = scic_sds_phy_ready_state_exit, | ||
2799 | }, | ||
2800 | [SCI_BASE_PHY_STATE_RESETTING] = { | ||
2801 | .enter_state = scic_sds_phy_resetting_state_enter, | ||
2802 | }, | ||
2803 | [SCI_BASE_PHY_STATE_FINAL] = { | ||
2804 | .enter_state = scic_sds_phy_final_state_enter, | ||
2805 | }, | ||
2806 | }; | ||
2807 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_phy.h b/drivers/scsi/isci/core/scic_sds_phy.h new file mode 100644 index 000000000000..d9691b30e457 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_phy.h | |||
@@ -0,0 +1,491 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_PHY_H_ | ||
57 | #define _SCIC_SDS_PHY_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants and prototypes for the | ||
61 | * struct scic_sds_phy object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "intel_sata.h" | ||
67 | #include "intel_sas.h" | ||
68 | #include "sci_base_phy.h" | ||
69 | #include "scu_registers.h" | ||
70 | |||
71 | struct scic_sds_port; | ||
72 | /** | ||
73 | * | ||
74 | * | ||
75 | * This is the timeout value for the SATA phy to wait for a SIGNATURE FIS | ||
76 | * before restarting the starting state machine. Technically, the old parallel | ||
77 | * ATA specification required up to 30 seconds for a device to issue its | ||
78 | * signature FIS as a result of a soft reset. Now we see that devices respond | ||
79 | * generally within 15 seconds, but we'll use 25 for now. | ||
80 | */ | ||
81 | #define SCIC_SDS_SIGNATURE_FIS_TIMEOUT 25000 | ||
82 | |||
83 | /** | ||
84 | * | ||
85 | * | ||
86 | * This is the timeout for the SATA OOB/SN because the hardware does not | ||
87 | * recognize a hot plug after OOB signal but before the SN signals. We need to | ||
88 | * make sure after a hotplug timeout if we have not received the speed event | ||
89 | * notification from the hardware that we restart the hardware OOB state | ||
90 | * machine. | ||
91 | */ | ||
92 | #define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250 | ||
93 | |||
94 | /** | ||
95 | * enum SCIC_SDS_PHY_STARTING_SUBSTATES - | ||
96 | * | ||
97 | * | ||
98 | */ | ||
99 | enum SCIC_SDS_PHY_STARTING_SUBSTATES { | ||
100 | /** | ||
101 | * Initial state | ||
102 | */ | ||
103 | SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL, | ||
104 | |||
105 | /** | ||
106 | * Wait state for the hardware OSSP event type notification | ||
107 | */ | ||
108 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN, | ||
109 | |||
110 | /** | ||
111 | * Wait state for the PHY speed notification | ||
112 | */ | ||
113 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN, | ||
114 | |||
115 | /** | ||
116 | * Wait state for the IAF Unsolicited frame notification | ||
117 | */ | ||
118 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF, | ||
119 | |||
120 | /** | ||
121 | * Wait state for the request to consume power | ||
122 | */ | ||
123 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER, | ||
124 | |||
125 | /** | ||
126 | * Wait state for request to consume power | ||
127 | */ | ||
128 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER, | ||
129 | |||
130 | /** | ||
131 | * Wait state for the SATA PHY notification | ||
132 | */ | ||
133 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN, | ||
134 | |||
135 | /** | ||
136 | * Wait for the SATA PHY speed notification | ||
137 | */ | ||
138 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN, | ||
139 | |||
140 | /** | ||
141 | * Wait state for the SIGNATURE FIS unsolicited frame notification | ||
142 | */ | ||
143 | SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF, | ||
144 | |||
145 | /** | ||
146 | * Exit state for this state machine | ||
147 | */ | ||
148 | SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL, | ||
149 | |||
150 | /** | ||
151 | * Maximum number of substates for the STARTING state machine | ||
152 | */ | ||
153 | SCIC_SDS_PHY_STARTING_MAX_SUBSTATES | ||
154 | }; | ||
155 | |||
156 | struct scic_sds_port; | ||
157 | struct scic_sds_controller; | ||
158 | |||
159 | #ifdef SCIC_DEBUG_ENABLED | ||
160 | #define MAX_STATE_TRANSITION_RECORD (256) | ||
161 | |||
162 | /** | ||
163 | * | ||
164 | * | ||
165 | * Debug code to record the state transitions for the phy object | ||
166 | */ | ||
167 | struct scic_sds_phy_state_record { | ||
168 | struct sci_base_observer base_state_observer; | ||
169 | struct sci_base_observer starting_state_observer; | ||
170 | |||
171 | u16 index; | ||
172 | |||
173 | u32 state_transition_table[MAX_STATE_TRANSITION_RECORD]; | ||
174 | |||
175 | }; | ||
176 | #endif /* SCIC_DEBUG_ENABLED */ | ||
177 | |||
178 | /** | ||
179 | * This enumeration provides a named phy type for the state machine | ||
180 | * | ||
181 | * | ||
182 | */ | ||
183 | enum SCIC_SDS_PHY_PROTOCOL { | ||
184 | /** | ||
185 | * This is an unknown phy type since there is either nothing on the other | ||
186 | * end or we have not detected the phy type as yet. | ||
187 | */ | ||
188 | SCIC_SDS_PHY_PROTOCOL_UNKNOWN, | ||
189 | |||
190 | /** | ||
191 | * This is a SAS PHY | ||
192 | */ | ||
193 | SCIC_SDS_PHY_PROTOCOL_SAS, | ||
194 | |||
195 | /** | ||
196 | * This is a SATA PHY | ||
197 | */ | ||
198 | SCIC_SDS_PHY_PROTOCOL_SATA, | ||
199 | |||
200 | SCIC_SDS_MAX_PHY_PROTOCOLS | ||
201 | }; | ||
202 | |||
203 | /** | ||
204 | * struct scic_sds_phy - This structure contains or references all of the data | ||
205 | * necessary to represent the core phy object and SCU harware protocol | ||
206 | * engine. | ||
207 | * | ||
208 | * | ||
209 | */ | ||
210 | struct scic_sds_phy { | ||
211 | struct sci_base_phy parent; | ||
212 | |||
213 | /** | ||
214 | * This field specifies the port object that owns/contains this phy. | ||
215 | */ | ||
216 | struct scic_sds_port *owning_port; | ||
217 | |||
218 | /** | ||
219 | * This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s, | ||
220 | * or 6.0 Gb/s operation. | ||
221 | */ | ||
222 | enum sci_sas_link_rate max_negotiated_speed; | ||
223 | |||
224 | /** | ||
225 | * This member specifies the protocol being utilized on this phy. This | ||
226 | * field contains a legitamite value once the PHY has link trained with | ||
227 | * a remote phy. | ||
228 | */ | ||
229 | enum SCIC_SDS_PHY_PROTOCOL protocol; | ||
230 | |||
231 | /** | ||
232 | * This field specifies the index with which this phy is associated (0-3). | ||
233 | */ | ||
234 | u8 phy_index; | ||
235 | |||
236 | /** | ||
237 | * This member indicates if this particular PHY has received a BCN while | ||
238 | * it had no port assignement. This BCN will be reported once the phy is | ||
239 | * assigned to a port. | ||
240 | */ | ||
241 | bool bcn_received_while_port_unassigned; | ||
242 | |||
243 | /** | ||
244 | * This field indicates if this PHY is currently in the process of | ||
245 | * link training (i.e. it has started OOB, but has yet to perform | ||
246 | * IAF exchange/Signature FIS reception). | ||
247 | */ | ||
248 | bool is_in_link_training; | ||
249 | |||
250 | union { | ||
251 | struct { | ||
252 | struct sci_sas_identify_address_frame identify_address_frame_buffer; | ||
253 | |||
254 | } sas; | ||
255 | |||
256 | struct { | ||
257 | struct sata_fis_reg_d2h signature_fis_buffer; | ||
258 | |||
259 | } sata; | ||
260 | |||
261 | } phy_type; | ||
262 | |||
263 | /** | ||
264 | * This field contains a reference to the timer utilized in detecting | ||
265 | * when a signature FIS timeout has occurred. The signature FIS is the | ||
266 | * first FIS sent by an attached SATA device after OOB/SN. | ||
267 | */ | ||
268 | void *sata_timeout_timer; | ||
269 | |||
270 | struct scic_sds_phy_state_handler *state_handlers; | ||
271 | |||
272 | struct sci_base_state_machine starting_substate_machine; | ||
273 | |||
274 | #ifdef SCIC_DEBUG_ENABLED | ||
275 | struct scic_sds_phy_state_record state_record; | ||
276 | #endif /* SCIC_DEBUG_ENABLED */ | ||
277 | |||
278 | /** | ||
279 | * This field points to the link layer register set within the SCU. | ||
280 | */ | ||
281 | struct scu_link_layer_registers *link_layer_registers; | ||
282 | |||
283 | }; | ||
284 | |||
285 | |||
286 | typedef enum sci_status (*SCIC_SDS_PHY_EVENT_HANDLER_T)(struct scic_sds_phy *, u32); | ||
287 | typedef enum sci_status (*SCIC_SDS_PHY_FRAME_HANDLER_T)(struct scic_sds_phy *, u32); | ||
288 | typedef enum sci_status (*SCIC_SDS_PHY_POWER_HANDLER_T)(struct scic_sds_phy *); | ||
289 | |||
290 | /** | ||
291 | * struct scic_sds_phy_state_handler - | ||
292 | * | ||
293 | * | ||
294 | */ | ||
295 | struct scic_sds_phy_state_handler { | ||
296 | /** | ||
297 | * This is the struct sci_base_phy object state handlers. | ||
298 | */ | ||
299 | struct sci_base_phy_state_handler parent; | ||
300 | |||
301 | /** | ||
302 | * The state handler for unsolicited frames received from the SCU hardware. | ||
303 | */ | ||
304 | SCIC_SDS_PHY_FRAME_HANDLER_T frame_handler; | ||
305 | |||
306 | /** | ||
307 | * The state handler for events received from the SCU hardware. | ||
308 | */ | ||
309 | SCIC_SDS_PHY_EVENT_HANDLER_T event_handler; | ||
310 | |||
311 | /** | ||
312 | * The state handler for staggered spinup. | ||
313 | */ | ||
314 | SCIC_SDS_PHY_POWER_HANDLER_T consume_power_handler; | ||
315 | |||
316 | }; | ||
317 | |||
318 | extern struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[]; | ||
319 | extern const struct sci_base_state scic_sds_phy_state_table[]; | ||
320 | extern const struct sci_base_state scic_sds_phy_starting_substates[]; | ||
321 | extern struct scic_sds_phy_state_handler | ||
322 | scic_sds_phy_starting_substate_handler_table[]; | ||
323 | |||
324 | |||
325 | /** | ||
326 | * scic_sds_phy_get_index() - | ||
327 | * | ||
328 | * This macro returns the phy index for the specified phy | ||
329 | */ | ||
330 | #define scic_sds_phy_get_index(phy) \ | ||
331 | ((phy)->phy_index) | ||
332 | |||
333 | /** | ||
334 | * scic_sds_phy_get_controller() - This macro returns the controller for this | ||
335 | * phy | ||
336 | * | ||
337 | * | ||
338 | */ | ||
339 | #define scic_sds_phy_get_controller(phy) \ | ||
340 | (scic_sds_port_get_controller((phy)->owning_port)) | ||
341 | |||
342 | /** | ||
343 | * scic_sds_phy_get_base_state_machine() - This macro returns the state machine | ||
344 | * for the base phy | ||
345 | * | ||
346 | * | ||
347 | */ | ||
348 | #define scic_sds_phy_get_base_state_machine(phy) \ | ||
349 | (&(phy)->parent.state_machine) | ||
350 | |||
351 | /** | ||
352 | * scic_sds_phy_get_starting_substate_machine() - This macro returns the | ||
353 | * starting substate machine for this phy | ||
354 | * | ||
355 | * | ||
356 | */ | ||
357 | #define scic_sds_phy_get_starting_substate_machine(phy) \ | ||
358 | (&(phy)->starting_substate_machine) | ||
359 | |||
360 | /** | ||
361 | * scic_sds_phy_set_state_handlers() - This macro sets the state handlers for | ||
362 | * this phy object | ||
363 | * | ||
364 | * | ||
365 | */ | ||
366 | #define scic_sds_phy_set_state_handlers(phy, handlers) \ | ||
367 | ((phy)->state_handlers = (handlers)) | ||
368 | |||
369 | /** | ||
370 | * scic_sds_phy_set_base_state_handlers() - | ||
371 | * | ||
372 | * This macro set the base state handlers for the phy object. | ||
373 | */ | ||
374 | #define scic_sds_phy_set_base_state_handlers(phy, state_id) \ | ||
375 | scic_sds_phy_set_state_handlers(\ | ||
376 | (phy), \ | ||
377 | &scic_sds_phy_state_handler_table[(state_id)] \ | ||
378 | ) | ||
379 | |||
380 | /** | ||
381 | * scic_sds_phy_is_ready() - | ||
382 | * | ||
383 | * This macro returns true if the current base state for this phy is | ||
384 | * SCI_BASE_PHY_STATE_READY | ||
385 | */ | ||
386 | #define scic_sds_phy_is_ready(phy) \ | ||
387 | (\ | ||
388 | SCI_BASE_PHY_STATE_READY \ | ||
389 | == sci_base_state_machine_get_state(\ | ||
390 | scic_sds_phy_get_base_state_machine(phy) \ | ||
391 | ) \ | ||
392 | ) | ||
393 | |||
394 | /* --------------------------------------------------------------------------- */ | ||
395 | |||
396 | |||
397 | |||
398 | |||
399 | /* --------------------------------------------------------------------------- */ | ||
400 | |||
401 | void scic_sds_phy_construct( | ||
402 | struct scic_sds_phy *this_phy, | ||
403 | struct scic_sds_port *owning_port, | ||
404 | u8 phy_index); | ||
405 | |||
406 | struct scic_sds_port *scic_sds_phy_get_port( | ||
407 | struct scic_sds_phy *this_phy); | ||
408 | |||
409 | void scic_sds_phy_set_port( | ||
410 | struct scic_sds_phy *this_phy, | ||
411 | struct scic_sds_port *owning_port); | ||
412 | |||
413 | enum sci_status scic_sds_phy_initialize( | ||
414 | struct scic_sds_phy *this_phy, | ||
415 | struct scu_link_layer_registers *link_layer_registers); | ||
416 | |||
417 | enum sci_status scic_sds_phy_start( | ||
418 | struct scic_sds_phy *this_phy); | ||
419 | |||
420 | enum sci_status scic_sds_phy_stop( | ||
421 | struct scic_sds_phy *this_phy); | ||
422 | |||
423 | enum sci_status scic_sds_phy_reset( | ||
424 | struct scic_sds_phy *this_phy); | ||
425 | |||
426 | /* --------------------------------------------------------------------------- */ | ||
427 | |||
428 | void scic_sds_phy_suspend( | ||
429 | struct scic_sds_phy *this_phy); | ||
430 | |||
431 | void scic_sds_phy_resume( | ||
432 | struct scic_sds_phy *this_phy); | ||
433 | |||
434 | /* --------------------------------------------------------------------------- */ | ||
435 | |||
436 | enum sci_status scic_sds_phy_event_handler( | ||
437 | struct scic_sds_phy *this_phy, | ||
438 | u32 event_code); | ||
439 | |||
440 | enum sci_status scic_sds_phy_frame_handler( | ||
441 | struct scic_sds_phy *this_phy, | ||
442 | u32 frame_index); | ||
443 | |||
444 | enum sci_status scic_sds_phy_consume_power_handler( | ||
445 | struct scic_sds_phy *this_phy); | ||
446 | |||
447 | void scic_sds_phy_get_sas_address( | ||
448 | struct scic_sds_phy *this_phy, | ||
449 | struct sci_sas_address *sas_address); | ||
450 | |||
451 | void scic_sds_phy_get_attached_sas_address( | ||
452 | struct scic_sds_phy *this_phy, | ||
453 | struct sci_sas_address *sas_address); | ||
454 | |||
455 | void scic_sds_phy_get_protocols( | ||
456 | struct scic_sds_phy *this_phy, | ||
457 | struct sci_sas_identify_address_frame_protocols *protocols); | ||
458 | |||
459 | void scic_sds_phy_get_attached_phy_protocols( | ||
460 | struct scic_sds_phy *this_phy, | ||
461 | struct sci_sas_identify_address_frame_protocols *protocols); | ||
462 | |||
463 | /* | ||
464 | * ****************************************************************************- | ||
465 | * * SCIC SDS PHY Handler Methods | ||
466 | * ****************************************************************************- */ | ||
467 | |||
468 | enum sci_status scic_sds_phy_default_start_handler( | ||
469 | struct sci_base_phy *phy); | ||
470 | |||
471 | enum sci_status scic_sds_phy_default_stop_handler( | ||
472 | struct sci_base_phy *phy); | ||
473 | |||
474 | enum sci_status scic_sds_phy_default_reset_handler( | ||
475 | struct sci_base_phy *phy); | ||
476 | |||
477 | enum sci_status scic_sds_phy_default_destroy_handler( | ||
478 | struct sci_base_phy *phy); | ||
479 | |||
480 | enum sci_status scic_sds_phy_default_frame_handler( | ||
481 | struct scic_sds_phy *phy, | ||
482 | u32 frame_index); | ||
483 | |||
484 | enum sci_status scic_sds_phy_default_event_handler( | ||
485 | struct scic_sds_phy *phy, | ||
486 | u32 evnet_code); | ||
487 | |||
488 | enum sci_status scic_sds_phy_default_consume_power_handler( | ||
489 | struct scic_sds_phy *phy); | ||
490 | |||
491 | #endif /* _SCIC_SDS_PHY_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h new file mode 100644 index 000000000000..7883819035da --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_PHY_REGISTERS_H_ | ||
57 | #define _SCIC_SDS_PHY_REGISTERS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the macros used by the phy object to read/write to the | ||
61 | * SCU link layer registers. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "scic_sds_controller.h" | ||
67 | |||
68 | /* | ||
69 | * ***************************************************************************** | ||
70 | * * SCU LINK LAYER REGISTER OPERATIONS | ||
71 | * ***************************************************************************** */ | ||
72 | |||
73 | /** | ||
74 | * scu_link_layer_register_read() - | ||
75 | * | ||
76 | * THis macro requests the SCU register write for the specified link layer | ||
77 | * register. | ||
78 | */ | ||
79 | #define scu_link_layer_register_read(phy, reg) \ | ||
80 | scu_register_read(\ | ||
81 | scic_sds_phy_get_controller(phy), \ | ||
82 | (phy)->link_layer_registers->reg \ | ||
83 | ) | ||
84 | |||
85 | /** | ||
86 | * scu_link_layer_register_write() - | ||
87 | * | ||
88 | * This macro requests the SCU register read for the specified link layer | ||
89 | * register. | ||
90 | */ | ||
91 | #define scu_link_layer_register_write(phy, reg, value) \ | ||
92 | scu_register_write(\ | ||
93 | scic_sds_phy_get_controller(phy), \ | ||
94 | (phy)->link_layer_registers->reg, \ | ||
95 | (value) \ | ||
96 | ) | ||
97 | |||
98 | /* | ||
99 | * ***************************************************************************** | ||
100 | * * SCU LINK LAYER REGISTERS | ||
101 | * ***************************************************************************** */ | ||
102 | |||
103 | /* / This macro reads from the SAS Identify Frame PHY Identifier register */ | ||
104 | #define SCU_SAS_TIPID_READ(phy) \ | ||
105 | scu_link_layer_register_read(phy, identify_frame_phy_id) | ||
106 | |||
107 | /* / This macro writes to the SAS Identify Frame PHY Identifier register */ | ||
108 | #define SCU_SAS_TIPID_WRITE(phy, value) \ | ||
109 | scu_link_layer_register_write(phy, identify_frame_phy_id, value) | ||
110 | |||
111 | /* / This macro reads from the SAS Identification register */ | ||
112 | #define SCU_SAS_TIID_READ(phy) \ | ||
113 | scu_link_layer_register_read(phy, transmit_identification) | ||
114 | |||
115 | /* / This macro writes to the SAS Identification register */ | ||
116 | #define SCU_SAS_TIID_WRITE(phy, value) \ | ||
117 | scu_link_layer_register_write(phy, transmit_identification, value) | ||
118 | |||
119 | /* / This macro reads the SAS Device Name High register */ | ||
120 | #define SCU_SAS_TIDNH_READ(phy) \ | ||
121 | scu_link_layer_register_read(phy, sas_device_name_high) | ||
122 | |||
123 | /* / This macro writes the SAS Device Name High register */ | ||
124 | #define SCU_SAS_TIDNH_WRITE(phy, value) \ | ||
125 | scu_link_layer_register_write(phy, sas_device_name_high, value) | ||
126 | |||
127 | /* / This macro reads the SAS Device Name Low register */ | ||
128 | #define SCU_SAS_TIDNL_READ(phy) \ | ||
129 | scu_link_layer_register_read(phy, sas_device_name_low) | ||
130 | |||
131 | /* / This macro writes the SAS Device Name Low register */ | ||
132 | #define SCU_SAS_TIDNL_WRITE(phy, value) \ | ||
133 | scu_link_layer_register_write(phy, sas_device_name_low, value) | ||
134 | |||
135 | /* / This macro reads the Source SAS Address High register */ | ||
136 | #define SCU_SAS_TISSAH_READ(phy) \ | ||
137 | scu_link_layer_register_read(phy, source_sas_address_high) | ||
138 | |||
139 | /* / This macro writes the Source SAS Address High register */ | ||
140 | #define SCU_SAS_TISSAH_WRITE(phy, value) \ | ||
141 | scu_link_layer_register_write(phy, source_sas_address_high, value) | ||
142 | |||
143 | /* / This macro reads the Source SAS Address Low register */ | ||
144 | #define SCU_SAS_TISSAL_READ(phy) \ | ||
145 | scu_link_layer_register_read(phy, source_sas_address_low) | ||
146 | |||
147 | /* / This macro writes the Source SAS Address Low register */ | ||
148 | #define SCU_SAS_TISSAL_WRITE(phy, value) \ | ||
149 | scu_link_layer_register_write(phy, source_sas_address_low, value) | ||
150 | |||
151 | /* / This macro reads the PHY Configuration register */ | ||
152 | #define SCU_SAS_PCFG_READ(phy) \ | ||
153 | scu_link_layer_register_read(phy, phy_configuration); | ||
154 | |||
155 | /* / This macro writes the PHY Configuration register */ | ||
156 | #define SCU_SAS_PCFG_WRITE(phy, value) \ | ||
157 | scu_link_layer_register_write(phy, phy_configuration, value) | ||
158 | |||
159 | /* / This macro reads the PHY Enable Spinup register */ | ||
160 | #define SCU_SAS_ENSPINUP_READ(phy) \ | ||
161 | scu_link_layer_register_read(phy, notify_enable_spinup_control) | ||
162 | |||
163 | /* / This macro writes the PHY Enable Spinup register */ | ||
164 | #define SCU_SAS_ENSPINUP_WRITE(phy, value) \ | ||
165 | scu_link_layer_register_write(phy, notify_enable_spinup_control, value) | ||
166 | |||
167 | /* / This macro reads the PHY Capacity register */ | ||
168 | #define SCU_SAS_PHYCAP_READ(phy) \ | ||
169 | scu_link_layer_register_read(phy, phy_capabilities) | ||
170 | |||
171 | /* / This macro writes the PHY Capacity register */ | ||
172 | #define SCU_SAS_PHYCAP_WRITE(phy, value) \ | ||
173 | scu_link_layer_register_write(phy, phy_capabilities, value) | ||
174 | |||
175 | /* / This macro reads the Recieved PHY Capacity register */ | ||
176 | #define SCU_SAS_RECPHYCAP_READ(phy) \ | ||
177 | scu_link_layer_register_read(phy, receive_phycap) | ||
178 | |||
179 | /* / This macro reads the link layer control register */ | ||
180 | #define SCU_SAS_LLCTL_READ(phy) \ | ||
181 | scu_link_layer_register_read(phy, link_layer_control); | ||
182 | |||
183 | /* / This macro writes the link layer control register */ | ||
184 | #define SCU_SAS_LLCTL_WRITE(phy, value) \ | ||
185 | scu_link_layer_register_write(phy, link_layer_control, value); | ||
186 | |||
187 | #endif /* _SCIC_SDS_PHY_REGISTERS_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_port.c b/drivers/scsi/isci/core/scic_sds_port.c new file mode 100644 index 000000000000..1af38505840c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port.c | |||
@@ -0,0 +1,2757 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "intel_sas.h" | ||
57 | #include "sci_base_port.h" | ||
58 | #include "scic_controller.h" | ||
59 | #include "scic_phy.h" | ||
60 | #include "scic_port.h" | ||
61 | #include "scic_sds_controller.h" | ||
62 | #include "scic_sds_phy.h" | ||
63 | #include "scic_sds_phy_registers.h" | ||
64 | #include "scic_sds_port.h" | ||
65 | #include "scic_sds_port_registers.h" | ||
66 | #include "scic_sds_remote_device.h" | ||
67 | #include "scic_sds_remote_node_context.h" | ||
68 | #include "scic_sds_request.h" | ||
69 | #include "scic_user_callback.h" | ||
70 | #include "sci_environment.h" | ||
71 | |||
72 | |||
73 | static void scic_sds_port_invalid_link_up( | ||
74 | struct scic_sds_port *this_port, | ||
75 | struct scic_sds_phy *phy); | ||
76 | static void scic_sds_port_timeout_handler( | ||
77 | void *port); | ||
78 | #define SCIC_SDS_PORT_MIN_TIMER_COUNT (SCI_MAX_PORTS) | ||
79 | #define SCIC_SDS_PORT_MAX_TIMER_COUNT (SCI_MAX_PORTS) | ||
80 | |||
81 | #define SCIC_SDS_PORT_HARD_RESET_TIMEOUT (1000) | ||
82 | |||
83 | void sci_base_port_construct( | ||
84 | struct sci_base_port *base_port, | ||
85 | const struct sci_base_state *state_table) | ||
86 | { | ||
87 | base_port->parent.private = NULL; | ||
88 | sci_base_state_machine_construct( | ||
89 | &base_port->state_machine, | ||
90 | &base_port->parent, | ||
91 | state_table, | ||
92 | SCI_BASE_PORT_STATE_STOPPED | ||
93 | ); | ||
94 | |||
95 | sci_base_state_machine_start( | ||
96 | &base_port->state_machine | ||
97 | ); | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * | ||
102 | * @this_port: This is the port object to which the phy is being assigned. | ||
103 | * @phy_index: This is the phy index that is being assigned to the port. | ||
104 | * | ||
105 | * This method will return a true value if the specified phy can be assigned to | ||
106 | * this port The following is a list of phys for each port that are allowed: - | ||
107 | * Port 0 - 3 2 1 0 - Port 1 - 1 - Port 2 - 3 2 - Port 3 - 3 This method | ||
108 | * doesn't preclude all configurations. It merely ensures that a phy is part | ||
109 | * of the allowable set of phy identifiers for that port. For example, one | ||
110 | * could assign phy 3 to port 0 and no other phys. Please refer to | ||
111 | * scic_sds_port_is_phy_mask_valid() for information regarding whether the | ||
112 | * phy_mask for a port can be supported. bool true if this is a valid phy | ||
113 | * assignment for the port false if this is not a valid phy assignment for the | ||
114 | * port | ||
115 | */ | ||
116 | bool scic_sds_port_is_valid_phy_assignment( | ||
117 | struct scic_sds_port *this_port, | ||
118 | u32 phy_index) | ||
119 | { | ||
120 | /* Initialize to invalid value. */ | ||
121 | u32 existing_phy_index = SCI_MAX_PHYS; | ||
122 | u32 index; | ||
123 | |||
124 | if ((this_port->physical_port_index == 1) && (phy_index != 1)) { | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | if (this_port->physical_port_index == 3 && phy_index != 3) { | ||
129 | return false; | ||
130 | } | ||
131 | |||
132 | if ( | ||
133 | (this_port->physical_port_index == 2) | ||
134 | && ((phy_index == 0) || (phy_index == 1)) | ||
135 | ) { | ||
136 | return false; | ||
137 | } | ||
138 | |||
139 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
140 | if ((this_port->phy_table[index] != NULL) | ||
141 | && (index != phy_index)) { | ||
142 | existing_phy_index = index; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * Ensure that all of the phys in the port are capable of | ||
148 | * operating at the same maximum link rate. */ | ||
149 | if ( | ||
150 | (existing_phy_index < SCI_MAX_PHYS) | ||
151 | && (this_port->owning_controller->user_parameters.sds1.phys[ | ||
152 | phy_index].max_speed_generation != | ||
153 | this_port->owning_controller->user_parameters.sds1.phys[ | ||
154 | existing_phy_index].max_speed_generation) | ||
155 | ) | ||
156 | return false; | ||
157 | |||
158 | return true; | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * This method requests a list (mask) of the phys contained in the supplied SAS | ||
163 | * port. | ||
164 | * @this_port: a handle corresponding to the SAS port for which to return the | ||
165 | * phy mask. | ||
166 | * | ||
167 | * Return a bit mask indicating which phys are a part of this port. Each bit | ||
168 | * corresponds to a phy identifier (e.g. bit 0 = phy id 0). | ||
169 | */ | ||
170 | u32 scic_sds_port_get_phys(struct scic_sds_port *this_port) | ||
171 | { | ||
172 | u32 index; | ||
173 | u32 mask; | ||
174 | |||
175 | mask = 0; | ||
176 | |||
177 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
178 | if (this_port->phy_table[index] != NULL) { | ||
179 | mask |= (1 << index); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | return mask; | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * | ||
188 | * @this_port: This is the port object for which to determine if the phy mask | ||
189 | * can be supported. | ||
190 | * | ||
191 | * This method will return a true value if the port's phy mask can be supported | ||
192 | * by the SCU. The following is a list of valid PHY mask configurations for | ||
193 | * each port: - Port 0 - [[3 2] 1] 0 - Port 1 - [1] - Port 2 - [[3] 2] | ||
194 | * - Port 3 - [3] This method returns a boolean indication specifying if the | ||
195 | * phy mask can be supported. true if this is a valid phy assignment for the | ||
196 | * port false if this is not a valid phy assignment for the port | ||
197 | */ | ||
198 | bool scic_sds_port_is_phy_mask_valid( | ||
199 | struct scic_sds_port *this_port, | ||
200 | u32 phy_mask) | ||
201 | { | ||
202 | if (this_port->physical_port_index == 0) { | ||
203 | if (((phy_mask & 0x0F) == 0x0F) | ||
204 | || ((phy_mask & 0x03) == 0x03) | ||
205 | || ((phy_mask & 0x01) == 0x01) | ||
206 | || (phy_mask == 0)) | ||
207 | return true; | ||
208 | } else if (this_port->physical_port_index == 1) { | ||
209 | if (((phy_mask & 0x02) == 0x02) | ||
210 | || (phy_mask == 0)) | ||
211 | return true; | ||
212 | } else if (this_port->physical_port_index == 2) { | ||
213 | if (((phy_mask & 0x0C) == 0x0C) | ||
214 | || ((phy_mask & 0x04) == 0x04) | ||
215 | || (phy_mask == 0)) | ||
216 | return true; | ||
217 | } else if (this_port->physical_port_index == 3) { | ||
218 | if (((phy_mask & 0x08) == 0x08) | ||
219 | || (phy_mask == 0)) | ||
220 | return true; | ||
221 | } | ||
222 | |||
223 | return false; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * | ||
228 | * @this_port: This parameter specifies the port from which to return a | ||
229 | * connected phy. | ||
230 | * | ||
231 | * This method retrieves a currently active (i.e. connected) phy contained in | ||
232 | * the port. Currently, the lowest order phy that is connected is returned. | ||
233 | * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is | ||
234 | * returned if there are no currently active (i.e. connected to a remote end | ||
235 | * point) phys contained in the port. All other values specify a struct scic_sds_phy | ||
236 | * object that is active in the port. | ||
237 | */ | ||
238 | static struct scic_sds_phy *scic_sds_port_get_a_connected_phy( | ||
239 | struct scic_sds_port *this_port | ||
240 | ) { | ||
241 | u32 index; | ||
242 | struct scic_sds_phy *phy; | ||
243 | |||
244 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
245 | /* | ||
246 | * Ensure that the phy is both part of the port and currently | ||
247 | * connected to the remote end-point. */ | ||
248 | phy = this_port->phy_table[index]; | ||
249 | if ( | ||
250 | (phy != NULL) | ||
251 | && scic_sds_port_active_phy(this_port, phy) | ||
252 | ) { | ||
253 | return phy; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | return NULL; | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * scic_sds_port_set_phy() - | ||
262 | * @out]: port The port object to which the phy assignement is being made. | ||
263 | * @out]: phy The phy which is being assigned to the port. | ||
264 | * | ||
265 | * This method attempts to make the assignment of the phy to the port. If | ||
266 | * successful the phy is assigned to the ports phy table. bool true if the phy | ||
267 | * assignment can be made. false if the phy assignement can not be made. This | ||
268 | * is a functional test that only fails if the phy is currently assigned to a | ||
269 | * different port. | ||
270 | */ | ||
271 | enum sci_status scic_sds_port_set_phy( | ||
272 | struct scic_sds_port *port, | ||
273 | struct scic_sds_phy *phy) | ||
274 | { | ||
275 | /* | ||
276 | * Check to see if we can add this phy to a port | ||
277 | * that means that the phy is not part of a port and that the port does | ||
278 | * not already have a phy assinged to the phy index. */ | ||
279 | if ( | ||
280 | (port->phy_table[phy->phy_index] == SCI_INVALID_HANDLE) | ||
281 | && (scic_sds_phy_get_port(phy) == SCI_INVALID_HANDLE) | ||
282 | && scic_sds_port_is_valid_phy_assignment(port, phy->phy_index) | ||
283 | ) { | ||
284 | /* | ||
285 | * Phy is being added in the stopped state so we are in MPC mode | ||
286 | * make logical port index = physical port index */ | ||
287 | port->logical_port_index = port->physical_port_index; | ||
288 | port->phy_table[phy->phy_index] = phy; | ||
289 | scic_sds_phy_set_port(phy, port); | ||
290 | |||
291 | return SCI_SUCCESS; | ||
292 | } | ||
293 | |||
294 | return SCI_FAILURE; | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * scic_sds_port_clear_phy() - | ||
299 | * @out]: port The port from which the phy is being cleared. | ||
300 | * @out]: phy The phy being cleared from the port. | ||
301 | * | ||
302 | * This method will clear the phy assigned to this port. This method fails if | ||
303 | * this phy is not currently assinged to this port. bool true if the phy is | ||
304 | * removed from the port. false if this phy is not assined to this port. | ||
305 | */ | ||
306 | enum sci_status scic_sds_port_clear_phy( | ||
307 | struct scic_sds_port *port, | ||
308 | struct scic_sds_phy *phy) | ||
309 | { | ||
310 | /* Make sure that this phy is part of this port */ | ||
311 | if ( | ||
312 | (port->phy_table[phy->phy_index] == phy) | ||
313 | && (scic_sds_phy_get_port(phy) == port) | ||
314 | ) { | ||
315 | /* Yep it is assigned to this port so remove it */ | ||
316 | scic_sds_phy_set_port( | ||
317 | phy, | ||
318 | &scic_sds_port_get_controller(port)->port_table[SCI_MAX_PORTS] | ||
319 | ); | ||
320 | |||
321 | port->phy_table[phy->phy_index] = SCI_INVALID_HANDLE; | ||
322 | |||
323 | return SCI_SUCCESS; | ||
324 | } | ||
325 | |||
326 | return SCI_FAILURE; | ||
327 | } | ||
328 | |||
329 | /** | ||
330 | * scic_sds_port_add_phy() - | ||
331 | * @this_port: This parameter specifies the port in which the phy will be added. | ||
332 | * @the_phy: This parameter is the phy which is to be added to the port. | ||
333 | * | ||
334 | * This method will add a PHY to the selected port. This method returns an | ||
335 | * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other status | ||
336 | * is failre to add the phy to the port. | ||
337 | */ | ||
338 | enum sci_status scic_sds_port_add_phy( | ||
339 | struct scic_sds_port *this_port, | ||
340 | struct scic_sds_phy *the_phy) | ||
341 | { | ||
342 | return this_port->state_handlers->parent.add_phy_handler( | ||
343 | &this_port->parent, &the_phy->parent); | ||
344 | } | ||
345 | |||
346 | |||
347 | /** | ||
348 | * scic_sds_port_remove_phy() - | ||
349 | * @this_port: This parameter specifies the port in which the phy will be added. | ||
350 | * @the_phy: This parameter is the phy which is to be added to the port. | ||
351 | * | ||
352 | * This method will remove the PHY from the selected PORT. This method returns | ||
353 | * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any other | ||
354 | * status is failre to add the phy to the port. | ||
355 | */ | ||
356 | enum sci_status scic_sds_port_remove_phy( | ||
357 | struct scic_sds_port *this_port, | ||
358 | struct scic_sds_phy *the_phy) | ||
359 | { | ||
360 | return this_port->state_handlers->parent.remove_phy_handler( | ||
361 | &this_port->parent, &the_phy->parent); | ||
362 | } | ||
363 | |||
364 | /** | ||
365 | * This method requests the SAS address for the supplied SAS port from the SCI | ||
366 | * implementation. | ||
367 | * @this_port: a handle corresponding to the SAS port for which to return the | ||
368 | * SAS address. | ||
369 | * @sas_address: This parameter specifies a pointer to a SAS address structure | ||
370 | * into which the core will copy the SAS address for the port. | ||
371 | * | ||
372 | */ | ||
373 | void scic_sds_port_get_sas_address( | ||
374 | struct scic_sds_port *this_port, | ||
375 | struct sci_sas_address *sas_address) | ||
376 | { | ||
377 | u32 index; | ||
378 | |||
379 | sas_address->high = 0; | ||
380 | sas_address->low = 0; | ||
381 | |||
382 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
383 | if (this_port->phy_table[index] != NULL) { | ||
384 | scic_sds_phy_get_sas_address(this_port->phy_table[index], sas_address); | ||
385 | } | ||
386 | } | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * This method will indicate which protocols are supported by this port. | ||
391 | * @this_port: a handle corresponding to the SAS port for which to return the | ||
392 | * supported protocols. | ||
393 | * @protocols: This parameter specifies a pointer to an IAF protocol field | ||
394 | * structure into which the core will copy the protocol values for the port. | ||
395 | * The values are returned as part of a bit mask in order to allow for | ||
396 | * multi-protocol support. | ||
397 | * | ||
398 | */ | ||
399 | static void scic_sds_port_get_protocols( | ||
400 | struct scic_sds_port *this_port, | ||
401 | struct sci_sas_identify_address_frame_protocols *protocols) | ||
402 | { | ||
403 | u8 index; | ||
404 | |||
405 | protocols->u.all = 0; | ||
406 | |||
407 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
408 | if (this_port->phy_table[index] != NULL) { | ||
409 | scic_sds_phy_get_protocols(this_port->phy_table[index], protocols); | ||
410 | } | ||
411 | } | ||
412 | } | ||
413 | |||
414 | /** | ||
415 | * This method requests the SAS address for the device directly attached to | ||
416 | * this SAS port. | ||
417 | * @this_port: a handle corresponding to the SAS port for which to return the | ||
418 | * SAS address. | ||
419 | * @sas_address: This parameter specifies a pointer to a SAS address structure | ||
420 | * into which the core will copy the SAS address for the device directly | ||
421 | * attached to the port. | ||
422 | * | ||
423 | */ | ||
424 | void scic_sds_port_get_attached_sas_address( | ||
425 | struct scic_sds_port *this_port, | ||
426 | struct sci_sas_address *sas_address) | ||
427 | { | ||
428 | struct sci_sas_identify_address_frame_protocols protocols; | ||
429 | struct scic_sds_phy *phy; | ||
430 | |||
431 | /* | ||
432 | * Ensure that the phy is both part of the port and currently | ||
433 | * connected to the remote end-point. */ | ||
434 | phy = scic_sds_port_get_a_connected_phy(this_port); | ||
435 | if (phy != NULL) { | ||
436 | scic_sds_phy_get_attached_phy_protocols(phy, &protocols); | ||
437 | |||
438 | if (!protocols.u.bits.stp_target) { | ||
439 | scic_sds_phy_get_attached_sas_address(phy, sas_address); | ||
440 | } else { | ||
441 | scic_sds_phy_get_sas_address(phy, sas_address); | ||
442 | sas_address->low += phy->phy_index; | ||
443 | } | ||
444 | } else { | ||
445 | sas_address->high = 0; | ||
446 | sas_address->low = 0; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | /** | ||
451 | * This method will indicate which protocols are supported by this remote | ||
452 | * device. | ||
453 | * @this_port: a handle corresponding to the SAS port for which to return the | ||
454 | * supported protocols. | ||
455 | * @protocols: This parameter specifies a pointer to an IAF protocol field | ||
456 | * structure into which the core will copy the protocol values for the port. | ||
457 | * The values are returned as part of a bit mask in order to allow for | ||
458 | * multi-protocol support. | ||
459 | * | ||
460 | */ | ||
461 | void scic_sds_port_get_attached_protocols( | ||
462 | struct scic_sds_port *this_port, | ||
463 | struct sci_sas_identify_address_frame_protocols *protocols) | ||
464 | { | ||
465 | struct scic_sds_phy *phy; | ||
466 | |||
467 | /* | ||
468 | * Ensure that the phy is both part of the port and currently | ||
469 | * connected to the remote end-point. */ | ||
470 | phy = scic_sds_port_get_a_connected_phy(this_port); | ||
471 | if (phy != NULL) | ||
472 | scic_sds_phy_get_attached_phy_protocols(phy, protocols); | ||
473 | else | ||
474 | protocols->u.all = 0; | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * This method returns the amount of memory requred for a port object. | ||
479 | * | ||
480 | * u32 | ||
481 | */ | ||
482 | |||
483 | /** | ||
484 | * This method returns the minimum number of timers required for all port | ||
485 | * objects. | ||
486 | * | ||
487 | * u32 | ||
488 | */ | ||
489 | |||
490 | /** | ||
491 | * This method returns the maximum number of timers required for all port | ||
492 | * objects. | ||
493 | * | ||
494 | * u32 | ||
495 | */ | ||
496 | |||
497 | /** | ||
498 | * | ||
499 | * @this_port: | ||
500 | * @port_index: | ||
501 | * | ||
502 | * | ||
503 | */ | ||
504 | void scic_sds_port_construct( | ||
505 | struct scic_sds_port *this_port, | ||
506 | u8 port_index, | ||
507 | struct scic_sds_controller *owning_controller) | ||
508 | { | ||
509 | u32 index; | ||
510 | |||
511 | sci_base_port_construct( | ||
512 | &this_port->parent, | ||
513 | scic_sds_port_state_table | ||
514 | ); | ||
515 | |||
516 | sci_base_state_machine_construct( | ||
517 | scic_sds_port_get_ready_substate_machine(this_port), | ||
518 | &this_port->parent.parent, | ||
519 | scic_sds_port_ready_substate_table, | ||
520 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING | ||
521 | ); | ||
522 | |||
523 | this_port->logical_port_index = SCIC_SDS_DUMMY_PORT; | ||
524 | this_port->physical_port_index = port_index; | ||
525 | this_port->active_phy_mask = 0; | ||
526 | |||
527 | this_port->owning_controller = owning_controller; | ||
528 | |||
529 | this_port->started_request_count = 0; | ||
530 | this_port->assigned_device_count = 0; | ||
531 | |||
532 | this_port->timer_handle = SCI_INVALID_HANDLE; | ||
533 | |||
534 | this_port->transport_layer_registers = NULL; | ||
535 | this_port->port_task_scheduler_registers = NULL; | ||
536 | |||
537 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
538 | this_port->phy_table[index] = NULL; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | /** | ||
543 | * This method performs initialization of the supplied port. Initialization | ||
544 | * includes: - state machine initialization - member variable initialization | ||
545 | * - configuring the phy_mask | ||
546 | * @this_port: | ||
547 | * @transport_layer_registers: | ||
548 | * @port_task_scheduler_registers: | ||
549 | * @port_configuration_regsiter: | ||
550 | * | ||
551 | * enum sci_status SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This value is returned | ||
552 | * if the phy being added to the port | ||
553 | */ | ||
554 | enum sci_status scic_sds_port_initialize( | ||
555 | struct scic_sds_port *this_port, | ||
556 | void *transport_layer_registers, | ||
557 | void *port_task_scheduler_registers, | ||
558 | void *port_configuration_regsiter, | ||
559 | void *viit_registers) | ||
560 | { | ||
561 | u32 tl_control; | ||
562 | |||
563 | this_port->transport_layer_registers = transport_layer_registers; | ||
564 | this_port->port_task_scheduler_registers = port_task_scheduler_registers; | ||
565 | this_port->port_pe_configuration_register = port_configuration_regsiter; | ||
566 | this_port->viit_registers = viit_registers; | ||
567 | |||
568 | scic_sds_port_set_direct_attached_device_id( | ||
569 | this_port, | ||
570 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | ||
571 | ); | ||
572 | |||
573 | /* | ||
574 | * Hardware team recommends that we enable the STP prefetch | ||
575 | * for all ports */ | ||
576 | tl_control = SCU_TLCR_READ(this_port); | ||
577 | tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH); | ||
578 | SCU_TLCR_WRITE(this_port, tl_control); | ||
579 | |||
580 | /* | ||
581 | * If this is not the dummy port make the assignment of | ||
582 | * the timer and start the state machine */ | ||
583 | if (this_port->physical_port_index != SCI_MAX_PORTS) { | ||
584 | /* / @todo should we create the timer at create time? */ | ||
585 | this_port->timer_handle = scic_cb_timer_create( | ||
586 | scic_sds_port_get_controller(this_port), | ||
587 | scic_sds_port_timeout_handler, | ||
588 | this_port | ||
589 | ); | ||
590 | |||
591 | } else { | ||
592 | /* | ||
593 | * Force the dummy port into a condition where it rejects all requests | ||
594 | * as its in an invalid state for any operation. | ||
595 | * / @todo should we set a set of specical handlers for the dummy port? */ | ||
596 | scic_sds_port_set_base_state_handlers( | ||
597 | this_port, SCI_BASE_PORT_STATE_STOPPED | ||
598 | ); | ||
599 | } | ||
600 | |||
601 | return SCI_SUCCESS; | ||
602 | } | ||
603 | |||
604 | /** | ||
605 | * | ||
606 | * @this_port: This is the struct scic_sds_port object for which has a phy that has | ||
607 | * gone link up. | ||
608 | * @the_phy: This is the struct scic_sds_phy object that has gone link up. | ||
609 | * @do_notify_user: This parameter specifies whether to inform the user (via | ||
610 | * scic_cb_port_link_up()) as to the fact that a new phy as become ready. | ||
611 | * | ||
612 | * This method is the a general link up handler for the struct scic_sds_port object. | ||
613 | * This function will determine if this struct scic_sds_phy can be assigned to this | ||
614 | * struct scic_sds_port object. If the struct scic_sds_phy object can is not a valid PHY for | ||
615 | * this port then the function will notify the SCIC_USER. A PHY can only be | ||
616 | * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in | ||
617 | * the same port. none | ||
618 | */ | ||
619 | void scic_sds_port_general_link_up_handler( | ||
620 | struct scic_sds_port *this_port, | ||
621 | struct scic_sds_phy *the_phy, | ||
622 | bool do_notify_user) | ||
623 | { | ||
624 | struct sci_sas_address port_sas_address; | ||
625 | struct sci_sas_address phy_sas_address; | ||
626 | |||
627 | scic_sds_port_get_attached_sas_address(this_port, &port_sas_address); | ||
628 | scic_sds_phy_get_attached_sas_address(the_phy, &phy_sas_address); | ||
629 | |||
630 | /* | ||
631 | * If the SAS address of the new phy matches the SAS address of | ||
632 | * other phys in the port OR this is the first phy in the port, | ||
633 | * then activate the phy and allow it to be used for operations | ||
634 | * in this port. */ | ||
635 | if ( | ||
636 | ( | ||
637 | (phy_sas_address.high == port_sas_address.high) | ||
638 | && (phy_sas_address.low == port_sas_address.low) | ||
639 | ) | ||
640 | || (this_port->active_phy_mask == 0) | ||
641 | ) { | ||
642 | scic_sds_port_activate_phy(this_port, the_phy, do_notify_user); | ||
643 | |||
644 | if (this_port->parent.state_machine.current_state_id | ||
645 | == SCI_BASE_PORT_STATE_RESETTING) { | ||
646 | sci_base_state_machine_change_state( | ||
647 | &this_port->parent.state_machine, SCI_BASE_PORT_STATE_READY | ||
648 | ); | ||
649 | } | ||
650 | } else { | ||
651 | scic_sds_port_invalid_link_up(this_port, the_phy); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | |||
656 | enum sci_status scic_port_start(struct scic_sds_port *port) | ||
657 | { | ||
658 | return port->state_handlers->parent.start_handler(&port->parent); | ||
659 | } | ||
660 | |||
661 | |||
662 | enum sci_status scic_port_stop(struct scic_sds_port *port) | ||
663 | { | ||
664 | return port->state_handlers->parent.stop_handler(&port->parent); | ||
665 | } | ||
666 | |||
667 | |||
668 | enum sci_status scic_port_get_properties( | ||
669 | struct scic_sds_port *port, | ||
670 | struct scic_port_properties *prop) | ||
671 | { | ||
672 | if ((port == SCI_INVALID_HANDLE) || | ||
673 | (port->logical_port_index == SCIC_SDS_DUMMY_PORT)) | ||
674 | return SCI_FAILURE_INVALID_PORT; | ||
675 | |||
676 | prop->index = port->logical_port_index; | ||
677 | prop->phy_mask = scic_sds_port_get_phys(port); | ||
678 | scic_sds_port_get_sas_address(port, &prop->local.sas_address); | ||
679 | scic_sds_port_get_protocols(port, &prop->local.protocols); | ||
680 | scic_sds_port_get_attached_sas_address(port, &prop->remote.sas_address); | ||
681 | scic_sds_port_get_attached_protocols(port, &prop->remote.protocols); | ||
682 | |||
683 | return SCI_SUCCESS; | ||
684 | } | ||
685 | |||
686 | |||
687 | enum sci_status scic_port_hard_reset( | ||
688 | struct scic_sds_port *port, | ||
689 | u32 reset_timeout) | ||
690 | { | ||
691 | return port->state_handlers->parent.reset_handler( | ||
692 | &port->parent, reset_timeout); | ||
693 | } | ||
694 | |||
695 | /** | ||
696 | * | ||
697 | * @this_port: The port for which the direct attached device id is to be | ||
698 | * assigned. | ||
699 | * | ||
700 | * This method assigns the direct attached device ID for this port. | ||
701 | */ | ||
702 | void scic_sds_port_set_direct_attached_device_id( | ||
703 | struct scic_sds_port *this_port, | ||
704 | u32 device_id) | ||
705 | { | ||
706 | u32 tl_control; | ||
707 | |||
708 | SCU_STPTLDARNI_WRITE(this_port, device_id); | ||
709 | |||
710 | /* | ||
711 | * The read should guarntee that the first write gets posted | ||
712 | * before the next write */ | ||
713 | tl_control = SCU_TLCR_READ(this_port); | ||
714 | tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); | ||
715 | SCU_TLCR_WRITE(this_port, tl_control); | ||
716 | } | ||
717 | |||
718 | |||
719 | /** | ||
720 | * | ||
721 | * @this_port: This is the port on which the phy should be enabled. | ||
722 | * @the_phy: This is the specific phy which to enable. | ||
723 | * @do_notify_user: This parameter specifies whether to inform the user (via | ||
724 | * scic_cb_port_link_up()) as to the fact that a new phy as become ready. | ||
725 | * | ||
726 | * This method will activate the phy in the port. Activation includes: - adding | ||
727 | * the phy to the port - enabling the Protocol Engine in the silicon. - | ||
728 | * notifying the user that the link is up. none | ||
729 | */ | ||
730 | void scic_sds_port_activate_phy( | ||
731 | struct scic_sds_port *this_port, | ||
732 | struct scic_sds_phy *the_phy, | ||
733 | bool do_notify_user) | ||
734 | { | ||
735 | struct scic_sds_controller *controller; | ||
736 | struct sci_sas_identify_address_frame_protocols protocols; | ||
737 | |||
738 | controller = scic_sds_port_get_controller(this_port); | ||
739 | scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); | ||
740 | |||
741 | /* If this is sata port then the phy has already been resumed */ | ||
742 | if (!protocols.u.bits.stp_target) { | ||
743 | scic_sds_phy_resume(the_phy); | ||
744 | } | ||
745 | |||
746 | this_port->active_phy_mask |= 1 << the_phy->phy_index; | ||
747 | |||
748 | scic_sds_controller_clear_invalid_phy(controller, the_phy); | ||
749 | |||
750 | if (do_notify_user == true) | ||
751 | scic_cb_port_link_up(this_port->owning_controller, this_port, the_phy); | ||
752 | } | ||
753 | |||
754 | /** | ||
755 | * | ||
756 | * @this_port: This is the port on which the phy should be deactivated. | ||
757 | * @the_phy: This is the specific phy that is no longer active in the port. | ||
758 | * @do_notify_user: This parameter specifies whether to inform the user (via | ||
759 | * scic_cb_port_link_down()) as to the fact that a new phy as become ready. | ||
760 | * | ||
761 | * This method will deactivate the supplied phy in the port. none | ||
762 | */ | ||
763 | void scic_sds_port_deactivate_phy( | ||
764 | struct scic_sds_port *this_port, | ||
765 | struct scic_sds_phy *the_phy, | ||
766 | bool do_notify_user) | ||
767 | { | ||
768 | this_port->active_phy_mask &= ~(1 << the_phy->phy_index); | ||
769 | |||
770 | the_phy->max_negotiated_speed = SCI_SAS_NO_LINK_RATE; | ||
771 | |||
772 | /* Re-assign the phy back to the LP as if it were a narrow port */ | ||
773 | SCU_PCSPExCR_WRITE(this_port, the_phy->phy_index, the_phy->phy_index); | ||
774 | |||
775 | if (do_notify_user == true) | ||
776 | scic_cb_port_link_down(this_port->owning_controller, this_port, the_phy); | ||
777 | } | ||
778 | |||
779 | /** | ||
780 | * | ||
781 | * @this_port: This is the port on which the phy should be disabled. | ||
782 | * @the_phy: This is the specific phy which to disabled. | ||
783 | * | ||
784 | * This method will disable the phy and report that the phy is not valid for | ||
785 | * this port object. None | ||
786 | */ | ||
787 | static void scic_sds_port_invalid_link_up( | ||
788 | struct scic_sds_port *this_port, | ||
789 | struct scic_sds_phy *the_phy) | ||
790 | { | ||
791 | struct scic_sds_controller *controller = scic_sds_port_get_controller(this_port); | ||
792 | |||
793 | /* | ||
794 | * Check to see if we have alreay reported this link as bad and if not go | ||
795 | * ahead and tell the SCI_USER that we have discovered an invalid link. */ | ||
796 | if ((controller->invalid_phy_mask & (1 << the_phy->phy_index)) == 0) { | ||
797 | scic_sds_controller_set_invalid_phy(controller, the_phy); | ||
798 | |||
799 | scic_cb_port_invalid_link_up(controller, this_port, the_phy); | ||
800 | } | ||
801 | } | ||
802 | |||
803 | /** | ||
804 | * This method returns false if the port only has a single phy object assigned. | ||
805 | * If there are no phys or more than one phy then the method will return | ||
806 | * true. | ||
807 | * @this_port: The port for which the wide port condition is to be checked. | ||
808 | * | ||
809 | * bool true Is returned if this is a wide ported port. false Is returned if | ||
810 | * this is a narrow port. | ||
811 | */ | ||
812 | static bool scic_sds_port_is_wide(struct scic_sds_port *this_port) | ||
813 | { | ||
814 | u32 index; | ||
815 | u32 phy_count = 0; | ||
816 | |||
817 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
818 | if (this_port->phy_table[index] != NULL) { | ||
819 | phy_count++; | ||
820 | } | ||
821 | } | ||
822 | |||
823 | return phy_count != 1; | ||
824 | } | ||
825 | |||
826 | /** | ||
827 | * This method is called by the PHY object when the link is detected. if the | ||
828 | * port wants the PHY to continue on to the link up state then the port | ||
829 | * layer must return true. If the port object returns false the phy object | ||
830 | * must halt its attempt to go link up. | ||
831 | * @this_port: The port associated with the phy object. | ||
832 | * @the_phy: The phy object that is trying to go link up. | ||
833 | * | ||
834 | * true if the phy object can continue to the link up condition. true Is | ||
835 | * returned if this phy can continue to the ready state. false Is returned if | ||
836 | * can not continue on to the ready state. This notification is in place for | ||
837 | * wide ports and direct attached phys. Since there are no wide ported SATA | ||
838 | * devices this could become an invalid port configuration. | ||
839 | */ | ||
840 | bool scic_sds_port_link_detected( | ||
841 | struct scic_sds_port *this_port, | ||
842 | struct scic_sds_phy *the_phy) | ||
843 | { | ||
844 | struct sci_sas_identify_address_frame_protocols protocols; | ||
845 | |||
846 | scic_sds_phy_get_attached_phy_protocols(the_phy, &protocols); | ||
847 | |||
848 | if ( | ||
849 | (this_port->logical_port_index != SCIC_SDS_DUMMY_PORT) | ||
850 | && (protocols.u.bits.stp_target) | ||
851 | && scic_sds_port_is_wide(this_port) | ||
852 | ) { | ||
853 | scic_sds_port_invalid_link_up(this_port, the_phy); | ||
854 | |||
855 | return false; | ||
856 | } | ||
857 | |||
858 | return true; | ||
859 | } | ||
860 | |||
861 | /** | ||
862 | * This method is the entry point for the phy to inform the port that it is now | ||
863 | * in a ready state | ||
864 | * @this_port: | ||
865 | * | ||
866 | * | ||
867 | */ | ||
868 | void scic_sds_port_link_up( | ||
869 | struct scic_sds_port *this_port, | ||
870 | struct scic_sds_phy *the_phy) | ||
871 | { | ||
872 | the_phy->is_in_link_training = false; | ||
873 | |||
874 | this_port->state_handlers->link_up_handler(this_port, the_phy); | ||
875 | } | ||
876 | |||
877 | /** | ||
878 | * This method is the entry point for the phy to inform the port that it is no | ||
879 | * longer in a ready state | ||
880 | * @this_port: | ||
881 | * | ||
882 | * | ||
883 | */ | ||
884 | void scic_sds_port_link_down( | ||
885 | struct scic_sds_port *this_port, | ||
886 | struct scic_sds_phy *the_phy) | ||
887 | { | ||
888 | this_port->state_handlers->link_down_handler(this_port, the_phy); | ||
889 | } | ||
890 | |||
891 | /** | ||
892 | * This method is called to start an IO request on this port. | ||
893 | * @this_port: | ||
894 | * @the_device: | ||
895 | * @the_io_request: | ||
896 | * | ||
897 | * enum sci_status | ||
898 | */ | ||
899 | enum sci_status scic_sds_port_start_io( | ||
900 | struct scic_sds_port *this_port, | ||
901 | struct scic_sds_remote_device *the_device, | ||
902 | struct scic_sds_request *the_io_request) | ||
903 | { | ||
904 | return this_port->state_handlers->start_io_handler( | ||
905 | this_port, the_device, the_io_request); | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * This method is called to complete an IO request to the port. | ||
910 | * @this_port: | ||
911 | * @the_device: | ||
912 | * @the_io_request: | ||
913 | * | ||
914 | * enum sci_status | ||
915 | */ | ||
916 | enum sci_status scic_sds_port_complete_io( | ||
917 | struct scic_sds_port *this_port, | ||
918 | struct scic_sds_remote_device *the_device, | ||
919 | struct scic_sds_request *the_io_request) | ||
920 | { | ||
921 | return this_port->state_handlers->complete_io_handler( | ||
922 | this_port, the_device, the_io_request); | ||
923 | } | ||
924 | |||
925 | /** | ||
926 | * This method is provided to timeout requests for port operations. Mostly its | ||
927 | * for the port reset operation. | ||
928 | * | ||
929 | * | ||
930 | */ | ||
931 | static void scic_sds_port_timeout_handler(void *port) | ||
932 | { | ||
933 | struct scic_sds_port *this_port = port; | ||
934 | u32 current_state; | ||
935 | |||
936 | current_state = sci_base_state_machine_get_state( | ||
937 | &this_port->parent.state_machine); | ||
938 | |||
939 | if (current_state == SCI_BASE_PORT_STATE_RESETTING) { | ||
940 | /* | ||
941 | * if the port is still in the resetting state then the timeout fired | ||
942 | * before the reset completed. */ | ||
943 | sci_base_state_machine_change_state( | ||
944 | &this_port->parent.state_machine, | ||
945 | SCI_BASE_PORT_STATE_FAILED | ||
946 | ); | ||
947 | } else if (current_state == SCI_BASE_PORT_STATE_STOPPED) { | ||
948 | /* | ||
949 | * if the port is stopped then the start request failed | ||
950 | * In this case stay in the stopped state. */ | ||
951 | dev_err(sciport_to_dev(this_port), | ||
952 | "%s: SCIC Port 0x%p failed to stop before tiemout.\n", | ||
953 | __func__, | ||
954 | this_port); | ||
955 | } else if (current_state == SCI_BASE_PORT_STATE_STOPPING) { | ||
956 | /* if the port is still stopping then the stop has not completed */ | ||
957 | scic_cb_port_stop_complete( | ||
958 | scic_sds_port_get_controller(this_port), | ||
959 | port, | ||
960 | SCI_FAILURE_TIMEOUT | ||
961 | ); | ||
962 | } else { | ||
963 | /* | ||
964 | * The port is in the ready state and we have a timer reporting a timeout | ||
965 | * this should not happen. */ | ||
966 | dev_err(sciport_to_dev(this_port), | ||
967 | "%s: SCIC Port 0x%p is processing a timeout operation " | ||
968 | "in state %d.\n", | ||
969 | __func__, | ||
970 | this_port, | ||
971 | current_state); | ||
972 | } | ||
973 | } | ||
974 | |||
975 | /* --------------------------------------------------------------------------- */ | ||
976 | |||
977 | #ifdef SCIC_DEBUG_ENABLED | ||
978 | void scic_sds_port_decrement_request_count(struct scic_sds_port *this_port) | ||
979 | { | ||
980 | if (this_port->started_request_count == 0) | ||
981 | dev_warn(sciport_to_dev(this_port), | ||
982 | __func__, | ||
983 | "%s: SCIC Port object requested to decrement started " | ||
984 | "io count past zero.\n"); | ||
985 | else | ||
986 | this_port->started_request_count--; | ||
987 | } | ||
988 | #endif | ||
989 | |||
990 | /** | ||
991 | * This function updates the hardwares VIIT entry for this port. | ||
992 | * | ||
993 | * | ||
994 | */ | ||
995 | void scic_sds_port_update_viit_entry(struct scic_sds_port *this_port) | ||
996 | { | ||
997 | struct sci_sas_address sas_address; | ||
998 | |||
999 | scic_sds_port_get_sas_address(this_port, &sas_address); | ||
1000 | |||
1001 | scu_port_viit_register_write( | ||
1002 | this_port, initiator_sas_address_hi, sas_address.high); | ||
1003 | |||
1004 | scu_port_viit_register_write( | ||
1005 | this_port, initiator_sas_address_lo, sas_address.low); | ||
1006 | |||
1007 | /* This value get cleared just in case its not already cleared */ | ||
1008 | scu_port_viit_register_write( | ||
1009 | this_port, reserved, 0); | ||
1010 | |||
1011 | /* We are required to update the status register last */ | ||
1012 | scu_port_viit_register_write( | ||
1013 | this_port, status, ( | ||
1014 | SCU_VIIT_ENTRY_ID_VIIT | ||
1015 | | SCU_VIIT_IPPT_INITIATOR | ||
1016 | | ((1 << this_port->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) | ||
1017 | | SCU_VIIT_STATUS_ALL_VALID | ||
1018 | ) | ||
1019 | ); | ||
1020 | } | ||
1021 | |||
1022 | /** | ||
1023 | * This method returns the maximum allowed speed for data transfers on this | ||
1024 | * port. This maximum allowed speed evaluates to the maximum speed of the | ||
1025 | * slowest phy in the port. | ||
1026 | * @this_port: This parameter specifies the port for which to retrieve the | ||
1027 | * maximum allowed speed. | ||
1028 | * | ||
1029 | * This method returns the maximum negotiated speed of the slowest phy in the | ||
1030 | * port. | ||
1031 | */ | ||
1032 | enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( | ||
1033 | struct scic_sds_port *this_port) | ||
1034 | { | ||
1035 | u16 index = 0; | ||
1036 | enum sci_sas_link_rate max_allowed_speed = SCI_SAS_600_GB; | ||
1037 | struct scic_sds_phy *phy = NULL; | ||
1038 | |||
1039 | /* | ||
1040 | * Loop through all of the phys in this port and find the phy with the | ||
1041 | * lowest maximum link rate. */ | ||
1042 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
1043 | phy = this_port->phy_table[index]; | ||
1044 | if ( | ||
1045 | (phy != NULL) | ||
1046 | && (scic_sds_port_active_phy(this_port, phy) == true) | ||
1047 | && (phy->max_negotiated_speed < max_allowed_speed) | ||
1048 | ) | ||
1049 | max_allowed_speed = phy->max_negotiated_speed; | ||
1050 | } | ||
1051 | |||
1052 | return max_allowed_speed; | ||
1053 | } | ||
1054 | |||
1055 | |||
1056 | /** | ||
1057 | * This method passes the event to core user. | ||
1058 | * @this_port: The port that a BCN happens. | ||
1059 | * @this_phy: The phy that receives BCN. | ||
1060 | * | ||
1061 | */ | ||
1062 | void scic_sds_port_broadcast_change_received( | ||
1063 | struct scic_sds_port *this_port, | ||
1064 | struct scic_sds_phy *this_phy) | ||
1065 | { | ||
1066 | /* notify the user. */ | ||
1067 | scic_cb_port_bc_change_primitive_received( | ||
1068 | this_port->owning_controller, this_port, this_phy | ||
1069 | ); | ||
1070 | } | ||
1071 | |||
1072 | |||
1073 | /** | ||
1074 | * This API methhod enables the broadcast change notification from underneath | ||
1075 | * hardware. | ||
1076 | * @this_port: The port that a BCN had been disabled from. | ||
1077 | * | ||
1078 | */ | ||
1079 | void scic_port_enable_broadcast_change_notification( | ||
1080 | struct scic_sds_port *port) | ||
1081 | { | ||
1082 | struct scic_sds_phy *phy; | ||
1083 | u32 register_value; | ||
1084 | u8 index; | ||
1085 | |||
1086 | /* Loop through all of the phys to enable BCN. */ | ||
1087 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
1088 | phy = port->phy_table[index]; | ||
1089 | if (phy != NULL) { | ||
1090 | register_value = SCU_SAS_LLCTL_READ(phy); | ||
1091 | |||
1092 | /* clear the bit by writing 1. */ | ||
1093 | SCU_SAS_LLCTL_WRITE(phy, register_value); | ||
1094 | } | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1098 | /* | ||
1099 | * **************************************************************************** | ||
1100 | * * READY SUBSTATE HANDLERS | ||
1101 | * **************************************************************************** */ | ||
1102 | |||
1103 | /** | ||
1104 | * | ||
1105 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1106 | * object. | ||
1107 | * | ||
1108 | * This method is the general ready state stop handler for the struct scic_sds_port | ||
1109 | * object. This function will transition the ready substate machine to its | ||
1110 | * final state. enum sci_status SCI_SUCCESS | ||
1111 | */ | ||
1112 | static enum sci_status scic_sds_port_ready_substate_stop_handler( | ||
1113 | struct sci_base_port *port) | ||
1114 | { | ||
1115 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1116 | |||
1117 | sci_base_state_machine_change_state( | ||
1118 | &this_port->parent.state_machine, | ||
1119 | SCI_BASE_PORT_STATE_STOPPING | ||
1120 | ); | ||
1121 | |||
1122 | return SCI_SUCCESS; | ||
1123 | } | ||
1124 | |||
1125 | /** | ||
1126 | * | ||
1127 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1128 | * object. | ||
1129 | * @device: This is the struct sci_base_remote_device object which is not used in this | ||
1130 | * function. | ||
1131 | * @io_request: This is the struct sci_base_request object which is not used in this | ||
1132 | * function. | ||
1133 | * | ||
1134 | * This method is the general ready substate complete io handler for the | ||
1135 | * struct scic_sds_port object. This function decrments the outstanding request count | ||
1136 | * for this port object. enum sci_status SCI_SUCCESS | ||
1137 | */ | ||
1138 | static enum sci_status scic_sds_port_ready_substate_complete_io_handler( | ||
1139 | struct scic_sds_port *port, | ||
1140 | struct scic_sds_remote_device *device, | ||
1141 | struct scic_sds_request *io_request) | ||
1142 | { | ||
1143 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1144 | |||
1145 | scic_sds_port_decrement_request_count(this_port); | ||
1146 | |||
1147 | return SCI_SUCCESS; | ||
1148 | } | ||
1149 | |||
1150 | static enum sci_status scic_sds_port_ready_substate_add_phy_handler( | ||
1151 | struct sci_base_port *port, | ||
1152 | struct sci_base_phy *phy) | ||
1153 | { | ||
1154 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1155 | struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; | ||
1156 | enum sci_status status; | ||
1157 | |||
1158 | status = scic_sds_port_set_phy(this_port, this_phy); | ||
1159 | |||
1160 | if (status == SCI_SUCCESS) { | ||
1161 | scic_sds_port_general_link_up_handler(this_port, this_phy, true); | ||
1162 | |||
1163 | this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; | ||
1164 | |||
1165 | sci_base_state_machine_change_state( | ||
1166 | &this_port->ready_substate_machine, | ||
1167 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1168 | ); | ||
1169 | } | ||
1170 | |||
1171 | return status; | ||
1172 | } | ||
1173 | |||
1174 | |||
1175 | static enum sci_status scic_sds_port_ready_substate_remove_phy_handler( | ||
1176 | struct sci_base_port *port, | ||
1177 | struct sci_base_phy *phy) | ||
1178 | { | ||
1179 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1180 | struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; | ||
1181 | enum sci_status status; | ||
1182 | |||
1183 | status = scic_sds_port_clear_phy(this_port, this_phy); | ||
1184 | |||
1185 | if (status == SCI_SUCCESS) { | ||
1186 | scic_sds_port_deactivate_phy(this_port, this_phy, true); | ||
1187 | |||
1188 | this_port->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING; | ||
1189 | |||
1190 | sci_base_state_machine_change_state( | ||
1191 | &this_port->ready_substate_machine, | ||
1192 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1193 | ); | ||
1194 | } | ||
1195 | |||
1196 | return status; | ||
1197 | } | ||
1198 | |||
1199 | /* | ||
1200 | * **************************************************************************** | ||
1201 | * * READY SUBSTATE WAITING HANDLERS | ||
1202 | * **************************************************************************** */ | ||
1203 | |||
1204 | /** | ||
1205 | * | ||
1206 | * @this_port: This is the struct scic_sds_port object that which has a phy that has | ||
1207 | * gone link up. | ||
1208 | * @the_phy: This is the struct scic_sds_phy object that has gone link up. | ||
1209 | * | ||
1210 | * This method is the ready waiting substate link up handler for the | ||
1211 | * struct scic_sds_port object. This methos will report the link up condition for | ||
1212 | * this port and will transition to the ready operational substate. none | ||
1213 | */ | ||
1214 | static void scic_sds_port_ready_waiting_substate_link_up_handler( | ||
1215 | struct scic_sds_port *this_port, | ||
1216 | struct scic_sds_phy *the_phy) | ||
1217 | { | ||
1218 | /* | ||
1219 | * Since this is the first phy going link up for the port we can just enable | ||
1220 | * it and continue. */ | ||
1221 | scic_sds_port_activate_phy(this_port, the_phy, true); | ||
1222 | |||
1223 | sci_base_state_machine_change_state( | ||
1224 | &this_port->ready_substate_machine, | ||
1225 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1226 | ); | ||
1227 | } | ||
1228 | |||
1229 | /** | ||
1230 | * | ||
1231 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1232 | * object. | ||
1233 | * @device: This is the struct sci_base_remote_device object which is not used in this | ||
1234 | * request. | ||
1235 | * @io_request: This is the struct sci_base_request object which is not used in this | ||
1236 | * function. | ||
1237 | * | ||
1238 | * This method is the ready waiting substate start io handler for the | ||
1239 | * struct scic_sds_port object. The port object can not accept new requests so the | ||
1240 | * request is failed. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1241 | */ | ||
1242 | static enum sci_status scic_sds_port_ready_waiting_substate_start_io_handler( | ||
1243 | struct scic_sds_port *port, | ||
1244 | struct scic_sds_remote_device *device, | ||
1245 | struct scic_sds_request *io_request) | ||
1246 | { | ||
1247 | return SCI_FAILURE_INVALID_STATE; | ||
1248 | } | ||
1249 | |||
1250 | /* | ||
1251 | * **************************************************************************** | ||
1252 | * * READY SUBSTATE OPERATIONAL HANDLERS | ||
1253 | * **************************************************************************** */ | ||
1254 | |||
1255 | /** | ||
1256 | * | ||
1257 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1258 | * object. | ||
1259 | * @timeout: This is the timeout for the reset request to complete. | ||
1260 | * | ||
1261 | * This method will casue the port to reset. enum sci_status SCI_SUCCESS | ||
1262 | */ | ||
1263 | static enum sci_status scic_sds_port_ready_operational_substate_reset_handler( | ||
1264 | struct sci_base_port *port, | ||
1265 | u32 timeout) | ||
1266 | { | ||
1267 | enum sci_status status = SCI_FAILURE_INVALID_PHY; | ||
1268 | u32 phy_index; | ||
1269 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1270 | struct scic_sds_phy *selected_phy = SCI_INVALID_HANDLE; | ||
1271 | |||
1272 | |||
1273 | /* Select a phy on which we can send the hard reset request. */ | ||
1274 | for ( | ||
1275 | phy_index = 0; | ||
1276 | (phy_index < SCI_MAX_PHYS) | ||
1277 | && (selected_phy == SCI_INVALID_HANDLE); | ||
1278 | phy_index++ | ||
1279 | ) { | ||
1280 | selected_phy = this_port->phy_table[phy_index]; | ||
1281 | |||
1282 | if ( | ||
1283 | (selected_phy != SCI_INVALID_HANDLE) | ||
1284 | && !scic_sds_port_active_phy(this_port, selected_phy) | ||
1285 | ) { | ||
1286 | /* We found a phy but it is not ready select different phy */ | ||
1287 | selected_phy = SCI_INVALID_HANDLE; | ||
1288 | } | ||
1289 | } | ||
1290 | |||
1291 | /* If we have a phy then go ahead and start the reset procedure */ | ||
1292 | if (selected_phy != SCI_INVALID_HANDLE) { | ||
1293 | status = scic_sds_phy_reset(selected_phy); | ||
1294 | |||
1295 | if (status == SCI_SUCCESS) { | ||
1296 | scic_cb_timer_start( | ||
1297 | scic_sds_port_get_controller(this_port), | ||
1298 | this_port->timer_handle, | ||
1299 | timeout | ||
1300 | ); | ||
1301 | |||
1302 | this_port->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED; | ||
1303 | |||
1304 | sci_base_state_machine_change_state( | ||
1305 | &this_port->parent.state_machine, | ||
1306 | SCI_BASE_PORT_STATE_RESETTING | ||
1307 | ); | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1311 | return status; | ||
1312 | } | ||
1313 | |||
1314 | /** | ||
1315 | * scic_sds_port_ready_operational_substate_link_up_handler() - | ||
1316 | * @this_port: This is the struct scic_sds_port object that which has a phy that has | ||
1317 | * gone link up. | ||
1318 | * @the_phy: This is the struct scic_sds_phy object that has gone link up. | ||
1319 | * | ||
1320 | * This method is the ready operational substate link up handler for the | ||
1321 | * struct scic_sds_port object. This function notifies the SCI User that the phy has | ||
1322 | * gone link up. none | ||
1323 | */ | ||
1324 | static void scic_sds_port_ready_operational_substate_link_up_handler( | ||
1325 | struct scic_sds_port *this_port, | ||
1326 | struct scic_sds_phy *the_phy) | ||
1327 | { | ||
1328 | scic_sds_port_general_link_up_handler(this_port, the_phy, true); | ||
1329 | } | ||
1330 | |||
1331 | /** | ||
1332 | * scic_sds_port_ready_operational_substate_link_down_handler() - | ||
1333 | * @this_port: This is the struct scic_sds_port object that which has a phy that has | ||
1334 | * gone link down. | ||
1335 | * @the_phy: This is the struct scic_sds_phy object that has gone link down. | ||
1336 | * | ||
1337 | * This method is the ready operational substate link down handler for the | ||
1338 | * struct scic_sds_port object. This function notifies the SCI User that the phy has | ||
1339 | * gone link down and if this is the last phy in the port the port will change | ||
1340 | * state to the ready waiting substate. none | ||
1341 | */ | ||
1342 | static void scic_sds_port_ready_operational_substate_link_down_handler( | ||
1343 | struct scic_sds_port *this_port, | ||
1344 | struct scic_sds_phy *the_phy) | ||
1345 | { | ||
1346 | scic_sds_port_deactivate_phy(this_port, the_phy, true); | ||
1347 | |||
1348 | /* | ||
1349 | * If there are no active phys left in the port, then transition | ||
1350 | * the port to the WAITING state until such time as a phy goes | ||
1351 | * link up. */ | ||
1352 | if (this_port->active_phy_mask == 0) { | ||
1353 | sci_base_state_machine_change_state( | ||
1354 | scic_sds_port_get_ready_substate_machine(this_port), | ||
1355 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING | ||
1356 | ); | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | /** | ||
1361 | * | ||
1362 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1363 | * object. | ||
1364 | * @device: This is the struct sci_base_remote_device object which is not used in this | ||
1365 | * function. | ||
1366 | * @io_request: This is the struct sci_base_request object which is not used in this | ||
1367 | * function. | ||
1368 | * | ||
1369 | * This method is the ready operational substate start io handler for the | ||
1370 | * struct scic_sds_port object. This function incremetns the outstanding request | ||
1371 | * count for this port object. enum sci_status SCI_SUCCESS | ||
1372 | */ | ||
1373 | static enum sci_status scic_sds_port_ready_operational_substate_start_io_handler( | ||
1374 | struct scic_sds_port *port, | ||
1375 | struct scic_sds_remote_device *device, | ||
1376 | struct scic_sds_request *io_request) | ||
1377 | { | ||
1378 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1379 | |||
1380 | scic_sds_port_increment_request_count(this_port); | ||
1381 | |||
1382 | return SCI_SUCCESS; | ||
1383 | } | ||
1384 | |||
1385 | /* | ||
1386 | * **************************************************************************** | ||
1387 | * * READY SUBSTATE OPERATIONAL HANDLERS | ||
1388 | * **************************************************************************** */ | ||
1389 | |||
1390 | /** | ||
1391 | * scic_sds_port_ready_configuring_substate_add_phy_handler() - | ||
1392 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1393 | * object. | ||
1394 | * | ||
1395 | * This is the default method for a port add phy request. It will report a | ||
1396 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1397 | */ | ||
1398 | static enum sci_status scic_sds_port_ready_configuring_substate_add_phy_handler( | ||
1399 | struct sci_base_port *port, | ||
1400 | struct sci_base_phy *phy) | ||
1401 | { | ||
1402 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1403 | struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; | ||
1404 | enum sci_status status; | ||
1405 | |||
1406 | status = scic_sds_port_set_phy(this_port, this_phy); | ||
1407 | |||
1408 | if (status == SCI_SUCCESS) { | ||
1409 | scic_sds_port_general_link_up_handler(this_port, this_phy, true); | ||
1410 | |||
1411 | /* | ||
1412 | * Re-enter the configuring state since this may be the last phy in | ||
1413 | * the port. */ | ||
1414 | sci_base_state_machine_change_state( | ||
1415 | &this_port->ready_substate_machine, | ||
1416 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1417 | ); | ||
1418 | } | ||
1419 | |||
1420 | return status; | ||
1421 | } | ||
1422 | |||
1423 | /** | ||
1424 | * scic_sds_port_ready_configuring_substate_remove_phy_handler() - | ||
1425 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1426 | * object. | ||
1427 | * | ||
1428 | * This is the default method for a port remove phy request. It will report a | ||
1429 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1430 | */ | ||
1431 | static enum sci_status scic_sds_port_ready_configuring_substate_remove_phy_handler( | ||
1432 | struct sci_base_port *port, | ||
1433 | struct sci_base_phy *phy) | ||
1434 | { | ||
1435 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
1436 | struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; | ||
1437 | enum sci_status status; | ||
1438 | |||
1439 | status = scic_sds_port_clear_phy(this_port, this_phy); | ||
1440 | |||
1441 | if (status == SCI_SUCCESS) { | ||
1442 | scic_sds_port_deactivate_phy(this_port, this_phy, true); | ||
1443 | |||
1444 | /* | ||
1445 | * Re-enter the configuring state since this may be the last phy in | ||
1446 | * the port. */ | ||
1447 | sci_base_state_machine_change_state( | ||
1448 | &this_port->ready_substate_machine, | ||
1449 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1450 | ); | ||
1451 | } | ||
1452 | |||
1453 | return status; | ||
1454 | } | ||
1455 | |||
1456 | /** | ||
1457 | * scic_sds_port_ready_configuring_substate_complete_io_handler() - | ||
1458 | * @port: This is the port that is being requested to complete the io request. | ||
1459 | * @device: This is the device on which the io is completing. | ||
1460 | * | ||
1461 | * This method will decrement the outstanding request count for this port. If | ||
1462 | * the request count goes to 0 then the port can be reprogrammed with its new | ||
1463 | * phy data. | ||
1464 | */ | ||
1465 | static enum sci_status scic_sds_port_ready_configuring_substate_complete_io_handler( | ||
1466 | struct scic_sds_port *port, | ||
1467 | struct scic_sds_remote_device *device, | ||
1468 | struct scic_sds_request *io_request) | ||
1469 | { | ||
1470 | scic_sds_port_decrement_request_count(port); | ||
1471 | |||
1472 | if (port->started_request_count == 0) { | ||
1473 | sci_base_state_machine_change_state( | ||
1474 | &port->ready_substate_machine, | ||
1475 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1476 | ); | ||
1477 | } | ||
1478 | |||
1479 | return SCI_SUCCESS; | ||
1480 | } | ||
1481 | |||
1482 | /* --------------------------------------------------------------------------- */ | ||
1483 | |||
1484 | struct scic_sds_port_state_handler | ||
1485 | scic_sds_port_ready_substate_handler_table[SCIC_SDS_PORT_READY_MAX_SUBSTATES] = | ||
1486 | { | ||
1487 | /* SCIC_SDS_PORT_READY_SUBSTATE_WAITING */ | ||
1488 | { | ||
1489 | { | ||
1490 | scic_sds_port_default_start_handler, | ||
1491 | scic_sds_port_ready_substate_stop_handler, | ||
1492 | scic_sds_port_default_destruct_handler, | ||
1493 | scic_sds_port_default_reset_handler, | ||
1494 | scic_sds_port_ready_substate_add_phy_handler, | ||
1495 | scic_sds_port_default_remove_phy_handler | ||
1496 | }, | ||
1497 | scic_sds_port_default_frame_handler, | ||
1498 | scic_sds_port_default_event_handler, | ||
1499 | scic_sds_port_ready_waiting_substate_link_up_handler, | ||
1500 | scic_sds_port_default_link_down_handler, | ||
1501 | scic_sds_port_ready_waiting_substate_start_io_handler, | ||
1502 | scic_sds_port_ready_substate_complete_io_handler, | ||
1503 | }, | ||
1504 | /* SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL */ | ||
1505 | { | ||
1506 | { | ||
1507 | scic_sds_port_default_start_handler, | ||
1508 | scic_sds_port_ready_substate_stop_handler, | ||
1509 | scic_sds_port_default_destruct_handler, | ||
1510 | scic_sds_port_ready_operational_substate_reset_handler, | ||
1511 | scic_sds_port_ready_substate_add_phy_handler, | ||
1512 | scic_sds_port_ready_substate_remove_phy_handler | ||
1513 | }, | ||
1514 | scic_sds_port_default_frame_handler, | ||
1515 | scic_sds_port_default_event_handler, | ||
1516 | scic_sds_port_ready_operational_substate_link_up_handler, | ||
1517 | scic_sds_port_ready_operational_substate_link_down_handler, | ||
1518 | scic_sds_port_ready_operational_substate_start_io_handler, | ||
1519 | scic_sds_port_ready_substate_complete_io_handler | ||
1520 | }, | ||
1521 | /* SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING */ | ||
1522 | { | ||
1523 | { | ||
1524 | scic_sds_port_default_start_handler, | ||
1525 | scic_sds_port_ready_substate_stop_handler, | ||
1526 | scic_sds_port_default_destruct_handler, | ||
1527 | scic_sds_port_default_reset_handler, | ||
1528 | scic_sds_port_ready_configuring_substate_add_phy_handler, | ||
1529 | scic_sds_port_ready_configuring_substate_remove_phy_handler | ||
1530 | }, | ||
1531 | scic_sds_port_default_frame_handler, | ||
1532 | scic_sds_port_default_event_handler, | ||
1533 | scic_sds_port_default_link_up_handler, | ||
1534 | scic_sds_port_default_link_down_handler, | ||
1535 | scic_sds_port_default_start_io_handler, | ||
1536 | scic_sds_port_ready_configuring_substate_complete_io_handler | ||
1537 | } | ||
1538 | }; | ||
1539 | |||
1540 | |||
1541 | /** | ||
1542 | * scic_sds_port_set_ready_state_handlers() - | ||
1543 | * | ||
1544 | * This macro sets the port ready substate handlers. | ||
1545 | */ | ||
1546 | #define scic_sds_port_set_ready_state_handlers(port, state_id) \ | ||
1547 | scic_sds_port_set_state_handlers(\ | ||
1548 | port, &scic_sds_port_ready_substate_handler_table[(state_id)] \ | ||
1549 | ) | ||
1550 | |||
1551 | /* | ||
1552 | * ****************************************************************************** | ||
1553 | * * PORT STATE PRIVATE METHODS | ||
1554 | * ****************************************************************************** */ | ||
1555 | |||
1556 | /** | ||
1557 | * | ||
1558 | * @this_port: This is the struct scic_sds_port object to suspend. | ||
1559 | * | ||
1560 | * This method will susped the port task scheduler for this port object. none | ||
1561 | */ | ||
1562 | static void scic_sds_port_suspend_port_task_scheduler( | ||
1563 | struct scic_sds_port *this_port) | ||
1564 | { | ||
1565 | u32 pts_control_value; | ||
1566 | u32 tl_control_value; | ||
1567 | |||
1568 | pts_control_value = scu_port_task_scheduler_read(this_port, control); | ||
1569 | tl_control_value = scu_transport_layer_read(this_port, control); | ||
1570 | |||
1571 | pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND); | ||
1572 | tl_control_value |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE); | ||
1573 | |||
1574 | scu_port_task_scheduler_write(this_port, control, pts_control_value); | ||
1575 | scu_transport_layer_write(this_port, control, tl_control_value); | ||
1576 | } | ||
1577 | |||
1578 | /** | ||
1579 | * | ||
1580 | * @this_port: This is the struct scic_sds_port object to resume. | ||
1581 | * | ||
1582 | * This method will resume the port task scheduler for this port object. none | ||
1583 | */ | ||
1584 | static void scic_sds_port_resume_port_task_scheduler( | ||
1585 | struct scic_sds_port *this_port) | ||
1586 | { | ||
1587 | u32 pts_control_value; | ||
1588 | |||
1589 | pts_control_value = scu_port_task_scheduler_read(this_port, control); | ||
1590 | |||
1591 | pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND); | ||
1592 | |||
1593 | scu_port_task_scheduler_write(this_port, control, pts_control_value); | ||
1594 | } | ||
1595 | |||
1596 | /* | ||
1597 | * ****************************************************************************** | ||
1598 | * * PORT READY SUBSTATE METHODS | ||
1599 | * ****************************************************************************** */ | ||
1600 | |||
1601 | /** | ||
1602 | * | ||
1603 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
1604 | * | ||
1605 | * This method will perform the actions required by the struct scic_sds_port on | ||
1606 | * entering the SCIC_SDS_PORT_READY_SUBSTATE_WAITING. This function checks the | ||
1607 | * port for any ready phys. If there is at least one phy in a ready state then | ||
1608 | * the port transitions to the ready operational substate. none | ||
1609 | */ | ||
1610 | static void scic_sds_port_ready_substate_waiting_enter( | ||
1611 | struct sci_base_object *object) | ||
1612 | { | ||
1613 | struct scic_sds_port *this_port = (struct scic_sds_port *)object; | ||
1614 | |||
1615 | scic_sds_port_set_ready_state_handlers( | ||
1616 | this_port, SCIC_SDS_PORT_READY_SUBSTATE_WAITING | ||
1617 | ); | ||
1618 | |||
1619 | scic_sds_port_suspend_port_task_scheduler(this_port); | ||
1620 | |||
1621 | this_port->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS; | ||
1622 | |||
1623 | if (this_port->active_phy_mask != 0) { | ||
1624 | /* At least one of the phys on the port is ready */ | ||
1625 | sci_base_state_machine_change_state( | ||
1626 | &this_port->ready_substate_machine, | ||
1627 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1628 | ); | ||
1629 | } | ||
1630 | } | ||
1631 | |||
1632 | /** | ||
1633 | * | ||
1634 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
1635 | * | ||
1636 | * This method will perform the actions required by the struct scic_sds_port on | ||
1637 | * entering the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function sets | ||
1638 | * the state handlers for the port object, notifies the SCI User that the port | ||
1639 | * is ready, and resumes port operations. none | ||
1640 | */ | ||
1641 | static void scic_sds_port_ready_substate_operational_enter( | ||
1642 | struct sci_base_object *object) | ||
1643 | { | ||
1644 | u32 index; | ||
1645 | struct scic_sds_port *this_port = (struct scic_sds_port *)object; | ||
1646 | |||
1647 | scic_sds_port_set_ready_state_handlers( | ||
1648 | this_port, SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1649 | ); | ||
1650 | |||
1651 | scic_cb_port_ready( | ||
1652 | scic_sds_port_get_controller(this_port), this_port | ||
1653 | ); | ||
1654 | |||
1655 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
1656 | if (this_port->phy_table[index] != NULL) { | ||
1657 | scic_sds_port_write_phy_assignment( | ||
1658 | this_port, this_port->phy_table[index] | ||
1659 | ); | ||
1660 | } | ||
1661 | } | ||
1662 | |||
1663 | scic_sds_port_update_viit_entry(this_port); | ||
1664 | |||
1665 | scic_sds_port_resume_port_task_scheduler(this_port); | ||
1666 | } | ||
1667 | |||
1668 | /** | ||
1669 | * | ||
1670 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
1671 | * | ||
1672 | * This method will perform the actions required by the struct scic_sds_port on | ||
1673 | * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports | ||
1674 | * the port not ready and suspends the port task scheduler. none | ||
1675 | */ | ||
1676 | static void scic_sds_port_ready_substate_operational_exit( | ||
1677 | struct sci_base_object *object) | ||
1678 | { | ||
1679 | struct scic_sds_port *this_port = (struct scic_sds_port *)object; | ||
1680 | |||
1681 | scic_cb_port_not_ready( | ||
1682 | scic_sds_port_get_controller(this_port), | ||
1683 | this_port, | ||
1684 | this_port->not_ready_reason | ||
1685 | ); | ||
1686 | } | ||
1687 | |||
1688 | /* | ||
1689 | * ****************************************************************************** | ||
1690 | * * PORT READY CONFIGURING METHODS | ||
1691 | * ****************************************************************************** */ | ||
1692 | |||
1693 | /** | ||
1694 | * scic_sds_port_ready_substate_configuring_enter() - | ||
1695 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
1696 | * | ||
1697 | * This method will perform the actions required by the struct scic_sds_port on | ||
1698 | * exiting the SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL. This function reports | ||
1699 | * the port not ready and suspends the port task scheduler. none | ||
1700 | */ | ||
1701 | static void scic_sds_port_ready_substate_configuring_enter( | ||
1702 | struct sci_base_object *object) | ||
1703 | { | ||
1704 | struct scic_sds_port *this_port = (struct scic_sds_port *)object; | ||
1705 | |||
1706 | scic_sds_port_set_ready_state_handlers( | ||
1707 | this_port, SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING | ||
1708 | ); | ||
1709 | |||
1710 | if (this_port->active_phy_mask == 0) { | ||
1711 | scic_cb_port_not_ready( | ||
1712 | scic_sds_port_get_controller(this_port), | ||
1713 | this_port, | ||
1714 | SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS | ||
1715 | ); | ||
1716 | |||
1717 | sci_base_state_machine_change_state( | ||
1718 | &this_port->ready_substate_machine, | ||
1719 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING | ||
1720 | ); | ||
1721 | } else if (this_port->started_request_count == 0) { | ||
1722 | sci_base_state_machine_change_state( | ||
1723 | &this_port->ready_substate_machine, | ||
1724 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL | ||
1725 | ); | ||
1726 | } | ||
1727 | } | ||
1728 | |||
1729 | static void scic_sds_port_ready_substate_configuring_exit( | ||
1730 | struct sci_base_object *object) | ||
1731 | { | ||
1732 | struct scic_sds_port *this_port = (struct scic_sds_port *)object; | ||
1733 | |||
1734 | scic_sds_port_suspend_port_task_scheduler(this_port); | ||
1735 | } | ||
1736 | |||
1737 | /* --------------------------------------------------------------------------- */ | ||
1738 | |||
1739 | const struct sci_base_state scic_sds_port_ready_substate_table[] = { | ||
1740 | [SCIC_SDS_PORT_READY_SUBSTATE_WAITING] = { | ||
1741 | .enter_state = scic_sds_port_ready_substate_waiting_enter, | ||
1742 | }, | ||
1743 | [SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL] = { | ||
1744 | .enter_state = scic_sds_port_ready_substate_operational_enter, | ||
1745 | .exit_state = scic_sds_port_ready_substate_operational_exit | ||
1746 | }, | ||
1747 | [SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING] = { | ||
1748 | .enter_state = scic_sds_port_ready_substate_configuring_enter, | ||
1749 | .exit_state = scic_sds_port_ready_substate_configuring_exit | ||
1750 | }, | ||
1751 | }; | ||
1752 | |||
1753 | /* | ||
1754 | * *************************************************************************** | ||
1755 | * * DEFAULT HANDLERS | ||
1756 | * *************************************************************************** */ | ||
1757 | |||
1758 | /** | ||
1759 | * | ||
1760 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1761 | * object. | ||
1762 | * | ||
1763 | * This is the default method for port a start request. It will report a | ||
1764 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1765 | */ | ||
1766 | enum sci_status scic_sds_port_default_start_handler( | ||
1767 | struct sci_base_port *port) | ||
1768 | { | ||
1769 | struct scic_sds_port *sci_port = (struct scic_sds_port *)port; | ||
1770 | |||
1771 | dev_warn(sciport_to_dev(sci_port), | ||
1772 | "%s: SCIC Port 0x%p requested to start while in invalid " | ||
1773 | "state %d\n", | ||
1774 | __func__, | ||
1775 | port, | ||
1776 | sci_base_state_machine_get_state( | ||
1777 | scic_sds_port_get_base_state_machine( | ||
1778 | (struct scic_sds_port *)port))); | ||
1779 | |||
1780 | return SCI_FAILURE_INVALID_STATE; | ||
1781 | } | ||
1782 | |||
1783 | /** | ||
1784 | * | ||
1785 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1786 | * object. | ||
1787 | * | ||
1788 | * This is the default method for a port stop request. It will report a | ||
1789 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1790 | */ | ||
1791 | static enum sci_status scic_sds_port_default_stop_handler( | ||
1792 | struct sci_base_port *port) | ||
1793 | { | ||
1794 | struct scic_sds_port *sci_port = (struct scic_sds_port *)port; | ||
1795 | |||
1796 | dev_warn(sciport_to_dev(sci_port), | ||
1797 | "%s: SCIC Port 0x%p requested to stop while in invalid " | ||
1798 | "state %d\n", | ||
1799 | __func__, | ||
1800 | port, | ||
1801 | sci_base_state_machine_get_state( | ||
1802 | scic_sds_port_get_base_state_machine( | ||
1803 | (struct scic_sds_port *)port))); | ||
1804 | |||
1805 | return SCI_FAILURE_INVALID_STATE; | ||
1806 | } | ||
1807 | |||
1808 | /** | ||
1809 | * | ||
1810 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1811 | * object. | ||
1812 | * | ||
1813 | * This is the default method for a port destruct request. It will report a | ||
1814 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1815 | */ | ||
1816 | enum sci_status scic_sds_port_default_destruct_handler( | ||
1817 | struct sci_base_port *port) | ||
1818 | { | ||
1819 | struct scic_sds_port *sci_port = (struct scic_sds_port *)port; | ||
1820 | |||
1821 | dev_warn(sciport_to_dev(sci_port), | ||
1822 | "%s: SCIC Port 0x%p requested to destruct while in invalid " | ||
1823 | "state %d\n", | ||
1824 | __func__, | ||
1825 | port, | ||
1826 | sci_base_state_machine_get_state( | ||
1827 | scic_sds_port_get_base_state_machine( | ||
1828 | (struct scic_sds_port *)port))); | ||
1829 | |||
1830 | return SCI_FAILURE_INVALID_STATE; | ||
1831 | } | ||
1832 | |||
1833 | /** | ||
1834 | * | ||
1835 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1836 | * object. | ||
1837 | * @timeout: This is the timeout for the reset request to complete. | ||
1838 | * | ||
1839 | * This is the default method for a port reset request. It will report a | ||
1840 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1841 | */ | ||
1842 | enum sci_status scic_sds_port_default_reset_handler( | ||
1843 | struct sci_base_port *port, | ||
1844 | u32 timeout) | ||
1845 | { | ||
1846 | struct scic_sds_port *sci_port = (struct scic_sds_port *)port; | ||
1847 | |||
1848 | dev_warn(sciport_to_dev(sci_port), | ||
1849 | "%s: SCIC Port 0x%p requested to reset while in invalid " | ||
1850 | "state %d\n", | ||
1851 | __func__, | ||
1852 | port, | ||
1853 | sci_base_state_machine_get_state( | ||
1854 | scic_sds_port_get_base_state_machine( | ||
1855 | (struct scic_sds_port *)port))); | ||
1856 | |||
1857 | return SCI_FAILURE_INVALID_STATE; | ||
1858 | } | ||
1859 | |||
1860 | /** | ||
1861 | * | ||
1862 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1863 | * object. | ||
1864 | * | ||
1865 | * This is the default method for a port add phy request. It will report a | ||
1866 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1867 | */ | ||
1868 | static enum sci_status scic_sds_port_default_add_phy_handler( | ||
1869 | struct sci_base_port *port, | ||
1870 | struct sci_base_phy *phy) | ||
1871 | { | ||
1872 | struct scic_sds_port *sci_port = (struct scic_sds_port *)port; | ||
1873 | |||
1874 | dev_warn(sciport_to_dev(sci_port), | ||
1875 | "%s: SCIC Port 0x%p requested to add phy 0x%p while in " | ||
1876 | "invalid state %d\n", | ||
1877 | __func__, | ||
1878 | port, | ||
1879 | phy, | ||
1880 | sci_base_state_machine_get_state( | ||
1881 | scic_sds_port_get_base_state_machine( | ||
1882 | (struct scic_sds_port *)port))); | ||
1883 | |||
1884 | return SCI_FAILURE_INVALID_STATE; | ||
1885 | } | ||
1886 | |||
1887 | /** | ||
1888 | * | ||
1889 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1890 | * object. | ||
1891 | * | ||
1892 | * This is the default method for a port remove phy request. It will report a | ||
1893 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1894 | */ | ||
1895 | enum sci_status scic_sds_port_default_remove_phy_handler( | ||
1896 | struct sci_base_port *port, | ||
1897 | struct sci_base_phy *phy) | ||
1898 | { | ||
1899 | struct scic_sds_port *sci_port = (struct scic_sds_port *)port; | ||
1900 | |||
1901 | dev_warn(sciport_to_dev(sci_port), | ||
1902 | "%s: SCIC Port 0x%p requested to remove phy 0x%p while in " | ||
1903 | "invalid state %d\n", | ||
1904 | __func__, | ||
1905 | port, | ||
1906 | phy, | ||
1907 | sci_base_state_machine_get_state( | ||
1908 | scic_sds_port_get_base_state_machine( | ||
1909 | (struct scic_sds_port *)port))); | ||
1910 | |||
1911 | return SCI_FAILURE_INVALID_STATE; | ||
1912 | } | ||
1913 | |||
1914 | /** | ||
1915 | * | ||
1916 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1917 | * object. | ||
1918 | * | ||
1919 | * This is the default method for a port unsolicited frame request. It will | ||
1920 | * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE Is it even | ||
1921 | * possible to receive an unsolicited frame directed to a port object? It | ||
1922 | * seems possible if we implementing virtual functions but until then? | ||
1923 | */ | ||
1924 | enum sci_status scic_sds_port_default_frame_handler( | ||
1925 | struct scic_sds_port *port, | ||
1926 | u32 frame_index) | ||
1927 | { | ||
1928 | dev_warn(sciport_to_dev(port), | ||
1929 | "%s: SCIC Port 0x%p requested to process frame %d while in " | ||
1930 | "invalid state %d\n", | ||
1931 | __func__, | ||
1932 | port, | ||
1933 | frame_index, | ||
1934 | sci_base_state_machine_get_state( | ||
1935 | scic_sds_port_get_base_state_machine(port))); | ||
1936 | |||
1937 | scic_sds_controller_release_frame( | ||
1938 | scic_sds_port_get_controller(port), frame_index | ||
1939 | ); | ||
1940 | |||
1941 | return SCI_FAILURE_INVALID_STATE; | ||
1942 | } | ||
1943 | |||
1944 | /** | ||
1945 | * | ||
1946 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1947 | * object. | ||
1948 | * | ||
1949 | * This is the default method for a port event request. It will report a | ||
1950 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1951 | */ | ||
1952 | enum sci_status scic_sds_port_default_event_handler( | ||
1953 | struct scic_sds_port *port, | ||
1954 | u32 event_code) | ||
1955 | { | ||
1956 | dev_warn(sciport_to_dev(port), | ||
1957 | "%s: SCIC Port 0x%p requested to process event 0x%x while " | ||
1958 | "in invalid state %d\n", | ||
1959 | __func__, | ||
1960 | port, | ||
1961 | event_code, | ||
1962 | sci_base_state_machine_get_state( | ||
1963 | scic_sds_port_get_base_state_machine( | ||
1964 | (struct scic_sds_port *)port))); | ||
1965 | |||
1966 | return SCI_FAILURE_INVALID_STATE; | ||
1967 | } | ||
1968 | |||
1969 | /** | ||
1970 | * | ||
1971 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1972 | * object. | ||
1973 | * | ||
1974 | * This is the default method for a port link up notification. It will report | ||
1975 | * a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1976 | */ | ||
1977 | void scic_sds_port_default_link_up_handler( | ||
1978 | struct scic_sds_port *this_port, | ||
1979 | struct scic_sds_phy *phy) | ||
1980 | { | ||
1981 | dev_warn(sciport_to_dev(this_port), | ||
1982 | "%s: SCIC Port 0x%p received link_up notification from phy " | ||
1983 | "0x%p while in invalid state %d\n", | ||
1984 | __func__, | ||
1985 | this_port, | ||
1986 | phy, | ||
1987 | sci_base_state_machine_get_state( | ||
1988 | scic_sds_port_get_base_state_machine(this_port))); | ||
1989 | } | ||
1990 | |||
1991 | /** | ||
1992 | * | ||
1993 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
1994 | * object. | ||
1995 | * | ||
1996 | * This is the default method for a port link down notification. It will | ||
1997 | * report a warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1998 | */ | ||
1999 | void scic_sds_port_default_link_down_handler( | ||
2000 | struct scic_sds_port *this_port, | ||
2001 | struct scic_sds_phy *phy) | ||
2002 | { | ||
2003 | dev_warn(sciport_to_dev(this_port), | ||
2004 | "%s: SCIC Port 0x%p received link down notification from " | ||
2005 | "phy 0x%p while in invalid state %d\n", | ||
2006 | __func__, | ||
2007 | this_port, | ||
2008 | phy, | ||
2009 | sci_base_state_machine_get_state( | ||
2010 | scic_sds_port_get_base_state_machine(this_port))); | ||
2011 | } | ||
2012 | |||
2013 | /** | ||
2014 | * | ||
2015 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2016 | * object. | ||
2017 | * | ||
2018 | * This is the default method for a port start io request. It will report a | ||
2019 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2020 | */ | ||
2021 | enum sci_status scic_sds_port_default_start_io_handler( | ||
2022 | struct scic_sds_port *this_port, | ||
2023 | struct scic_sds_remote_device *device, | ||
2024 | struct scic_sds_request *io_request) | ||
2025 | { | ||
2026 | dev_warn(sciport_to_dev(this_port), | ||
2027 | "%s: SCIC Port 0x%p requested to start io request 0x%p " | ||
2028 | "while in invalid state %d\n", | ||
2029 | __func__, | ||
2030 | this_port, | ||
2031 | io_request, | ||
2032 | sci_base_state_machine_get_state( | ||
2033 | scic_sds_port_get_base_state_machine(this_port))); | ||
2034 | |||
2035 | return SCI_FAILURE_INVALID_STATE; | ||
2036 | } | ||
2037 | |||
2038 | /** | ||
2039 | * | ||
2040 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2041 | * object. | ||
2042 | * | ||
2043 | * This is the default method for a port complete io request. It will report a | ||
2044 | * warning and exit. enum sci_status SCI_FAILURE_INVALID_STATE | ||
2045 | */ | ||
2046 | static enum sci_status scic_sds_port_default_complete_io_handler( | ||
2047 | struct scic_sds_port *this_port, | ||
2048 | struct scic_sds_remote_device *device, | ||
2049 | struct scic_sds_request *io_request) | ||
2050 | { | ||
2051 | dev_warn(sciport_to_dev(this_port), | ||
2052 | "%s: SCIC Port 0x%p requested to complete io request 0x%p " | ||
2053 | "while in invalid state %d\n", | ||
2054 | __func__, | ||
2055 | this_port, | ||
2056 | io_request, | ||
2057 | sci_base_state_machine_get_state( | ||
2058 | scic_sds_port_get_base_state_machine(this_port))); | ||
2059 | |||
2060 | return SCI_FAILURE_INVALID_STATE; | ||
2061 | } | ||
2062 | |||
2063 | /* | ||
2064 | * **************************************************************************** | ||
2065 | * * GENERAL STATE HANDLERS | ||
2066 | * **************************************************************************** */ | ||
2067 | |||
2068 | /** | ||
2069 | * | ||
2070 | * @port: This is the struct scic_sds_port object on which the io request count will | ||
2071 | * be decremented. | ||
2072 | * @device: This is the struct scic_sds_remote_device object to which the io request | ||
2073 | * is being directed. This parameter is not required to complete this | ||
2074 | * operation. | ||
2075 | * @io_request: This is the request that is being completed on this port | ||
2076 | * object. This parameter is not required to complete this operation. | ||
2077 | * | ||
2078 | * This is a general complete io request handler for the struct scic_sds_port object. | ||
2079 | * enum sci_status SCI_SUCCESS | ||
2080 | */ | ||
2081 | static enum sci_status scic_sds_port_general_complete_io_handler( | ||
2082 | struct scic_sds_port *port, | ||
2083 | struct scic_sds_remote_device *device, | ||
2084 | struct scic_sds_request *io_request) | ||
2085 | { | ||
2086 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
2087 | |||
2088 | scic_sds_port_decrement_request_count(this_port); | ||
2089 | |||
2090 | return SCI_SUCCESS; | ||
2091 | } | ||
2092 | |||
2093 | /* | ||
2094 | * **************************************************************************** | ||
2095 | * * STOPPED STATE HANDLERS | ||
2096 | * **************************************************************************** */ | ||
2097 | |||
2098 | /** | ||
2099 | * | ||
2100 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2101 | * object. | ||
2102 | * | ||
2103 | * This method takes the struct scic_sds_port from a stopped state and attempts to | ||
2104 | * start it. To start a port it must have no assiged devices and it must have | ||
2105 | * at least one phy assigned to it. If those conditions are met then the port | ||
2106 | * can transition to the ready state. enum sci_status | ||
2107 | * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION This struct scic_sds_port object could | ||
2108 | * not be started because the port configuration is not valid. SCI_SUCCESS the | ||
2109 | * start request is successful and the struct scic_sds_port object has transitioned to | ||
2110 | * the SCI_BASE_PORT_STATE_READY. | ||
2111 | */ | ||
2112 | static enum sci_status scic_sds_port_stopped_state_start_handler( | ||
2113 | struct sci_base_port *port) | ||
2114 | { | ||
2115 | u32 phy_mask; | ||
2116 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
2117 | |||
2118 | if (this_port->assigned_device_count > 0) { | ||
2119 | /* | ||
2120 | * / @todo This is a start failure operation because there are still | ||
2121 | * / devices assigned to this port. There must be no devices | ||
2122 | * / assigned to a port on a start operation. */ | ||
2123 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
2124 | } | ||
2125 | |||
2126 | phy_mask = scic_sds_port_get_phys(this_port); | ||
2127 | |||
2128 | /* | ||
2129 | * There are one or more phys assigned to this port. Make sure | ||
2130 | * the port's phy mask is in fact legal and supported by the | ||
2131 | * silicon. */ | ||
2132 | if (scic_sds_port_is_phy_mask_valid(this_port, phy_mask) == true) { | ||
2133 | sci_base_state_machine_change_state( | ||
2134 | scic_sds_port_get_base_state_machine(this_port), | ||
2135 | SCI_BASE_PORT_STATE_READY | ||
2136 | ); | ||
2137 | |||
2138 | return SCI_SUCCESS; | ||
2139 | } | ||
2140 | |||
2141 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
2142 | } | ||
2143 | |||
2144 | /** | ||
2145 | * | ||
2146 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2147 | * object. | ||
2148 | * | ||
2149 | * This method takes the struct scic_sds_port that is in a stopped state and handles a | ||
2150 | * stop request. This function takes no action. enum sci_status SCI_SUCCESS the | ||
2151 | * stop request is successful as the struct scic_sds_port object is already stopped. | ||
2152 | */ | ||
2153 | static enum sci_status scic_sds_port_stopped_state_stop_handler( | ||
2154 | struct sci_base_port *port) | ||
2155 | { | ||
2156 | /* We are already stopped so there is nothing to do here */ | ||
2157 | return SCI_SUCCESS; | ||
2158 | } | ||
2159 | |||
2160 | /** | ||
2161 | * | ||
2162 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2163 | * object. | ||
2164 | * | ||
2165 | * This method takes the struct scic_sds_port that is in a stopped state and handles | ||
2166 | * the destruct request. The stopped state is the only state in which the | ||
2167 | * struct scic_sds_port can be destroyed. This function causes the port object to | ||
2168 | * transition to the SCI_BASE_PORT_STATE_FINAL. enum sci_status SCI_SUCCESS | ||
2169 | */ | ||
2170 | static enum sci_status scic_sds_port_stopped_state_destruct_handler( | ||
2171 | struct sci_base_port *port) | ||
2172 | { | ||
2173 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
2174 | |||
2175 | sci_base_state_machine_stop(&this_port->parent.state_machine); | ||
2176 | |||
2177 | return SCI_SUCCESS; | ||
2178 | } | ||
2179 | |||
2180 | /** | ||
2181 | * | ||
2182 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2183 | * object. | ||
2184 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2185 | * object. | ||
2186 | * | ||
2187 | * This method takes the struct scic_sds_port that is in a stopped state and handles | ||
2188 | * the add phy request. In MPC mode the only time a phy can be added to a port | ||
2189 | * is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status | ||
2190 | * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not | ||
2191 | * be added to the port. SCI_SUCCESS if the phy is added to the port. | ||
2192 | */ | ||
2193 | static enum sci_status scic_sds_port_stopped_state_add_phy_handler( | ||
2194 | struct sci_base_port *port, | ||
2195 | struct sci_base_phy *phy) | ||
2196 | { | ||
2197 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
2198 | struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; | ||
2199 | struct sci_sas_address port_sas_address; | ||
2200 | |||
2201 | /* Read the port assigned SAS Address if there is one */ | ||
2202 | scic_sds_port_get_sas_address(this_port, &port_sas_address); | ||
2203 | |||
2204 | if (port_sas_address.high != 0 && port_sas_address.low != 0) { | ||
2205 | struct sci_sas_address phy_sas_address; | ||
2206 | |||
2207 | /* | ||
2208 | * Make sure that the PHY SAS Address matches the SAS Address | ||
2209 | * for this port. */ | ||
2210 | scic_sds_phy_get_sas_address(this_phy, &phy_sas_address); | ||
2211 | |||
2212 | if ( | ||
2213 | (port_sas_address.high != phy_sas_address.high) | ||
2214 | || (port_sas_address.low != phy_sas_address.low) | ||
2215 | ) { | ||
2216 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
2217 | } | ||
2218 | } | ||
2219 | |||
2220 | return scic_sds_port_set_phy(this_port, this_phy); | ||
2221 | } | ||
2222 | |||
2223 | |||
2224 | /** | ||
2225 | * | ||
2226 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2227 | * object. | ||
2228 | * @phy: This is the struct sci_base_phy object which is cast into a struct scic_sds_phy | ||
2229 | * object. | ||
2230 | * | ||
2231 | * This method takes the struct scic_sds_port that is in a stopped state and handles | ||
2232 | * the remove phy request. In MPC mode the only time a phy can be removed from | ||
2233 | * a port is in the SCI_BASE_PORT_STATE_STOPPED. enum sci_status | ||
2234 | * SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION is returned when the phy can not | ||
2235 | * be added to the port. SCI_SUCCESS if the phy is added to the port. | ||
2236 | */ | ||
2237 | static enum sci_status scic_sds_port_stopped_state_remove_phy_handler( | ||
2238 | struct sci_base_port *port, | ||
2239 | struct sci_base_phy *phy) | ||
2240 | { | ||
2241 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
2242 | struct scic_sds_phy *this_phy = (struct scic_sds_phy *)phy; | ||
2243 | |||
2244 | return scic_sds_port_clear_phy(this_port, this_phy); | ||
2245 | } | ||
2246 | |||
2247 | /* | ||
2248 | * **************************************************************************** | ||
2249 | * * READY STATE HANDLERS | ||
2250 | * **************************************************************************** */ | ||
2251 | |||
2252 | /* | ||
2253 | * **************************************************************************** | ||
2254 | * * RESETTING STATE HANDLERS | ||
2255 | * **************************************************************************** */ | ||
2256 | |||
2257 | /* | ||
2258 | * **************************************************************************** | ||
2259 | * * STOPPING STATE HANDLERS | ||
2260 | * **************************************************************************** */ | ||
2261 | |||
2262 | /** | ||
2263 | * | ||
2264 | * @port: This is the struct scic_sds_port object on which the io request count will | ||
2265 | * be decremented. | ||
2266 | * @device: This is the struct scic_sds_remote_device object to which the io request | ||
2267 | * is being directed. This parameter is not required to complete this | ||
2268 | * operation. | ||
2269 | * @io_request: This is the request that is being completed on this port | ||
2270 | * object. This parameter is not required to complete this operation. | ||
2271 | * | ||
2272 | * This method takes the struct scic_sds_port that is in a stopping state and handles | ||
2273 | * the complete io request. Should the request count reach 0 then the port | ||
2274 | * object will transition to the stopped state. enum sci_status SCI_SUCCESS | ||
2275 | */ | ||
2276 | static enum sci_status scic_sds_port_stopping_state_complete_io_handler( | ||
2277 | struct scic_sds_port *port, | ||
2278 | struct scic_sds_remote_device *device, | ||
2279 | struct scic_sds_request *io_request) | ||
2280 | { | ||
2281 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
2282 | |||
2283 | scic_sds_port_decrement_request_count(this_port); | ||
2284 | |||
2285 | if (this_port->started_request_count == 0) { | ||
2286 | sci_base_state_machine_change_state( | ||
2287 | scic_sds_port_get_base_state_machine(this_port), | ||
2288 | SCI_BASE_PORT_STATE_STOPPED | ||
2289 | ); | ||
2290 | } | ||
2291 | |||
2292 | return SCI_SUCCESS; | ||
2293 | } | ||
2294 | |||
2295 | /* | ||
2296 | * **************************************************************************** | ||
2297 | * * RESETTING STATE HANDLERS | ||
2298 | * **************************************************************************** */ | ||
2299 | |||
2300 | /** | ||
2301 | * | ||
2302 | * @port: This is the port object which is being requested to stop. | ||
2303 | * | ||
2304 | * This method will stop a failed port. This causes a transition to the | ||
2305 | * stopping state. enum sci_status SCI_SUCCESS | ||
2306 | */ | ||
2307 | static enum sci_status scic_sds_port_reset_state_stop_handler( | ||
2308 | struct sci_base_port *port) | ||
2309 | { | ||
2310 | struct scic_sds_port *this_port = (struct scic_sds_port *)port; | ||
2311 | |||
2312 | sci_base_state_machine_change_state( | ||
2313 | &this_port->parent.state_machine, | ||
2314 | SCI_BASE_PORT_STATE_STOPPING | ||
2315 | ); | ||
2316 | |||
2317 | return SCI_SUCCESS; | ||
2318 | } | ||
2319 | |||
2320 | /** | ||
2321 | * | ||
2322 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2323 | * object. | ||
2324 | * | ||
2325 | * This method will transition a failed port to its ready state. The port | ||
2326 | * failed because a hard reset request timed out but at some time later one or | ||
2327 | * more phys in the port became ready. enum sci_status SCI_SUCCESS | ||
2328 | */ | ||
2329 | static void scic_sds_port_reset_state_link_up_handler( | ||
2330 | struct scic_sds_port *this_port, | ||
2331 | struct scic_sds_phy *phy) | ||
2332 | { | ||
2333 | /* | ||
2334 | * / @todo We should make sure that the phy that has gone link up is the same | ||
2335 | * / one on which we sent the reset. It is possible that the phy on | ||
2336 | * / which we sent the reset is not the one that has gone link up and we | ||
2337 | * / want to make sure that phy being reset comes back. Consider the | ||
2338 | * / case where a reset is sent but before the hardware processes the | ||
2339 | * / reset it get a link up on the port because of a hot plug event. | ||
2340 | * / because of the reset request this phy will go link down almost | ||
2341 | * / immediately. */ | ||
2342 | |||
2343 | /* | ||
2344 | * In the resetting state we don't notify the user regarding | ||
2345 | * link up and link down notifications. */ | ||
2346 | scic_sds_port_general_link_up_handler(this_port, phy, false); | ||
2347 | } | ||
2348 | |||
2349 | /** | ||
2350 | * | ||
2351 | * @port: This is the struct sci_base_port object which is cast into a struct scic_sds_port | ||
2352 | * object. | ||
2353 | * | ||
2354 | * This method process link down notifications that occur during a port reset | ||
2355 | * operation. Link downs can occur during the reset operation. enum sci_status | ||
2356 | * SCI_SUCCESS | ||
2357 | */ | ||
2358 | static void scic_sds_port_reset_state_link_down_handler( | ||
2359 | struct scic_sds_port *this_port, | ||
2360 | struct scic_sds_phy *phy) | ||
2361 | { | ||
2362 | /* | ||
2363 | * In the resetting state we don't notify the user regarding | ||
2364 | * link up and link down notifications. */ | ||
2365 | scic_sds_port_deactivate_phy(this_port, phy, false); | ||
2366 | } | ||
2367 | |||
2368 | /* --------------------------------------------------------------------------- */ | ||
2369 | |||
2370 | struct scic_sds_port_state_handler | ||
2371 | scic_sds_port_state_handler_table[SCI_BASE_PORT_MAX_STATES] = | ||
2372 | { | ||
2373 | /* SCI_BASE_PORT_STATE_STOPPED */ | ||
2374 | { | ||
2375 | { | ||
2376 | scic_sds_port_stopped_state_start_handler, | ||
2377 | scic_sds_port_stopped_state_stop_handler, | ||
2378 | scic_sds_port_stopped_state_destruct_handler, | ||
2379 | scic_sds_port_default_reset_handler, | ||
2380 | scic_sds_port_stopped_state_add_phy_handler, | ||
2381 | scic_sds_port_stopped_state_remove_phy_handler | ||
2382 | }, | ||
2383 | scic_sds_port_default_frame_handler, | ||
2384 | scic_sds_port_default_event_handler, | ||
2385 | scic_sds_port_default_link_up_handler, | ||
2386 | scic_sds_port_default_link_down_handler, | ||
2387 | scic_sds_port_default_start_io_handler, | ||
2388 | scic_sds_port_default_complete_io_handler | ||
2389 | }, | ||
2390 | /* SCI_BASE_PORT_STATE_STOPPING */ | ||
2391 | { | ||
2392 | { | ||
2393 | scic_sds_port_default_start_handler, | ||
2394 | scic_sds_port_default_stop_handler, | ||
2395 | scic_sds_port_default_destruct_handler, | ||
2396 | scic_sds_port_default_reset_handler, | ||
2397 | scic_sds_port_default_add_phy_handler, | ||
2398 | scic_sds_port_default_remove_phy_handler | ||
2399 | }, | ||
2400 | scic_sds_port_default_frame_handler, | ||
2401 | scic_sds_port_default_event_handler, | ||
2402 | scic_sds_port_default_link_up_handler, | ||
2403 | scic_sds_port_default_link_down_handler, | ||
2404 | scic_sds_port_default_start_io_handler, | ||
2405 | scic_sds_port_stopping_state_complete_io_handler | ||
2406 | }, | ||
2407 | /* SCI_BASE_PORT_STATE_READY */ | ||
2408 | { | ||
2409 | { | ||
2410 | scic_sds_port_default_start_handler, | ||
2411 | scic_sds_port_default_stop_handler, | ||
2412 | scic_sds_port_default_destruct_handler, | ||
2413 | scic_sds_port_default_reset_handler, | ||
2414 | scic_sds_port_default_add_phy_handler, | ||
2415 | scic_sds_port_default_remove_phy_handler | ||
2416 | }, | ||
2417 | scic_sds_port_default_frame_handler, | ||
2418 | scic_sds_port_default_event_handler, | ||
2419 | scic_sds_port_default_link_up_handler, | ||
2420 | scic_sds_port_default_link_down_handler, | ||
2421 | scic_sds_port_default_start_io_handler, | ||
2422 | scic_sds_port_general_complete_io_handler | ||
2423 | }, | ||
2424 | /* SCI_BASE_PORT_STATE_RESETTING */ | ||
2425 | { | ||
2426 | { | ||
2427 | scic_sds_port_default_start_handler, | ||
2428 | scic_sds_port_reset_state_stop_handler, | ||
2429 | scic_sds_port_default_destruct_handler, | ||
2430 | scic_sds_port_default_reset_handler, | ||
2431 | scic_sds_port_default_add_phy_handler, | ||
2432 | scic_sds_port_default_remove_phy_handler | ||
2433 | }, | ||
2434 | scic_sds_port_default_frame_handler, | ||
2435 | scic_sds_port_default_event_handler, | ||
2436 | scic_sds_port_reset_state_link_up_handler, | ||
2437 | scic_sds_port_reset_state_link_down_handler, | ||
2438 | scic_sds_port_default_start_io_handler, | ||
2439 | scic_sds_port_general_complete_io_handler | ||
2440 | }, | ||
2441 | /* SCI_BASE_PORT_STATE_FAILED */ | ||
2442 | { | ||
2443 | { | ||
2444 | scic_sds_port_default_start_handler, | ||
2445 | scic_sds_port_default_stop_handler, | ||
2446 | scic_sds_port_default_destruct_handler, | ||
2447 | scic_sds_port_default_reset_handler, | ||
2448 | scic_sds_port_default_add_phy_handler, | ||
2449 | scic_sds_port_default_remove_phy_handler | ||
2450 | }, | ||
2451 | scic_sds_port_default_frame_handler, | ||
2452 | scic_sds_port_default_event_handler, | ||
2453 | scic_sds_port_default_link_up_handler, | ||
2454 | scic_sds_port_default_link_down_handler, | ||
2455 | scic_sds_port_default_start_io_handler, | ||
2456 | scic_sds_port_general_complete_io_handler | ||
2457 | } | ||
2458 | }; | ||
2459 | |||
2460 | /* | ||
2461 | * ****************************************************************************** | ||
2462 | * * PORT STATE PRIVATE METHODS | ||
2463 | * ****************************************************************************** */ | ||
2464 | |||
2465 | /** | ||
2466 | * | ||
2467 | * @this_port: This is the port object which to suspend. | ||
2468 | * | ||
2469 | * This method will enable the SCU Port Task Scheduler for this port object but | ||
2470 | * will leave the port task scheduler in a suspended state. none | ||
2471 | */ | ||
2472 | static void scic_sds_port_enable_port_task_scheduler( | ||
2473 | struct scic_sds_port *this_port) | ||
2474 | { | ||
2475 | u32 pts_control_value; | ||
2476 | |||
2477 | pts_control_value = scu_port_task_scheduler_read(this_port, control); | ||
2478 | |||
2479 | pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND); | ||
2480 | |||
2481 | scu_port_task_scheduler_write(this_port, control, pts_control_value); | ||
2482 | } | ||
2483 | |||
2484 | /** | ||
2485 | * | ||
2486 | * @this_port: This is the port object which to resume. | ||
2487 | * | ||
2488 | * This method will disable the SCU port task scheduler for this port object. | ||
2489 | * none | ||
2490 | */ | ||
2491 | static void scic_sds_port_disable_port_task_scheduler( | ||
2492 | struct scic_sds_port *this_port) | ||
2493 | { | ||
2494 | u32 pts_control_value; | ||
2495 | |||
2496 | pts_control_value = scu_port_task_scheduler_read(this_port, control); | ||
2497 | |||
2498 | pts_control_value &= ~(SCU_PTSxCR_GEN_BIT(ENABLE) | ||
2499 | | SCU_PTSxCR_GEN_BIT(SUSPEND)); | ||
2500 | |||
2501 | scu_port_task_scheduler_write(this_port, control, pts_control_value); | ||
2502 | } | ||
2503 | |||
2504 | /* | ||
2505 | * ****************************************************************************** | ||
2506 | * * PORT STATE METHODS | ||
2507 | * ****************************************************************************** */ | ||
2508 | |||
2509 | /** | ||
2510 | * | ||
2511 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2512 | * | ||
2513 | * This method will perform the actions required by the struct scic_sds_port on | ||
2514 | * entering the SCI_BASE_PORT_STATE_STOPPED. This function sets the stopped | ||
2515 | * state handlers for the struct scic_sds_port object and disables the port task | ||
2516 | * scheduler in the hardware. none | ||
2517 | */ | ||
2518 | static void scic_sds_port_stopped_state_enter( | ||
2519 | struct sci_base_object *object) | ||
2520 | { | ||
2521 | struct scic_sds_port *this_port; | ||
2522 | |||
2523 | this_port = (struct scic_sds_port *)object; | ||
2524 | |||
2525 | scic_sds_port_set_base_state_handlers( | ||
2526 | this_port, SCI_BASE_PORT_STATE_STOPPED | ||
2527 | ); | ||
2528 | |||
2529 | if ( | ||
2530 | SCI_BASE_PORT_STATE_STOPPING | ||
2531 | == this_port->parent.state_machine.previous_state_id | ||
2532 | ) { | ||
2533 | /* | ||
2534 | * If we enter this state becasuse of a request to stop | ||
2535 | * the port then we want to disable the hardwares port | ||
2536 | * task scheduler. */ | ||
2537 | scic_sds_port_disable_port_task_scheduler(this_port); | ||
2538 | } | ||
2539 | } | ||
2540 | |||
2541 | /** | ||
2542 | * | ||
2543 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2544 | * | ||
2545 | * This method will perform the actions required by the struct scic_sds_port on | ||
2546 | * exiting the SCI_BASE_STATE_STOPPED. This function enables the SCU hardware | ||
2547 | * port task scheduler. none | ||
2548 | */ | ||
2549 | static void scic_sds_port_stopped_state_exit( | ||
2550 | struct sci_base_object *object) | ||
2551 | { | ||
2552 | struct scic_sds_port *this_port; | ||
2553 | |||
2554 | this_port = (struct scic_sds_port *)object; | ||
2555 | |||
2556 | /* Enable and suspend the port task scheduler */ | ||
2557 | scic_sds_port_enable_port_task_scheduler(this_port); | ||
2558 | } | ||
2559 | |||
2560 | /** | ||
2561 | * | ||
2562 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2563 | * | ||
2564 | * This method will perform the actions required by the struct scic_sds_port on | ||
2565 | * entering the SCI_BASE_PORT_STATE_READY. This function sets the ready state | ||
2566 | * handlers for the struct scic_sds_port object, reports the port object as not ready | ||
2567 | * and starts the ready substate machine. none | ||
2568 | */ | ||
2569 | static void scic_sds_port_ready_state_enter( | ||
2570 | struct sci_base_object *object) | ||
2571 | { | ||
2572 | struct scic_sds_port *this_port; | ||
2573 | |||
2574 | this_port = (struct scic_sds_port *)object; | ||
2575 | |||
2576 | /* Put the ready state handlers in place though they will not be there long */ | ||
2577 | scic_sds_port_set_base_state_handlers( | ||
2578 | this_port, SCI_BASE_PORT_STATE_READY | ||
2579 | ); | ||
2580 | |||
2581 | if ( | ||
2582 | SCI_BASE_PORT_STATE_RESETTING | ||
2583 | == this_port->parent.state_machine.previous_state_id | ||
2584 | ) { | ||
2585 | scic_cb_port_hard_reset_complete( | ||
2586 | scic_sds_port_get_controller(this_port), | ||
2587 | this_port, | ||
2588 | SCI_SUCCESS | ||
2589 | ); | ||
2590 | } else { | ||
2591 | /* Notify the caller that the port is not yet ready */ | ||
2592 | scic_cb_port_not_ready( | ||
2593 | scic_sds_port_get_controller(this_port), | ||
2594 | this_port, | ||
2595 | SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS | ||
2596 | ); | ||
2597 | } | ||
2598 | |||
2599 | /* Start the ready substate machine */ | ||
2600 | sci_base_state_machine_start( | ||
2601 | scic_sds_port_get_ready_substate_machine(this_port) | ||
2602 | ); | ||
2603 | } | ||
2604 | |||
2605 | /** | ||
2606 | * | ||
2607 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2608 | * | ||
2609 | * This method will perform the actions required by the struct scic_sds_port on | ||
2610 | * exiting the SCI_BASE_STATE_READY. This function does nothing. none | ||
2611 | */ | ||
2612 | static void scic_sds_port_ready_state_exit( | ||
2613 | struct sci_base_object *object) | ||
2614 | { | ||
2615 | struct scic_sds_port *this_port; | ||
2616 | |||
2617 | this_port = (struct scic_sds_port *)object; | ||
2618 | |||
2619 | sci_base_state_machine_stop(&this_port->ready_substate_machine); | ||
2620 | } | ||
2621 | |||
2622 | /** | ||
2623 | * | ||
2624 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2625 | * | ||
2626 | * This method will perform the actions required by the struct scic_sds_port on | ||
2627 | * entering the SCI_BASE_PORT_STATE_RESETTING. This function sets the resetting | ||
2628 | * state handlers for the struct scic_sds_port object. none | ||
2629 | */ | ||
2630 | static void scic_sds_port_resetting_state_enter( | ||
2631 | struct sci_base_object *object) | ||
2632 | { | ||
2633 | struct scic_sds_port *this_port; | ||
2634 | |||
2635 | this_port = (struct scic_sds_port *)object; | ||
2636 | |||
2637 | scic_sds_port_set_base_state_handlers( | ||
2638 | this_port, SCI_BASE_PORT_STATE_RESETTING | ||
2639 | ); | ||
2640 | |||
2641 | scic_sds_port_set_direct_attached_device_id( | ||
2642 | this_port, | ||
2643 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | ||
2644 | ); | ||
2645 | } | ||
2646 | |||
2647 | /** | ||
2648 | * | ||
2649 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2650 | * | ||
2651 | * This method will perform the actions required by the struct scic_sds_port on | ||
2652 | * exiting the SCI_BASE_STATE_RESETTING. This function does nothing. none | ||
2653 | */ | ||
2654 | static void scic_sds_port_resetting_state_exit( | ||
2655 | struct sci_base_object *object) | ||
2656 | { | ||
2657 | struct scic_sds_port *this_port; | ||
2658 | |||
2659 | this_port = (struct scic_sds_port *)object; | ||
2660 | |||
2661 | scic_cb_timer_stop( | ||
2662 | scic_sds_port_get_controller(this_port), | ||
2663 | this_port->timer_handle | ||
2664 | ); | ||
2665 | } | ||
2666 | |||
2667 | /** | ||
2668 | * | ||
2669 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2670 | * | ||
2671 | * This method will perform the actions required by the struct scic_sds_port on | ||
2672 | * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping | ||
2673 | * state handlers for the struct scic_sds_port object. none | ||
2674 | */ | ||
2675 | static void scic_sds_port_stopping_state_enter( | ||
2676 | struct sci_base_object *object) | ||
2677 | { | ||
2678 | struct scic_sds_port *this_port; | ||
2679 | |||
2680 | this_port = (struct scic_sds_port *)object; | ||
2681 | |||
2682 | scic_sds_port_set_base_state_handlers( | ||
2683 | this_port, SCI_BASE_PORT_STATE_STOPPING | ||
2684 | ); | ||
2685 | } | ||
2686 | |||
2687 | /** | ||
2688 | * | ||
2689 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2690 | * | ||
2691 | * This method will perform the actions required by the struct scic_sds_port on | ||
2692 | * exiting the SCI_BASE_STATE_STOPPING. This function does nothing. none | ||
2693 | */ | ||
2694 | static void scic_sds_port_stopping_state_exit( | ||
2695 | struct sci_base_object *object) | ||
2696 | { | ||
2697 | struct scic_sds_port *this_port; | ||
2698 | |||
2699 | this_port = (struct scic_sds_port *)object; | ||
2700 | |||
2701 | scic_cb_timer_stop( | ||
2702 | scic_sds_port_get_controller(this_port), | ||
2703 | this_port->timer_handle | ||
2704 | ); | ||
2705 | } | ||
2706 | |||
2707 | /** | ||
2708 | * | ||
2709 | * @object: This is the struct sci_base_object which is cast to a struct scic_sds_port object. | ||
2710 | * | ||
2711 | * This method will perform the actions required by the struct scic_sds_port on | ||
2712 | * entering the SCI_BASE_PORT_STATE_STOPPING. This function sets the stopping | ||
2713 | * state handlers for the struct scic_sds_port object. none | ||
2714 | */ | ||
2715 | static void scic_sds_port_failed_state_enter( | ||
2716 | struct sci_base_object *object) | ||
2717 | { | ||
2718 | struct scic_sds_port *this_port; | ||
2719 | |||
2720 | this_port = (struct scic_sds_port *)object; | ||
2721 | |||
2722 | scic_sds_port_set_base_state_handlers( | ||
2723 | this_port, | ||
2724 | SCI_BASE_PORT_STATE_FAILED | ||
2725 | ); | ||
2726 | |||
2727 | scic_cb_port_hard_reset_complete( | ||
2728 | scic_sds_port_get_controller(this_port), | ||
2729 | this_port, | ||
2730 | SCI_FAILURE_TIMEOUT | ||
2731 | ); | ||
2732 | } | ||
2733 | |||
2734 | /* --------------------------------------------------------------------------- */ | ||
2735 | |||
2736 | const struct sci_base_state scic_sds_port_state_table[] = { | ||
2737 | [SCI_BASE_PORT_STATE_STOPPED] = { | ||
2738 | .enter_state = scic_sds_port_stopped_state_enter, | ||
2739 | .exit_state = scic_sds_port_stopped_state_exit | ||
2740 | }, | ||
2741 | [SCI_BASE_PORT_STATE_STOPPING] = { | ||
2742 | .enter_state = scic_sds_port_stopping_state_enter, | ||
2743 | .exit_state = scic_sds_port_stopping_state_exit | ||
2744 | }, | ||
2745 | [SCI_BASE_PORT_STATE_READY] = { | ||
2746 | .enter_state = scic_sds_port_ready_state_enter, | ||
2747 | .exit_state = scic_sds_port_ready_state_exit | ||
2748 | }, | ||
2749 | [SCI_BASE_PORT_STATE_RESETTING] = { | ||
2750 | .enter_state = scic_sds_port_resetting_state_enter, | ||
2751 | .exit_state = scic_sds_port_resetting_state_exit | ||
2752 | }, | ||
2753 | [SCI_BASE_PORT_STATE_FAILED] = { | ||
2754 | .enter_state = scic_sds_port_failed_state_enter, | ||
2755 | } | ||
2756 | }; | ||
2757 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_port.h b/drivers/scsi/isci/core/scic_sds_port.h new file mode 100644 index 000000000000..bbb9de5228ed --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port.h | |||
@@ -0,0 +1,514 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_PORT_H_ | ||
57 | #define _SCIC_SDS_PORT_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants and prototypes for the | ||
61 | * struct scic_sds_port object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_controller_constants.h" | ||
67 | #include "intel_sas.h" | ||
68 | #include "sci_base_port.h" | ||
69 | #include "sci_base_phy.h" | ||
70 | #include "scu_registers.h" | ||
71 | |||
72 | #define SCIC_SDS_DUMMY_PORT 0xFF | ||
73 | |||
74 | /** | ||
75 | * enum SCIC_SDS_PORT_READY_SUBSTATES - | ||
76 | * | ||
77 | * This enumeration depicts all of the states for the core port ready substate | ||
78 | * machine. | ||
79 | */ | ||
80 | enum SCIC_SDS_PORT_READY_SUBSTATES { | ||
81 | /** | ||
82 | * The substate where the port is started and ready but has no active phys. | ||
83 | */ | ||
84 | SCIC_SDS_PORT_READY_SUBSTATE_WAITING, | ||
85 | |||
86 | /** | ||
87 | * The substate where the port is started and ready and there is at least one | ||
88 | * phy operational. | ||
89 | */ | ||
90 | SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, | ||
91 | |||
92 | /** | ||
93 | * The substate where the port is started and there was an add/remove phy | ||
94 | * event. This state is only used in Automatic Port Configuration Mode (APC) | ||
95 | */ | ||
96 | SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, | ||
97 | |||
98 | SCIC_SDS_PORT_READY_MAX_SUBSTATES | ||
99 | }; | ||
100 | |||
101 | struct scic_sds_controller; | ||
102 | struct scic_sds_phy; | ||
103 | struct scic_sds_remote_device; | ||
104 | struct scic_sds_request; | ||
105 | |||
106 | /** | ||
107 | * struct scic_sds_port - | ||
108 | * | ||
109 | * The core port object provides the the abstraction for an SCU port. | ||
110 | */ | ||
111 | struct scic_sds_port { | ||
112 | /** | ||
113 | * This field is the oommon base port object. | ||
114 | */ | ||
115 | struct sci_base_port parent; | ||
116 | |||
117 | /** | ||
118 | * This field is the port index that is reported to the SCI USER. This allows | ||
119 | * the actual hardware physical port to change without the SCI USER getting a | ||
120 | * different answer for the get port index. | ||
121 | */ | ||
122 | u8 logical_port_index; | ||
123 | |||
124 | /** | ||
125 | * This field is the port index used to program the SCU hardware. | ||
126 | */ | ||
127 | u8 physical_port_index; | ||
128 | |||
129 | /** | ||
130 | * This field contains the active phy mask for the port. This mask is used in | ||
131 | * conjunction with the phy state to determine which phy to select for some | ||
132 | * port operations. | ||
133 | */ | ||
134 | u8 active_phy_mask; | ||
135 | |||
136 | /** | ||
137 | * This field contains the count of the io requests started on this port | ||
138 | * object. It is used to control controller shutdown. | ||
139 | */ | ||
140 | u32 started_request_count; | ||
141 | |||
142 | /** | ||
143 | * This field contains the number of devices assigned to this port. It is | ||
144 | * used to control port start requests. | ||
145 | */ | ||
146 | u32 assigned_device_count; | ||
147 | |||
148 | /** | ||
149 | * This field contains the reason for the port not going ready. It is | ||
150 | * assigned in the state handlers and used in the state transition. | ||
151 | */ | ||
152 | u32 not_ready_reason; | ||
153 | |||
154 | /** | ||
155 | * This field is the table of phys assigned to the port. | ||
156 | */ | ||
157 | struct scic_sds_phy *phy_table[SCI_MAX_PHYS]; | ||
158 | |||
159 | /** | ||
160 | * This field is a pointer back to the controller that owns this port object. | ||
161 | */ | ||
162 | struct scic_sds_controller *owning_controller; | ||
163 | |||
164 | /** | ||
165 | * This field contains the port start/stop timer handle. | ||
166 | */ | ||
167 | void *timer_handle; | ||
168 | |||
169 | /** | ||
170 | * This field points to the current set of state handlers for this port | ||
171 | * object. These state handlers are assigned at each enter state of the state | ||
172 | * machine. | ||
173 | */ | ||
174 | struct scic_sds_port_state_handler *state_handlers; | ||
175 | |||
176 | /** | ||
177 | * This field is the ready substate machine for the port. | ||
178 | */ | ||
179 | struct sci_base_state_machine ready_substate_machine; | ||
180 | |||
181 | /* / Memory mapped hardware register space */ | ||
182 | /** | ||
183 | * This field is the pointer to the transport layer register for the SCU | ||
184 | * hardware. | ||
185 | */ | ||
186 | struct scu_transport_layer_registers *transport_layer_registers; | ||
187 | |||
188 | /** | ||
189 | * This field is the pointer to the port task scheduler registers for the SCU | ||
190 | * hardware. | ||
191 | */ | ||
192 | struct scu_port_task_scheduler_registers *port_task_scheduler_registers; | ||
193 | |||
194 | /** | ||
195 | * This field is identical for all port objects and points to the port task | ||
196 | * scheduler group PE configuration registers. It is used to assign PEs to a | ||
197 | * port. | ||
198 | */ | ||
199 | SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register; | ||
200 | |||
201 | /** | ||
202 | * This field is the VIIT register space for ths port object. | ||
203 | */ | ||
204 | struct scu_viit_entry *viit_registers; | ||
205 | |||
206 | }; | ||
207 | |||
208 | |||
209 | typedef enum sci_status (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct scic_sds_port *, u32); | ||
210 | |||
211 | typedef enum sci_status (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct scic_sds_port *, u32); | ||
212 | |||
213 | typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct scic_sds_port *, struct scic_sds_phy *); | ||
214 | |||
215 | typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)( | ||
216 | struct scic_sds_port *, | ||
217 | struct scic_sds_remote_device *, | ||
218 | struct scic_sds_request *); | ||
219 | |||
220 | struct scic_sds_port_state_handler { | ||
221 | struct sci_base_port_state_handler parent; | ||
222 | |||
223 | SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler; | ||
224 | SCIC_SDS_PORT_EVENT_HANDLER_T event_handler; | ||
225 | |||
226 | SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler; | ||
227 | SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler; | ||
228 | |||
229 | SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler; | ||
230 | SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler; | ||
231 | |||
232 | }; | ||
233 | |||
234 | extern const struct sci_base_state scic_sds_port_state_table[]; | ||
235 | extern const struct sci_base_state scic_sds_port_ready_substate_table[]; | ||
236 | |||
237 | extern struct scic_sds_port_state_handler scic_sds_port_state_handler_table[]; | ||
238 | extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[]; | ||
239 | |||
240 | /** | ||
241 | * scic_sds_port_get_controller() - | ||
242 | * | ||
243 | * Helper macro to get the owning controller of this port | ||
244 | */ | ||
245 | #define scic_sds_port_get_controller(this_port) \ | ||
246 | ((this_port)->owning_controller) | ||
247 | |||
248 | /** | ||
249 | * scic_sds_port_get_base_state_machine() - | ||
250 | * | ||
251 | * Helper macro to get the base state machine for this port | ||
252 | */ | ||
253 | #define scic_sds_port_get_base_state_machine(this_port) \ | ||
254 | (&(this_port)->parent.state_machine) | ||
255 | |||
256 | /** | ||
257 | * scic_sds_port_set_base_state_handlers() - | ||
258 | * | ||
259 | * This macro will change the state handlers to those of the specified state id | ||
260 | */ | ||
261 | #define scic_sds_port_set_base_state_handlers(this_port, state_id) \ | ||
262 | scic_sds_port_set_state_handlers(\ | ||
263 | (this_port), &scic_sds_port_state_handler_table[(state_id)]) | ||
264 | |||
265 | /** | ||
266 | * scic_sds_port_get_ready_substate_machine() - | ||
267 | * | ||
268 | * Helper macro to get the ready substate machine for this port | ||
269 | */ | ||
270 | #define scic_sds_port_get_ready_substate_machine(this_port) \ | ||
271 | (&(this_port)->ready_substate_machine) | ||
272 | |||
273 | /** | ||
274 | * scic_sds_port_set_state_handlers() - | ||
275 | * | ||
276 | * Helper macro to set the port object state handlers | ||
277 | */ | ||
278 | #define scic_sds_port_set_state_handlers(this_port, handlers) \ | ||
279 | ((this_port)->state_handlers = (handlers)) | ||
280 | |||
281 | /** | ||
282 | * scic_sds_port_get_index() - | ||
283 | * | ||
284 | * This macro returns the physical port index for this port object | ||
285 | */ | ||
286 | #define scic_sds_port_get_index(this_port) \ | ||
287 | ((this_port)->physical_port_index) | ||
288 | |||
289 | /** | ||
290 | * scic_sds_port_increment_request_count() - | ||
291 | * | ||
292 | * Helper macro to increment the started request count | ||
293 | */ | ||
294 | #define scic_sds_port_increment_request_count(this_port) \ | ||
295 | ((this_port)->started_request_count++) | ||
296 | |||
297 | #ifdef SCIC_DEBUG_ENABLED | ||
298 | /** | ||
299 | * scic_sds_port_decrement_request_count() - This method decrements the started | ||
300 | * io request count. The method will not decrment the started io request | ||
301 | * count below 0 and will log a debug message if this is attempted. | ||
302 | * | ||
303 | * | ||
304 | */ | ||
305 | void scic_sds_port_decrement_request_count( | ||
306 | struct scic_sds_port *this_port); | ||
307 | #else | ||
308 | /** | ||
309 | * scic_sds_port_decrement_request_count() - | ||
310 | * | ||
311 | * Helper macro to decrement the started io request count. The macro will not | ||
312 | * decrement the started io request count below 0. | ||
313 | */ | ||
314 | #define scic_sds_port_decrement_request_count(this_port) \ | ||
315 | (\ | ||
316 | (this_port)->started_request_count = (\ | ||
317 | ((this_port)->started_request_count == 0) ? \ | ||
318 | (this_port)->started_request_count : \ | ||
319 | ((this_port)->started_request_count - 1) \ | ||
320 | ) \ | ||
321 | ) | ||
322 | #endif | ||
323 | |||
324 | /** | ||
325 | * scic_sds_port_write_phy_assignment() - | ||
326 | * | ||
327 | * Helper macro to write the phys port assignment | ||
328 | */ | ||
329 | #define scic_sds_port_write_phy_assignment(port, phy) \ | ||
330 | SCU_PCSPExCR_WRITE(\ | ||
331 | (port), \ | ||
332 | (phy)->phy_index, \ | ||
333 | (port)->physical_port_index \ | ||
334 | ) | ||
335 | |||
336 | /** | ||
337 | * scic_sds_port_read_phy_assignment() - | ||
338 | * | ||
339 | * Helper macro to read the phys port assignment | ||
340 | */ | ||
341 | #define scic_sds_port_read_phy_assignment(port, phy) \ | ||
342 | SCU_PCSPExCR_READ(\ | ||
343 | (port), \ | ||
344 | (phy)->phy_index \ | ||
345 | ) | ||
346 | |||
347 | #define scic_sds_port_active_phy(port, phy) \ | ||
348 | (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) | ||
349 | |||
350 | /* --------------------------------------------------------------------------- */ | ||
351 | |||
352 | |||
353 | |||
354 | |||
355 | /* --------------------------------------------------------------------------- */ | ||
356 | |||
357 | /* --------------------------------------------------------------------------- */ | ||
358 | |||
359 | void scic_sds_port_construct( | ||
360 | struct scic_sds_port *this_port, | ||
361 | u8 port_index, | ||
362 | struct scic_sds_controller *owning_controller); | ||
363 | |||
364 | enum sci_status scic_sds_port_initialize( | ||
365 | struct scic_sds_port *this_port, | ||
366 | void *transport_layer_registers, | ||
367 | void *port_task_scheduler_registers, | ||
368 | void *port_configuration_regsiter, | ||
369 | void *viit_registers); | ||
370 | |||
371 | /* --------------------------------------------------------------------------- */ | ||
372 | |||
373 | enum sci_status scic_sds_port_add_phy( | ||
374 | struct scic_sds_port *this_port, | ||
375 | struct scic_sds_phy *the_phy); | ||
376 | |||
377 | enum sci_status scic_sds_port_remove_phy( | ||
378 | struct scic_sds_port *this_port, | ||
379 | struct scic_sds_phy *the_phy); | ||
380 | |||
381 | void scic_sds_port_set_direct_attached_device_id( | ||
382 | struct scic_sds_port *this_port, | ||
383 | u32 device_id); | ||
384 | |||
385 | void scic_sds_port_activate_phy( | ||
386 | struct scic_sds_port *this_port, | ||
387 | struct scic_sds_phy *phy, | ||
388 | bool do_notify_user); | ||
389 | |||
390 | void scic_sds_port_deactivate_phy( | ||
391 | struct scic_sds_port *this_port, | ||
392 | struct scic_sds_phy *phy, | ||
393 | bool do_notify_user); | ||
394 | |||
395 | |||
396 | |||
397 | void scic_sds_port_general_link_up_handler( | ||
398 | struct scic_sds_port *this_port, | ||
399 | struct scic_sds_phy *the_phy, | ||
400 | bool do_notify_user); | ||
401 | |||
402 | bool scic_sds_port_link_detected( | ||
403 | struct scic_sds_port *this_port, | ||
404 | struct scic_sds_phy *phy); | ||
405 | |||
406 | void scic_sds_port_link_up( | ||
407 | struct scic_sds_port *this_port, | ||
408 | struct scic_sds_phy *phy); | ||
409 | |||
410 | void scic_sds_port_link_down( | ||
411 | struct scic_sds_port *this_port, | ||
412 | struct scic_sds_phy *phy); | ||
413 | |||
414 | /* --------------------------------------------------------------------------- */ | ||
415 | |||
416 | |||
417 | /* --------------------------------------------------------------------------- */ | ||
418 | |||
419 | enum sci_status scic_sds_port_start_io( | ||
420 | struct scic_sds_port *this_port, | ||
421 | struct scic_sds_remote_device *the_device, | ||
422 | struct scic_sds_request *the_io_request); | ||
423 | |||
424 | enum sci_status scic_sds_port_complete_io( | ||
425 | struct scic_sds_port *this_port, | ||
426 | struct scic_sds_remote_device *the_device, | ||
427 | struct scic_sds_request *the_io_request); | ||
428 | |||
429 | /* --------------------------------------------------------------------------- */ | ||
430 | |||
431 | void scic_sds_port_update_viit_entry( | ||
432 | struct scic_sds_port *this_port); | ||
433 | |||
434 | /* --------------------------------------------------------------------------- */ | ||
435 | |||
436 | enum sci_status scic_sds_port_default_start_handler( | ||
437 | struct sci_base_port *port); | ||
438 | |||
439 | |||
440 | enum sci_status scic_sds_port_default_destruct_handler( | ||
441 | struct sci_base_port *port); | ||
442 | |||
443 | enum sci_status scic_sds_port_default_reset_handler( | ||
444 | struct sci_base_port *port, | ||
445 | u32 timeout); | ||
446 | |||
447 | |||
448 | enum sci_status scic_sds_port_default_remove_phy_handler( | ||
449 | struct sci_base_port *port, | ||
450 | struct sci_base_phy *phy); | ||
451 | |||
452 | enum sci_status scic_sds_port_default_frame_handler( | ||
453 | struct scic_sds_port *port, | ||
454 | u32 frame_index); | ||
455 | |||
456 | enum sci_status scic_sds_port_default_event_handler( | ||
457 | struct scic_sds_port *port, | ||
458 | u32 event_code); | ||
459 | |||
460 | void scic_sds_port_default_link_up_handler( | ||
461 | struct scic_sds_port *this_port, | ||
462 | struct scic_sds_phy *phy); | ||
463 | |||
464 | void scic_sds_port_default_link_down_handler( | ||
465 | struct scic_sds_port *this_port, | ||
466 | struct scic_sds_phy *phy); | ||
467 | |||
468 | enum sci_status scic_sds_port_default_start_io_handler( | ||
469 | struct scic_sds_port *port, | ||
470 | struct scic_sds_remote_device *device, | ||
471 | struct scic_sds_request *io_request); | ||
472 | |||
473 | |||
474 | enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed( | ||
475 | struct scic_sds_port *this_port); | ||
476 | |||
477 | void scic_sds_port_broadcast_change_received( | ||
478 | struct scic_sds_port *this_port, | ||
479 | struct scic_sds_phy *this_phy); | ||
480 | |||
481 | bool scic_sds_port_is_valid_phy_assignment( | ||
482 | struct scic_sds_port *this_port, | ||
483 | u32 phy_index); | ||
484 | |||
485 | bool scic_sds_port_is_phy_mask_valid( | ||
486 | struct scic_sds_port *this_port, | ||
487 | u32 phy_mask); | ||
488 | |||
489 | u32 scic_sds_port_get_phys( | ||
490 | struct scic_sds_port *this_port); | ||
491 | |||
492 | void scic_sds_port_get_sas_address( | ||
493 | struct scic_sds_port *this_port, | ||
494 | struct sci_sas_address *sas_address); | ||
495 | |||
496 | void scic_sds_port_get_attached_sas_address( | ||
497 | struct scic_sds_port *this_port, | ||
498 | struct sci_sas_address *sas_address); | ||
499 | |||
500 | void scic_sds_port_get_attached_protocols( | ||
501 | struct scic_sds_port *this_port, | ||
502 | struct sci_sas_identify_address_frame_protocols *protocols); | ||
503 | |||
504 | enum sci_status scic_sds_port_set_phy( | ||
505 | struct scic_sds_port *port, | ||
506 | struct scic_sds_phy *phy); | ||
507 | |||
508 | enum sci_status scic_sds_port_clear_phy( | ||
509 | struct scic_sds_port *port, | ||
510 | struct scic_sds_phy *phy); | ||
511 | |||
512 | |||
513 | |||
514 | #endif /* _SCIC_SDS_PORT_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c new file mode 100644 index 000000000000..37d4469162a7 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.c | |||
@@ -0,0 +1,851 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the implementation for the public and protected methods | ||
58 | * for the port configuration agent. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #include "sci_environment.h" | ||
64 | #include "scic_controller.h" | ||
65 | #include "scic_sds_controller.h" | ||
66 | #include "scic_sds_port_configuration_agent.h" | ||
67 | |||
68 | #define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10) | ||
69 | #define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10) | ||
70 | #define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100) | ||
71 | |||
72 | enum SCIC_SDS_APC_ACTIVITY { | ||
73 | SCIC_SDS_APC_SKIP_PHY, | ||
74 | SCIC_SDS_APC_ADD_PHY, | ||
75 | SCIC_SDS_APC_START_TIMER, | ||
76 | |||
77 | SCIC_SDS_APC_ACTIVITY_MAX | ||
78 | }; | ||
79 | |||
80 | /* | ||
81 | * ****************************************************************************** | ||
82 | * General port configuration agent routines | ||
83 | * ****************************************************************************** */ | ||
84 | |||
85 | /** | ||
86 | * | ||
87 | * @address_one: A SAS Address to be compared. | ||
88 | * @address_two: A SAS Address to be compared. | ||
89 | * | ||
90 | * Compare the two SAS Address and if SAS Address One is greater than SAS | ||
91 | * Address Two then return > 0 else if SAS Address One is less than SAS Address | ||
92 | * Two return < 0 Otherwise they are the same return 0 A signed value of x > 0 | ||
93 | * > y where x is returned for Address One > Address Two y is returned for | ||
94 | * Address One < Address Two 0 is returned ofr Address One = Address Two | ||
95 | */ | ||
96 | static s32 sci_sas_address_compare( | ||
97 | struct sci_sas_address address_one, | ||
98 | struct sci_sas_address address_two) | ||
99 | { | ||
100 | if (address_one.high > address_two.high) { | ||
101 | return 1; | ||
102 | } else if (address_one.high < address_two.high) { | ||
103 | return -1; | ||
104 | } else if (address_one.low > address_two.low) { | ||
105 | return 1; | ||
106 | } else if (address_one.low < address_two.low) { | ||
107 | return -1; | ||
108 | } | ||
109 | |||
110 | /* The two SAS Address must be identical */ | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * | ||
116 | * @controller: The controller object used for the port search. | ||
117 | * @phy: The phy object to match. | ||
118 | * | ||
119 | * This routine will find a matching port for the phy. This means that the | ||
120 | * port and phy both have the same broadcast sas address and same received sas | ||
121 | * address. The port address or the SCI_INVALID_HANDLE if there is no matching | ||
122 | * port. port address if the port can be found to match the phy. | ||
123 | * SCI_INVALID_HANDLE if there is no matching port for the phy. | ||
124 | */ | ||
125 | static struct scic_sds_port *scic_sds_port_configuration_agent_find_port( | ||
126 | struct scic_sds_controller *controller, | ||
127 | struct scic_sds_phy *phy) | ||
128 | { | ||
129 | u8 port_index; | ||
130 | struct scic_sds_port *port_handle; | ||
131 | struct sci_sas_address port_sas_address; | ||
132 | struct sci_sas_address port_attached_device_address; | ||
133 | struct sci_sas_address phy_sas_address; | ||
134 | struct sci_sas_address phy_attached_device_address; | ||
135 | |||
136 | /* | ||
137 | * Since this phy can be a member of a wide port check to see if one or | ||
138 | * more phys match the sent and received SAS address as this phy in which | ||
139 | * case it should participate in the same port. */ | ||
140 | scic_sds_phy_get_sas_address(phy, &phy_sas_address); | ||
141 | scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address); | ||
142 | |||
143 | for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { | ||
144 | if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) { | ||
145 | struct scic_sds_port *port = (struct scic_sds_port *)port_handle; | ||
146 | |||
147 | scic_sds_port_get_sas_address(port, &port_sas_address); | ||
148 | scic_sds_port_get_attached_sas_address(port, &port_attached_device_address); | ||
149 | |||
150 | if ( | ||
151 | (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0) | ||
152 | && (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0) | ||
153 | ) { | ||
154 | return port; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | |||
159 | return SCI_INVALID_HANDLE; | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * | ||
164 | * @controller: This is the controller object that contains the port agent | ||
165 | * @port_agent: This is the port configruation agent for the controller. | ||
166 | * | ||
167 | * This routine will validate the port configuration is correct for the SCU | ||
168 | * hardware. The SCU hardware allows for port configurations as follows. LP0 | ||
169 | * -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2, | ||
170 | * PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for | ||
171 | * this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION | ||
172 | * the port configuration is not valid for this port configuration agent. | ||
173 | */ | ||
174 | static enum sci_status scic_sds_port_configuration_agent_validate_ports( | ||
175 | struct scic_sds_controller *controller, | ||
176 | struct scic_sds_port_configuration_agent *port_agent) | ||
177 | { | ||
178 | struct sci_sas_address first_address; | ||
179 | struct sci_sas_address second_address; | ||
180 | |||
181 | /* | ||
182 | * Sanity check the max ranges for all the phys the max index | ||
183 | * is always equal to the port range index */ | ||
184 | if ( | ||
185 | (port_agent->phy_valid_port_range[0].max_index != 0) | ||
186 | || (port_agent->phy_valid_port_range[1].max_index != 1) | ||
187 | || (port_agent->phy_valid_port_range[2].max_index != 2) | ||
188 | || (port_agent->phy_valid_port_range[3].max_index != 3) | ||
189 | ) { | ||
190 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * This is a request to configure a single x4 port or at least attempt | ||
195 | * to make all the phys into a single port */ | ||
196 | if ( | ||
197 | (port_agent->phy_valid_port_range[0].min_index == 0) | ||
198 | && (port_agent->phy_valid_port_range[1].min_index == 0) | ||
199 | && (port_agent->phy_valid_port_range[2].min_index == 0) | ||
200 | && (port_agent->phy_valid_port_range[3].min_index == 0) | ||
201 | ) { | ||
202 | return SCI_SUCCESS; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * This is a degenerate case where phy 1 and phy 2 are assigned | ||
207 | * to the same port this is explicitly disallowed by the hardware | ||
208 | * unless they are part of the same x4 port and this condition was | ||
209 | * already checked above. */ | ||
210 | if (port_agent->phy_valid_port_range[2].min_index == 1) { | ||
211 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * PE0 and PE3 can never have the same SAS Address unless they | ||
216 | * are part of the same x4 wide port and we have already checked | ||
217 | * for this condition. */ | ||
218 | scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); | ||
219 | scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); | ||
220 | |||
221 | if (sci_sas_address_compare(first_address, second_address) == 0) { | ||
222 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * PE0 and PE1 are configured into a 2x1 ports make sure that the | ||
227 | * SAS Address for PE0 and PE2 are different since they can not be | ||
228 | * part of the same port. */ | ||
229 | if ( | ||
230 | (port_agent->phy_valid_port_range[0].min_index == 0) | ||
231 | && (port_agent->phy_valid_port_range[1].min_index == 1) | ||
232 | ) { | ||
233 | scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address); | ||
234 | scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address); | ||
235 | |||
236 | if (sci_sas_address_compare(first_address, second_address) == 0) { | ||
237 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * PE2 and PE3 are configured into a 2x1 ports make sure that the | ||
243 | * SAS Address for PE1 and PE3 are different since they can not be | ||
244 | * part of the same port. */ | ||
245 | if ( | ||
246 | (port_agent->phy_valid_port_range[2].min_index == 2) | ||
247 | && (port_agent->phy_valid_port_range[3].min_index == 3) | ||
248 | ) { | ||
249 | scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address); | ||
250 | scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address); | ||
251 | |||
252 | if (sci_sas_address_compare(first_address, second_address) == 0) { | ||
253 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | return SCI_SUCCESS; | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * ****************************************************************************** | ||
262 | * Manual port configuration agent routines | ||
263 | * ****************************************************************************** */ | ||
264 | |||
265 | /** | ||
266 | * | ||
267 | * | ||
268 | * This routine will verify that all of the phys in the same port are using the | ||
269 | * same SAS address. | ||
270 | */ | ||
271 | static enum sci_status scic_sds_mpc_agent_validate_phy_configuration( | ||
272 | struct scic_sds_controller *controller, | ||
273 | struct scic_sds_port_configuration_agent *port_agent) | ||
274 | { | ||
275 | u32 phy_mask; | ||
276 | u32 assigned_phy_mask; | ||
277 | struct sci_sas_address sas_address; | ||
278 | struct sci_sas_address phy_assigned_address; | ||
279 | u8 port_index; | ||
280 | u8 phy_index; | ||
281 | |||
282 | assigned_phy_mask = 0; | ||
283 | sas_address.high = 0; | ||
284 | sas_address.low = 0; | ||
285 | |||
286 | for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) { | ||
287 | phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask; | ||
288 | |||
289 | if (phy_mask != 0) { | ||
290 | /* | ||
291 | * Make sure that one or more of the phys were not already assinged to | ||
292 | * a different port. */ | ||
293 | if ((phy_mask & ~assigned_phy_mask) == 0) { | ||
294 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
295 | } | ||
296 | |||
297 | /* Find the starting phy index for this round through the loop */ | ||
298 | for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) { | ||
299 | if ((1 << phy_index) & phy_mask) { | ||
300 | scic_sds_phy_get_sas_address( | ||
301 | &controller->phy_table[phy_index], &sas_address | ||
302 | ); | ||
303 | |||
304 | /* | ||
305 | * The phy_index can be used as the starting point for the | ||
306 | * port range since the hardware starts all logical ports | ||
307 | * the same as the PE index. */ | ||
308 | port_agent->phy_valid_port_range[phy_index].min_index = port_index; | ||
309 | port_agent->phy_valid_port_range[phy_index].max_index = phy_index; | ||
310 | |||
311 | if (phy_index != port_index) { | ||
312 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
313 | } | ||
314 | |||
315 | break; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * See how many additional phys are being added to this logical port. | ||
321 | * Note: We have not moved the current phy_index so we will actually | ||
322 | * compare the startting phy with itself. | ||
323 | * This is expected and required to add the phy to the port. */ | ||
324 | while (phy_index < SCI_MAX_PHYS) { | ||
325 | if ((1 << phy_index) & phy_mask) { | ||
326 | scic_sds_phy_get_sas_address( | ||
327 | &controller->phy_table[phy_index], &phy_assigned_address | ||
328 | ); | ||
329 | |||
330 | if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) { | ||
331 | /* | ||
332 | * The phy mask specified that this phy is part of the same port | ||
333 | * as the starting phy and it is not so fail this configuration */ | ||
334 | return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION; | ||
335 | } | ||
336 | |||
337 | port_agent->phy_valid_port_range[phy_index].min_index = port_index; | ||
338 | port_agent->phy_valid_port_range[phy_index].max_index = phy_index; | ||
339 | |||
340 | scic_sds_port_add_phy( | ||
341 | &controller->port_table[port_index], | ||
342 | &controller->phy_table[phy_index] | ||
343 | ); | ||
344 | |||
345 | assigned_phy_mask |= (1 << phy_index); | ||
346 | } | ||
347 | |||
348 | phy_index++; | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
353 | return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * | ||
358 | * | ||
359 | * This timer routine is used to allow the SCI User to rediscover or change | ||
360 | * device objects before a new series of link up notifications because a link | ||
361 | * down has allowed a better port configuration. | ||
362 | */ | ||
363 | static void scic_sds_mpc_agent_timeout_handler( | ||
364 | void *object) | ||
365 | { | ||
366 | u8 index; | ||
367 | struct scic_sds_controller *controller = (struct scic_sds_controller *)object; | ||
368 | struct scic_sds_port_configuration_agent *port_agent = &controller->port_agent; | ||
369 | u16 configure_phy_mask; | ||
370 | |||
371 | port_agent->timer_pending = false; | ||
372 | |||
373 | /* Find the mask of phys that are reported read but as yet unconfigured into a port */ | ||
374 | configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; | ||
375 | |||
376 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
377 | if (configure_phy_mask & (1 << index)) { | ||
378 | port_agent->link_up_handler( | ||
379 | controller, | ||
380 | port_agent, | ||
381 | scic_sds_phy_get_port(&controller->phy_table[index]), | ||
382 | &controller->phy_table[index] | ||
383 | ); | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * | ||
390 | * @controller: This is the controller object that receives the link up | ||
391 | * notification. | ||
392 | * @port: This is the port object associated with the phy. If the is no | ||
393 | * associated port this is an SCI_INVALID_HANDLE. | ||
394 | * @phy: This is the phy object which has gone ready. | ||
395 | * | ||
396 | * This method handles the manual port configuration link up notifications. | ||
397 | * Since all ports and phys are associate at initialization time we just turn | ||
398 | * around and notifiy the port object that there is a link up. If this PHY is | ||
399 | * not associated with a port there is no action taken. Is it possible to get a | ||
400 | * link up notification from a phy that has no assocoated port? | ||
401 | */ | ||
402 | static void scic_sds_mpc_agent_link_up( | ||
403 | struct scic_sds_controller *controller, | ||
404 | struct scic_sds_port_configuration_agent *port_agent, | ||
405 | struct scic_sds_port *port, | ||
406 | struct scic_sds_phy *phy) | ||
407 | { | ||
408 | /* | ||
409 | * If the port has an invalid handle then the phy was not assigned to | ||
410 | * a port. This is because the phy was not given the same SAS Address | ||
411 | * as the other PHYs in the port. */ | ||
412 | if (port != SCI_INVALID_HANDLE) { | ||
413 | port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); | ||
414 | |||
415 | scic_sds_port_link_up(port, phy); | ||
416 | |||
417 | if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) { | ||
418 | port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy)); | ||
419 | } | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * | ||
425 | * @controller: This is the controller object that receives the link down | ||
426 | * notification. | ||
427 | * @port: This is the port object associated with the phy. If the is no | ||
428 | * associated port this is an SCI_INVALID_HANDLE. The port is an invalid | ||
429 | * handle only if the phy was never port of this port. This happens when | ||
430 | * the phy is not broadcasting the same SAS address as the other phys in the | ||
431 | * assigned port. | ||
432 | * @phy: This is the phy object which has gone link down. | ||
433 | * | ||
434 | * This method handles the manual port configuration link down notifications. | ||
435 | * Since all ports and phys are associated at initialization time we just turn | ||
436 | * around and notifiy the port object of the link down event. If this PHY is | ||
437 | * not associated with a port there is no action taken. Is it possible to get a | ||
438 | * link down notification from a phy that has no assocoated port? | ||
439 | */ | ||
440 | static void scic_sds_mpc_agent_link_down( | ||
441 | struct scic_sds_controller *controller, | ||
442 | struct scic_sds_port_configuration_agent *port_agent, | ||
443 | struct scic_sds_port *port, | ||
444 | struct scic_sds_phy *phy) | ||
445 | { | ||
446 | if (port != SCI_INVALID_HANDLE) { | ||
447 | /* | ||
448 | * If we can form a new port from the remainder of the phys then we want | ||
449 | * to start the timer to allow the SCI User to cleanup old devices and | ||
450 | * rediscover the port before rebuilding the port with the phys that | ||
451 | * remain in the ready state. */ | ||
452 | port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); | ||
453 | port_agent->phy_configured_mask &= ~(1 << scic_sds_phy_get_index(phy)); | ||
454 | |||
455 | /* | ||
456 | * Check to see if there are more phys waiting to be configured into a port. | ||
457 | * If there are allow the SCI User to tear down this port, if necessary, and | ||
458 | * then reconstruc the port after the timeout. */ | ||
459 | if ( | ||
460 | (port_agent->phy_configured_mask == 0x0000) | ||
461 | && (port_agent->phy_ready_mask != 0x0000) | ||
462 | && !port_agent->timer_pending | ||
463 | ) { | ||
464 | port_agent->timer_pending = true; | ||
465 | |||
466 | scic_cb_timer_start( | ||
467 | controller, | ||
468 | port_agent->timer, | ||
469 | SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT | ||
470 | ); | ||
471 | } | ||
472 | |||
473 | scic_sds_port_link_down(port, phy); | ||
474 | } | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * ****************************************************************************** | ||
479 | * Automatic port configuration agent routines | ||
480 | * ****************************************************************************** */ | ||
481 | |||
482 | /** | ||
483 | * | ||
484 | * | ||
485 | * This routine will verify that the phys are assigned a valid SAS address for | ||
486 | * automatic port configuration mode. | ||
487 | */ | ||
488 | static enum sci_status scic_sds_apc_agent_validate_phy_configuration( | ||
489 | struct scic_sds_controller *controller, | ||
490 | struct scic_sds_port_configuration_agent *port_agent) | ||
491 | { | ||
492 | u8 phy_index; | ||
493 | u8 port_index; | ||
494 | struct sci_sas_address sas_address; | ||
495 | struct sci_sas_address phy_assigned_address; | ||
496 | |||
497 | phy_index = 0; | ||
498 | |||
499 | while (phy_index < SCI_MAX_PHYS) { | ||
500 | port_index = phy_index; | ||
501 | |||
502 | /* Get the assigned SAS Address for the first PHY on the controller. */ | ||
503 | scic_sds_phy_get_sas_address( | ||
504 | &controller->phy_table[phy_index], &sas_address | ||
505 | ); | ||
506 | |||
507 | while (++phy_index < SCI_MAX_PHYS) { | ||
508 | scic_sds_phy_get_sas_address( | ||
509 | &controller->phy_table[phy_index], &phy_assigned_address | ||
510 | ); | ||
511 | |||
512 | /* Verify each of the SAS address are all the same for every PHY */ | ||
513 | if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) { | ||
514 | port_agent->phy_valid_port_range[phy_index].min_index = port_index; | ||
515 | port_agent->phy_valid_port_range[phy_index].max_index = phy_index; | ||
516 | } else { | ||
517 | port_agent->phy_valid_port_range[phy_index].min_index = phy_index; | ||
518 | port_agent->phy_valid_port_range[phy_index].max_index = phy_index; | ||
519 | break; | ||
520 | } | ||
521 | } | ||
522 | } | ||
523 | |||
524 | return scic_sds_port_configuration_agent_validate_ports(controller, port_agent); | ||
525 | } | ||
526 | |||
527 | /** | ||
528 | * | ||
529 | * @controller: This is the controller that to which the port agent is assigned. | ||
530 | * @port_agent: This is the port agent that is requesting the timer start | ||
531 | * operation. | ||
532 | * @phy: This is the phy that has caused the timer operation to be scheduled. | ||
533 | * | ||
534 | * This routine will restart the automatic port configuration timeout timer for | ||
535 | * the next time period. This could be caused by either a link down event or a | ||
536 | * link up event where we can not yet tell to which port a phy belongs. | ||
537 | */ | ||
538 | static void scic_sds_apc_agent_start_timer( | ||
539 | struct scic_sds_controller *controller, | ||
540 | struct scic_sds_port_configuration_agent *port_agent, | ||
541 | struct scic_sds_phy *phy, | ||
542 | u32 timeout) | ||
543 | { | ||
544 | if (port_agent->timer_pending) { | ||
545 | scic_cb_timer_stop(controller, port_agent->timer); | ||
546 | } | ||
547 | |||
548 | port_agent->timer_pending = true; | ||
549 | |||
550 | scic_cb_timer_start(controller, port_agent->timer, timeout); | ||
551 | } | ||
552 | |||
553 | /** | ||
554 | * | ||
555 | * @controller: This is the controller object that receives the link up | ||
556 | * notification. | ||
557 | * @phy: This is the phy object which has gone link up. | ||
558 | * | ||
559 | * This method handles the automatic port configuration for link up | ||
560 | * notifications. | ||
561 | */ | ||
562 | static void scic_sds_apc_agent_configure_ports( | ||
563 | struct scic_sds_controller *controller, | ||
564 | struct scic_sds_port_configuration_agent *port_agent, | ||
565 | struct scic_sds_phy *phy, | ||
566 | bool start_timer) | ||
567 | { | ||
568 | u8 port_index; | ||
569 | enum sci_status status; | ||
570 | struct scic_sds_port *port; | ||
571 | struct scic_sds_port *port_handle; | ||
572 | enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY; | ||
573 | |||
574 | port = scic_sds_port_configuration_agent_find_port(controller, phy); | ||
575 | |||
576 | if (port != SCI_INVALID_HANDLE) { | ||
577 | if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) | ||
578 | apc_activity = SCIC_SDS_APC_ADD_PHY; | ||
579 | else | ||
580 | apc_activity = SCIC_SDS_APC_SKIP_PHY; | ||
581 | } else { | ||
582 | /* | ||
583 | * There is no matching Port for this PHY so lets search through the | ||
584 | * Ports and see if we can add the PHY to its own port or maybe start | ||
585 | * the timer and wait to see if a wider port can be made. | ||
586 | * | ||
587 | * Note the break when we reach the condition of the port id == phy id */ | ||
588 | for ( | ||
589 | port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index; | ||
590 | port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index; | ||
591 | port_index++ | ||
592 | ) { | ||
593 | scic_controller_get_port_handle(controller, port_index, &port_handle); | ||
594 | |||
595 | port = (struct scic_sds_port *)port_handle; | ||
596 | |||
597 | /* First we must make sure that this PHY can be added to this Port. */ | ||
598 | if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) { | ||
599 | /* | ||
600 | * Port contains a PHY with a greater PHY ID than the current | ||
601 | * PHY that has gone link up. This phy can not be part of any | ||
602 | * port so skip it and move on. */ | ||
603 | if (port->active_phy_mask > (1 << phy->phy_index)) { | ||
604 | apc_activity = SCIC_SDS_APC_SKIP_PHY; | ||
605 | break; | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * We have reached the end of our Port list and have not found | ||
610 | * any reason why we should not either add the PHY to the port | ||
611 | * or wait for more phys to become active. */ | ||
612 | if (port->physical_port_index == phy->phy_index) { | ||
613 | /* | ||
614 | * The Port either has no active PHYs. | ||
615 | * Consider that if the port had any active PHYs we would have | ||
616 | * or active PHYs with | ||
617 | * a lower PHY Id than this PHY. */ | ||
618 | if (apc_activity != SCIC_SDS_APC_START_TIMER) { | ||
619 | apc_activity = SCIC_SDS_APC_ADD_PHY; | ||
620 | } | ||
621 | |||
622 | break; | ||
623 | } | ||
624 | |||
625 | /* | ||
626 | * The current Port has no active PHYs and this PHY could be part | ||
627 | * of this Port. Since we dont know as yet setup to start the | ||
628 | * timer and see if there is a better configuration. */ | ||
629 | if (port->active_phy_mask == 0) { | ||
630 | apc_activity = SCIC_SDS_APC_START_TIMER; | ||
631 | } | ||
632 | } else if (port->active_phy_mask != 0) { | ||
633 | /* | ||
634 | * The Port has an active phy and the current Phy can not | ||
635 | * participate in this port so skip the PHY and see if | ||
636 | * there is a better configuration. */ | ||
637 | apc_activity = SCIC_SDS_APC_SKIP_PHY; | ||
638 | } | ||
639 | } | ||
640 | } | ||
641 | |||
642 | /* | ||
643 | * Check to see if the start timer operations should instead map to an | ||
644 | * add phy operation. This is caused because we have been waiting to | ||
645 | * add a phy to a port but could not becuase the automatic port | ||
646 | * configuration engine had a choice of possible ports for the phy. | ||
647 | * Since we have gone through a timeout we are going to restrict the | ||
648 | * choice to the smallest possible port. */ | ||
649 | if ( | ||
650 | (start_timer == false) | ||
651 | && (apc_activity == SCIC_SDS_APC_START_TIMER) | ||
652 | ) { | ||
653 | apc_activity = SCIC_SDS_APC_ADD_PHY; | ||
654 | } | ||
655 | |||
656 | switch (apc_activity) { | ||
657 | case SCIC_SDS_APC_ADD_PHY: | ||
658 | status = scic_sds_port_add_phy(port, phy); | ||
659 | |||
660 | if (status == SCI_SUCCESS) { | ||
661 | port_agent->phy_configured_mask |= (1 << phy->phy_index); | ||
662 | } | ||
663 | break; | ||
664 | |||
665 | case SCIC_SDS_APC_START_TIMER: | ||
666 | scic_sds_apc_agent_start_timer( | ||
667 | controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION | ||
668 | ); | ||
669 | break; | ||
670 | |||
671 | case SCIC_SDS_APC_SKIP_PHY: | ||
672 | default: | ||
673 | /* do nothing the PHY can not be made part of a port at this time. */ | ||
674 | break; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | /** | ||
679 | * | ||
680 | * @controller: This is the controller object that receives the link up | ||
681 | * notification. | ||
682 | * @port: This is the port object associated with the phy. If the is no | ||
683 | * associated port this is an SCI_INVALID_HANDLE. | ||
684 | * @phy: This is the phy object which has gone link up. | ||
685 | * | ||
686 | * This method handles the automatic port configuration for link up | ||
687 | * notifications. Is it possible to get a link down notification from a phy | ||
688 | * that has no assocoated port? | ||
689 | */ | ||
690 | static void scic_sds_apc_agent_link_up( | ||
691 | struct scic_sds_controller *controller, | ||
692 | struct scic_sds_port_configuration_agent *port_agent, | ||
693 | struct scic_sds_port *port, | ||
694 | struct scic_sds_phy *phy) | ||
695 | { | ||
696 | BUG_ON(port != SCI_INVALID_HANDLE); | ||
697 | |||
698 | port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy)); | ||
699 | |||
700 | scic_sds_apc_agent_configure_ports(controller, port_agent, phy, true); | ||
701 | } | ||
702 | |||
703 | /** | ||
704 | * | ||
705 | * @controller: This is the controller object that receives the link down | ||
706 | * notification. | ||
707 | * @port: This is the port object associated with the phy. If the is no | ||
708 | * associated port this is an SCI_INVALID_HANDLE. | ||
709 | * @phy: This is the phy object which has gone link down. | ||
710 | * | ||
711 | * This method handles the automatic port configuration link down | ||
712 | * notifications. not associated with a port there is no action taken. Is it | ||
713 | * possible to get a link down notification from a phy that has no assocoated | ||
714 | * port? | ||
715 | */ | ||
716 | static void scic_sds_apc_agent_link_down( | ||
717 | struct scic_sds_controller *controller, | ||
718 | struct scic_sds_port_configuration_agent *port_agent, | ||
719 | struct scic_sds_port *port, | ||
720 | struct scic_sds_phy *phy) | ||
721 | { | ||
722 | port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy)); | ||
723 | |||
724 | if (port != SCI_INVALID_HANDLE) { | ||
725 | if (port_agent->phy_configured_mask & (1 << phy->phy_index)) { | ||
726 | enum sci_status status; | ||
727 | |||
728 | status = scic_sds_port_remove_phy(port, phy); | ||
729 | |||
730 | if (status == SCI_SUCCESS) { | ||
731 | port_agent->phy_configured_mask &= ~(1 << phy->phy_index); | ||
732 | } | ||
733 | } | ||
734 | } | ||
735 | } | ||
736 | |||
737 | /** | ||
738 | * | ||
739 | * | ||
740 | * This routine will try to configure the phys into ports when the timer fires. | ||
741 | */ | ||
742 | static void scic_sds_apc_agent_timeout_handler( | ||
743 | void *object) | ||
744 | { | ||
745 | u32 index; | ||
746 | struct scic_sds_port_configuration_agent *port_agent; | ||
747 | struct scic_sds_controller *controller = (struct scic_sds_controller *)object; | ||
748 | u16 configure_phy_mask; | ||
749 | |||
750 | port_agent = scic_sds_controller_get_port_configuration_agent(controller); | ||
751 | |||
752 | port_agent->timer_pending = false; | ||
753 | |||
754 | configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask; | ||
755 | |||
756 | if (configure_phy_mask != 0x00) { | ||
757 | for (index = 0; index < SCI_MAX_PHYS; index++) { | ||
758 | if (configure_phy_mask & (1 << index)) { | ||
759 | scic_sds_apc_agent_configure_ports( | ||
760 | controller, port_agent, &controller->phy_table[index], false | ||
761 | ); | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | } | ||
766 | |||
767 | /* | ||
768 | * ****************************************************************************** | ||
769 | * Public port configuration agent routines | ||
770 | * ****************************************************************************** */ | ||
771 | |||
772 | /** | ||
773 | * | ||
774 | * | ||
775 | * This method will construct the port configuration agent for operation. This | ||
776 | * call is universal for both manual port configuration and automatic port | ||
777 | * configuration modes. | ||
778 | */ | ||
779 | void scic_sds_port_configuration_agent_construct( | ||
780 | struct scic_sds_port_configuration_agent *port_agent) | ||
781 | { | ||
782 | u32 index; | ||
783 | |||
784 | port_agent->phy_configured_mask = 0x00; | ||
785 | port_agent->phy_ready_mask = 0x00; | ||
786 | |||
787 | port_agent->link_up_handler = NULL; | ||
788 | port_agent->link_down_handler = NULL; | ||
789 | |||
790 | port_agent->timer_pending = false; | ||
791 | port_agent->timer = NULL; | ||
792 | |||
793 | for (index = 0; index < SCI_MAX_PORTS; index++) { | ||
794 | port_agent->phy_valid_port_range[index].min_index = 0; | ||
795 | port_agent->phy_valid_port_range[index].max_index = 0; | ||
796 | } | ||
797 | } | ||
798 | |||
799 | /** | ||
800 | * | ||
801 | * @controller: This is the controller object for which the port agent is being | ||
802 | * initialized. | ||
803 | * | ||
804 | * This method will construct the port configuration agent for this controller. | ||
805 | */ | ||
806 | enum sci_status scic_sds_port_configuration_agent_initialize( | ||
807 | struct scic_sds_controller *controller, | ||
808 | struct scic_sds_port_configuration_agent *port_agent) | ||
809 | { | ||
810 | enum sci_status status = SCI_SUCCESS; | ||
811 | enum SCIC_PORT_CONFIGURATION_MODE mode; | ||
812 | |||
813 | mode = scic_sds_controller_get_port_configuration_mode(controller); | ||
814 | |||
815 | if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) { | ||
816 | status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent); | ||
817 | |||
818 | port_agent->link_up_handler = scic_sds_mpc_agent_link_up; | ||
819 | port_agent->link_down_handler = scic_sds_mpc_agent_link_down; | ||
820 | |||
821 | port_agent->timer = scic_cb_timer_create( | ||
822 | controller, | ||
823 | scic_sds_mpc_agent_timeout_handler, | ||
824 | controller | ||
825 | ); | ||
826 | } else { | ||
827 | status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent); | ||
828 | |||
829 | port_agent->link_up_handler = scic_sds_apc_agent_link_up; | ||
830 | port_agent->link_down_handler = scic_sds_apc_agent_link_down; | ||
831 | |||
832 | port_agent->timer = scic_cb_timer_create( | ||
833 | controller, | ||
834 | scic_sds_apc_agent_timeout_handler, | ||
835 | controller | ||
836 | ); | ||
837 | } | ||
838 | |||
839 | /* Make sure we have actually gotten a timer */ | ||
840 | if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) { | ||
841 | dev_err(scic_to_dev(controller), | ||
842 | "%s: Controller 0x%p automatic port configuration " | ||
843 | "agent could not get timer.\n", | ||
844 | __func__, | ||
845 | controller); | ||
846 | |||
847 | status = SCI_FAILURE; | ||
848 | } | ||
849 | |||
850 | return status; | ||
851 | } | ||
diff --git a/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h new file mode 100644 index 000000000000..4146735ffc32 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port_configuration_agent.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ | ||
57 | #define _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants and prototypes used for the | ||
61 | * core controller automatic port configuration engine. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "scic_sds_port.h" | ||
67 | #include "scic_sds_phy.h" | ||
68 | |||
69 | struct scic_sds_controller; | ||
70 | struct scic_sds_port_configuration_agent; | ||
71 | struct scic_sds_port; | ||
72 | struct scic_sds_phy; | ||
73 | |||
74 | typedef void (*SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T)( | ||
75 | struct scic_sds_controller *, | ||
76 | struct scic_sds_port_configuration_agent *, | ||
77 | struct scic_sds_port *, | ||
78 | struct scic_sds_phy * | ||
79 | ); | ||
80 | |||
81 | struct SCIC_SDS_PORT_RANGE { | ||
82 | u8 min_index; | ||
83 | u8 max_index; | ||
84 | }; | ||
85 | |||
86 | struct scic_sds_port_configuration_agent { | ||
87 | u16 phy_configured_mask; | ||
88 | u16 phy_ready_mask; | ||
89 | |||
90 | struct SCIC_SDS_PORT_RANGE phy_valid_port_range[SCI_MAX_PHYS]; | ||
91 | |||
92 | bool timer_pending; | ||
93 | |||
94 | SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_up_handler; | ||
95 | SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_down_handler; | ||
96 | |||
97 | void *timer; | ||
98 | |||
99 | }; | ||
100 | |||
101 | void scic_sds_port_configuration_agent_construct( | ||
102 | struct scic_sds_port_configuration_agent *port_agent); | ||
103 | |||
104 | enum sci_status scic_sds_port_configuration_agent_initialize( | ||
105 | struct scic_sds_controller *controller, | ||
106 | struct scic_sds_port_configuration_agent *port_agent); | ||
107 | |||
108 | #endif /* _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_port_registers.h b/drivers/scsi/isci/core/scic_sds_port_registers.h new file mode 100644 index 000000000000..cf8bc073b952 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_port_registers.h | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_PORT_REGISTERS_H_ | ||
57 | #define _SCIC_SDS_PORT_REGISTERS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains a set of macros that assist in reading the SCU hardware | ||
61 | * registers. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | /** | ||
67 | * scu_transport_layer_read() - | ||
68 | * | ||
69 | * Macro to read the transport layer register associated with this port object. | ||
70 | */ | ||
71 | #define scu_transport_layer_read(port, reg) \ | ||
72 | scu_register_read(\ | ||
73 | scic_sds_port_get_controller(port), \ | ||
74 | (port)->transport_layer_registers->reg \ | ||
75 | ) | ||
76 | |||
77 | /** | ||
78 | * scu_transport_layer_write() - | ||
79 | * | ||
80 | * Macro to write the transport layer register associated with this port object. | ||
81 | */ | ||
82 | #define scu_transport_layer_write(port, reg, value) \ | ||
83 | scu_register_write(\ | ||
84 | scic_sds_port_get_controller(port), \ | ||
85 | (port)->transport_layer_registers->reg, \ | ||
86 | (value) \ | ||
87 | ) | ||
88 | |||
89 | /** | ||
90 | * scu_port_task_scheduler_read() - | ||
91 | * | ||
92 | * Macro to read the port task scheduler register associated with this port | ||
93 | * object | ||
94 | */ | ||
95 | #define scu_port_task_scheduler_read(port, reg) \ | ||
96 | scu_register_read(\ | ||
97 | scic_sds_port_get_controller(port), \ | ||
98 | (port)->port_task_scheduler_registers->reg \ | ||
99 | ) | ||
100 | |||
101 | /** | ||
102 | * scu_port_task_scheduler_write() - | ||
103 | * | ||
104 | * Macro to write the port task scheduler register associated with this port | ||
105 | * object | ||
106 | */ | ||
107 | #define scu_port_task_scheduler_write(port, reg, value) \ | ||
108 | scu_register_write(\ | ||
109 | scic_sds_port_get_controller(port), \ | ||
110 | (port)->port_task_scheduler_registers->reg, \ | ||
111 | (value) \ | ||
112 | ) | ||
113 | |||
114 | #define scu_port_viit_register_write(port, reg, value) \ | ||
115 | scu_register_write(\ | ||
116 | scic_sds_port_get_controller(port), \ | ||
117 | (port)->viit_registers->reg, \ | ||
118 | (value) \ | ||
119 | ) | ||
120 | |||
121 | /* | ||
122 | * **************************************************************************** | ||
123 | * * Transport Layer registers controlled by the port object | ||
124 | * **************************************************************************** */ | ||
125 | |||
126 | /** | ||
127 | * SCU_TLCR_READ() - | ||
128 | * | ||
129 | * This macro reads the Transport layer control register | ||
130 | */ | ||
131 | #define SCU_TLCR_READ(port) \ | ||
132 | scu_transport_layer_read(port, control) | ||
133 | |||
134 | /** | ||
135 | * SCU_TLCR_WRITE() - | ||
136 | * | ||
137 | * This macro writes the Transport layer control register | ||
138 | */ | ||
139 | #define SCU_TLCR_WRITE(port, value) \ | ||
140 | scu_transport_layer_write(port, control, value) | ||
141 | |||
142 | /** | ||
143 | * SCU_TLADTR_READ() - | ||
144 | * | ||
145 | * This macro reads the Transport layer address translation register | ||
146 | */ | ||
147 | #define SCU_TLADTR_READ(port) \ | ||
148 | scu_transport_layer_read(port, address_translation) | ||
149 | |||
150 | /** | ||
151 | * SCU_TLADTR_WRITE() - | ||
152 | * | ||
153 | * This macro writes the Transport layer address translation register | ||
154 | */ | ||
155 | #define SCU_TLADTR_WRITE(port) \ | ||
156 | scu_transport_layer_write(port, address_translation, value) | ||
157 | |||
158 | /** | ||
159 | * SCU_STPTLDARNI_WRITE() - | ||
160 | * | ||
161 | * This macro writes the STP Transport Layer Direct Attached RNi register. | ||
162 | */ | ||
163 | #define SCU_STPTLDARNI_WRITE(port, index) \ | ||
164 | scu_transport_layer_write(port, stp_rni, index) | ||
165 | |||
166 | /** | ||
167 | * SCU_STPTLDARNI_READ() - | ||
168 | * | ||
169 | * This macro reads the STP Transport Layer Direct Attached RNi register. | ||
170 | */ | ||
171 | #define SCU_STPTLDARNI_READ(port) \ | ||
172 | scu_transport_layer_read(port, stp_rni) | ||
173 | |||
174 | /* | ||
175 | * **************************************************************************** | ||
176 | * * Port Task Scheduler registers controlled by the port object | ||
177 | * **************************************************************************** */ | ||
178 | |||
179 | /** | ||
180 | * SCU_PTSxCR_READ() - | ||
181 | * | ||
182 | * Macro to read the port task scheduler control register | ||
183 | */ | ||
184 | #define SCU_PTSxCR_READ(port) \ | ||
185 | scu_port_task_scheduler_read(port, control) | ||
186 | |||
187 | /** | ||
188 | * SCU_PTSxCR_WRITE() - | ||
189 | * | ||
190 | * Macro to write the port task scheduler control regsister | ||
191 | */ | ||
192 | #define SCU_PTSxCR_WRITE(port, value) \ | ||
193 | scu_port_task_scheduler_write(port, control, value) | ||
194 | |||
195 | /* | ||
196 | * **************************************************************************** | ||
197 | * * Port PE Configuration registers | ||
198 | * **************************************************************************** */ | ||
199 | |||
200 | /** | ||
201 | * SCU_PCSPExCR_WRITE() - | ||
202 | * | ||
203 | * Macro to write the PE Port Configuration Register | ||
204 | */ | ||
205 | #define SCU_PCSPExCR_WRITE(port, phy_id, value) \ | ||
206 | scu_register_write(\ | ||
207 | scic_sds_port_get_controller(port), \ | ||
208 | (port)->port_pe_configuration_register[phy_id], \ | ||
209 | (value) \ | ||
210 | ) | ||
211 | |||
212 | /** | ||
213 | * SCU_PCSPExCR_READ() - | ||
214 | * | ||
215 | * Macro to read the PE Port Configuration Regsiter | ||
216 | */ | ||
217 | #define SCU_PCSPExCR_READ(port, phy_id) \ | ||
218 | scu_register_read(\ | ||
219 | scic_sds_port_get_controller(port), \ | ||
220 | (port)->port_pe_configuration_register[phy_id] \ | ||
221 | ) | ||
222 | |||
223 | #endif /* _SCIC_SDS_PORT_REGISTERS_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.c b/drivers/scsi/isci/core/scic_sds_remote_device.c new file mode 100644 index 000000000000..21f03bc7d797 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_device.c | |||
@@ -0,0 +1,2252 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the implementation of remote device methods. | ||
58 | * | ||
59 | * | ||
60 | */ | ||
61 | |||
62 | #include "intel_sas.h" | ||
63 | #include "sci_util.h" | ||
64 | #include "sci_environment.h" | ||
65 | #include "scic_port.h" | ||
66 | #include "scic_phy.h" | ||
67 | #include "scic_remote_device.h" | ||
68 | #include "scic_sds_port.h" | ||
69 | #include "scic_sds_phy.h" | ||
70 | #include "scic_sds_remote_device.h" | ||
71 | #include "scic_sds_request.h" | ||
72 | #include "scic_sds_controller.h" | ||
73 | |||
74 | #define SCIC_SDS_REMOTE_DEVICE_RESET_TIMEOUT (1000) | ||
75 | |||
76 | /* | ||
77 | * ***************************************************************************** | ||
78 | * * CORE REMOTE DEVICE PRIVATE METHODS | ||
79 | * ***************************************************************************** */ | ||
80 | |||
81 | /* | ||
82 | * ***************************************************************************** | ||
83 | * * CORE REMOTE DEVICE PUBLIC METHODS | ||
84 | * ***************************************************************************** */ | ||
85 | |||
86 | u32 scic_remote_device_get_object_size(void) | ||
87 | { | ||
88 | return sizeof(struct scic_sds_remote_device) | ||
89 | + sizeof(struct scic_sds_remote_node_context); | ||
90 | } | ||
91 | |||
92 | /* --------------------------------------------------------------------------- */ | ||
93 | |||
94 | void scic_remote_device_construct(struct scic_sds_port *sci_port, | ||
95 | struct scic_sds_remote_device *sci_dev) | ||
96 | { | ||
97 | sci_dev->owning_port = sci_port; | ||
98 | sci_dev->started_request_count = 0; | ||
99 | sci_dev->rnc = (struct scic_sds_remote_node_context *) &sci_dev[1]; | ||
100 | |||
101 | sci_base_remote_device_construct( | ||
102 | &sci_dev->parent, | ||
103 | scic_sds_remote_device_state_table | ||
104 | ); | ||
105 | |||
106 | scic_sds_remote_node_context_construct( | ||
107 | sci_dev, | ||
108 | sci_dev->rnc, | ||
109 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | ||
110 | ); | ||
111 | |||
112 | sci_object_set_association(sci_dev->rnc, sci_dev); | ||
113 | } | ||
114 | |||
115 | |||
116 | enum sci_status scic_remote_device_da_construct( | ||
117 | struct scic_sds_remote_device *sci_dev) | ||
118 | { | ||
119 | enum sci_status status; | ||
120 | u16 remote_node_index; | ||
121 | struct sci_sas_identify_address_frame_protocols protocols; | ||
122 | |||
123 | /* | ||
124 | * This information is request to determine how many remote node context | ||
125 | * entries will be needed to store the remote node. | ||
126 | */ | ||
127 | scic_sds_port_get_attached_protocols(sci_dev->owning_port, &protocols); | ||
128 | sci_dev->target_protocols.u.all = protocols.u.all; | ||
129 | sci_dev->is_direct_attached = true; | ||
130 | #if !defined(DISABLE_ATAPI) | ||
131 | sci_dev->is_atapi = scic_sds_remote_device_is_atapi(sci_dev); | ||
132 | #endif | ||
133 | |||
134 | status = scic_sds_controller_allocate_remote_node_context( | ||
135 | sci_dev->owning_port->owning_controller, | ||
136 | sci_dev, | ||
137 | &remote_node_index); | ||
138 | |||
139 | if (status == SCI_SUCCESS) { | ||
140 | scic_sds_remote_node_context_set_remote_node_index( | ||
141 | sci_dev->rnc, remote_node_index); | ||
142 | |||
143 | scic_sds_port_get_attached_sas_address( | ||
144 | sci_dev->owning_port, &sci_dev->device_address); | ||
145 | |||
146 | if (sci_dev->target_protocols.u.bits.attached_ssp_target) { | ||
147 | sci_dev->has_ready_substate_machine = false; | ||
148 | } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { | ||
149 | sci_dev->has_ready_substate_machine = true; | ||
150 | |||
151 | sci_base_state_machine_construct( | ||
152 | &sci_dev->ready_substate_machine, | ||
153 | &sci_dev->parent.parent, | ||
154 | scic_sds_stp_remote_device_ready_substate_table, | ||
155 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | ||
156 | } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { | ||
157 | sci_dev->has_ready_substate_machine = true; | ||
158 | |||
159 | /* add the SMP ready substate machine construction here */ | ||
160 | sci_base_state_machine_construct( | ||
161 | &sci_dev->ready_substate_machine, | ||
162 | &sci_dev->parent.parent, | ||
163 | scic_sds_smp_remote_device_ready_substate_table, | ||
164 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | ||
165 | } | ||
166 | |||
167 | sci_dev->connection_rate = scic_sds_port_get_max_allowed_speed( | ||
168 | sci_dev->owning_port); | ||
169 | |||
170 | /* / @todo Should I assign the port width by reading all of the phys on the port? */ | ||
171 | sci_dev->device_port_width = 1; | ||
172 | } | ||
173 | |||
174 | return status; | ||
175 | } | ||
176 | |||
177 | |||
178 | static void scic_sds_remote_device_get_info_from_smp_discover_response( | ||
179 | struct scic_sds_remote_device *this_device, | ||
180 | struct smp_response_discover *discover_response) | ||
181 | { | ||
182 | /* decode discover_response to set sas_address to this_device. */ | ||
183 | this_device->device_address.high = | ||
184 | discover_response->attached_sas_address.high; | ||
185 | |||
186 | this_device->device_address.low = | ||
187 | discover_response->attached_sas_address.low; | ||
188 | |||
189 | this_device->target_protocols.u.all = discover_response->protocols.u.all; | ||
190 | } | ||
191 | |||
192 | |||
193 | enum sci_status scic_remote_device_ea_construct( | ||
194 | struct scic_sds_remote_device *sci_dev, | ||
195 | struct smp_response_discover *discover_response) | ||
196 | { | ||
197 | enum sci_status status; | ||
198 | struct scic_sds_controller *the_controller; | ||
199 | |||
200 | the_controller = scic_sds_port_get_controller(sci_dev->owning_port); | ||
201 | |||
202 | scic_sds_remote_device_get_info_from_smp_discover_response( | ||
203 | sci_dev, discover_response); | ||
204 | |||
205 | status = scic_sds_controller_allocate_remote_node_context( | ||
206 | the_controller, sci_dev, &sci_dev->rnc->remote_node_index); | ||
207 | |||
208 | if (status == SCI_SUCCESS) { | ||
209 | if (sci_dev->target_protocols.u.bits.attached_ssp_target) { | ||
210 | sci_dev->has_ready_substate_machine = false; | ||
211 | } else if (sci_dev->target_protocols.u.bits.attached_smp_target) { | ||
212 | sci_dev->has_ready_substate_machine = true; | ||
213 | |||
214 | /* add the SMP ready substate machine construction here */ | ||
215 | sci_base_state_machine_construct( | ||
216 | &sci_dev->ready_substate_machine, | ||
217 | &sci_dev->parent.parent, | ||
218 | scic_sds_smp_remote_device_ready_substate_table, | ||
219 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | ||
220 | } else if (sci_dev->target_protocols.u.bits.attached_stp_target) { | ||
221 | sci_dev->has_ready_substate_machine = true; | ||
222 | |||
223 | sci_base_state_machine_construct( | ||
224 | &sci_dev->ready_substate_machine, | ||
225 | &sci_dev->parent.parent, | ||
226 | scic_sds_stp_remote_device_ready_substate_table, | ||
227 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * For SAS-2 the physical link rate is actually a logical link | ||
232 | * rate that incorporates multiplexing. The SCU doesn't | ||
233 | * incorporate multiplexing and for the purposes of the | ||
234 | * connection the logical link rate is that same as the | ||
235 | * physical. Furthermore, the SAS-2 and SAS-1.1 fields overlay | ||
236 | * one another, so this code works for both situations. */ | ||
237 | sci_dev->connection_rate = min_t(u16, | ||
238 | scic_sds_port_get_max_allowed_speed(sci_dev->owning_port), | ||
239 | discover_response->u2.sas1_1.negotiated_physical_link_rate | ||
240 | ); | ||
241 | |||
242 | /* / @todo Should I assign the port width by reading all of the phys on the port? */ | ||
243 | sci_dev->device_port_width = 1; | ||
244 | } | ||
245 | |||
246 | return status; | ||
247 | } | ||
248 | |||
249 | enum sci_status scic_remote_device_destruct( | ||
250 | struct scic_sds_remote_device *sci_dev) | ||
251 | { | ||
252 | return sci_dev->state_handlers->parent.destruct_handler(&sci_dev->parent); | ||
253 | } | ||
254 | |||
255 | |||
256 | enum sci_status scic_remote_device_start( | ||
257 | struct scic_sds_remote_device *sci_dev, | ||
258 | u32 timeout) | ||
259 | { | ||
260 | return sci_dev->state_handlers->parent.start_handler(&sci_dev->parent); | ||
261 | } | ||
262 | |||
263 | |||
264 | enum sci_status scic_remote_device_stop( | ||
265 | struct scic_sds_remote_device *sci_dev, | ||
266 | u32 timeout) | ||
267 | { | ||
268 | return sci_dev->state_handlers->parent.stop_handler(&sci_dev->parent); | ||
269 | } | ||
270 | |||
271 | |||
272 | enum sci_status scic_remote_device_reset( | ||
273 | struct scic_sds_remote_device *sci_dev) | ||
274 | { | ||
275 | return sci_dev->state_handlers->parent.reset_handler(&sci_dev->parent); | ||
276 | } | ||
277 | |||
278 | |||
279 | enum sci_status scic_remote_device_reset_complete( | ||
280 | struct scic_sds_remote_device *sci_dev) | ||
281 | { | ||
282 | return sci_dev->state_handlers->parent.reset_complete_handler(&sci_dev->parent); | ||
283 | } | ||
284 | |||
285 | |||
286 | enum sci_sas_link_rate scic_remote_device_get_connection_rate( | ||
287 | struct scic_sds_remote_device *sci_dev) | ||
288 | { | ||
289 | return sci_dev->connection_rate; | ||
290 | } | ||
291 | |||
292 | |||
293 | void scic_remote_device_get_protocols( | ||
294 | struct scic_sds_remote_device *sci_dev, | ||
295 | struct smp_discover_response_protocols *pr) | ||
296 | { | ||
297 | pr->u.all = sci_dev->target_protocols.u.all; | ||
298 | } | ||
299 | |||
300 | #if !defined(DISABLE_ATAPI) | ||
301 | bool scic_remote_device_is_atapi(struct scic_sds_remote_device *sci_dev) | ||
302 | { | ||
303 | return sci_dev->is_atapi; | ||
304 | } | ||
305 | #endif | ||
306 | |||
307 | |||
308 | /* | ||
309 | * ***************************************************************************** | ||
310 | * * SCU DRIVER STANDARD (SDS) REMOTE DEVICE IMPLEMENTATIONS | ||
311 | * ***************************************************************************** */ | ||
312 | |||
313 | /** | ||
314 | * | ||
315 | * | ||
316 | * Remote device timer requirements | ||
317 | */ | ||
318 | #define SCIC_SDS_REMOTE_DEVICE_MINIMUM_TIMER_COUNT (0) | ||
319 | #define SCIC_SDS_REMOTE_DEVICE_MAXIMUM_TIMER_COUNT (SCI_MAX_REMOTE_DEVICES) | ||
320 | |||
321 | |||
322 | /** | ||
323 | * | ||
324 | * @this_device: The remote device for which the suspend is being requested. | ||
325 | * | ||
326 | * This method invokes the remote device suspend state handler. enum sci_status | ||
327 | */ | ||
328 | enum sci_status scic_sds_remote_device_suspend( | ||
329 | struct scic_sds_remote_device *this_device, | ||
330 | u32 suspend_type) | ||
331 | { | ||
332 | return this_device->state_handlers->suspend_handler(this_device, suspend_type); | ||
333 | } | ||
334 | |||
335 | /** | ||
336 | * | ||
337 | * @this_device: The remote device for which the resume is being requested. | ||
338 | * | ||
339 | * This method invokes the remote device resume state handler. enum sci_status | ||
340 | */ | ||
341 | enum sci_status scic_sds_remote_device_resume( | ||
342 | struct scic_sds_remote_device *this_device) | ||
343 | { | ||
344 | return this_device->state_handlers->resume_handler(this_device); | ||
345 | } | ||
346 | |||
347 | /** | ||
348 | * | ||
349 | * @this_device: The remote device for which the event handling is being | ||
350 | * requested. | ||
351 | * @frame_index: This is the frame index that is being processed. | ||
352 | * | ||
353 | * This method invokes the frame handler for the remote device state machine | ||
354 | * enum sci_status | ||
355 | */ | ||
356 | enum sci_status scic_sds_remote_device_frame_handler( | ||
357 | struct scic_sds_remote_device *this_device, | ||
358 | u32 frame_index) | ||
359 | { | ||
360 | return this_device->state_handlers->frame_handler(this_device, frame_index); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * | ||
365 | * @this_device: The remote device for which the event handling is being | ||
366 | * requested. | ||
367 | * @event_code: This is the event code that is to be processed. | ||
368 | * | ||
369 | * This method invokes the remote device event handler. enum sci_status | ||
370 | */ | ||
371 | enum sci_status scic_sds_remote_device_event_handler( | ||
372 | struct scic_sds_remote_device *this_device, | ||
373 | u32 event_code) | ||
374 | { | ||
375 | return this_device->state_handlers->event_handler(this_device, event_code); | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * | ||
380 | * @controller: The controller that is starting the io request. | ||
381 | * @this_device: The remote device for which the start io handling is being | ||
382 | * requested. | ||
383 | * @io_request: The io request that is being started. | ||
384 | * | ||
385 | * This method invokes the remote device start io handler. enum sci_status | ||
386 | */ | ||
387 | enum sci_status scic_sds_remote_device_start_io( | ||
388 | struct scic_sds_controller *controller, | ||
389 | struct scic_sds_remote_device *this_device, | ||
390 | struct scic_sds_request *io_request) | ||
391 | { | ||
392 | return this_device->state_handlers->parent.start_io_handler( | ||
393 | &this_device->parent, &io_request->parent); | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * | ||
398 | * @controller: The controller that is completing the io request. | ||
399 | * @this_device: The remote device for which the complete io handling is being | ||
400 | * requested. | ||
401 | * @io_request: The io request that is being completed. | ||
402 | * | ||
403 | * This method invokes the remote device complete io handler. enum sci_status | ||
404 | */ | ||
405 | enum sci_status scic_sds_remote_device_complete_io( | ||
406 | struct scic_sds_controller *controller, | ||
407 | struct scic_sds_remote_device *this_device, | ||
408 | struct scic_sds_request *io_request) | ||
409 | { | ||
410 | return this_device->state_handlers->parent.complete_io_handler( | ||
411 | &this_device->parent, &io_request->parent); | ||
412 | } | ||
413 | |||
414 | /** | ||
415 | * | ||
416 | * @controller: The controller that is starting the task request. | ||
417 | * @this_device: The remote device for which the start task handling is being | ||
418 | * requested. | ||
419 | * @io_request: The task request that is being started. | ||
420 | * | ||
421 | * This method invokes the remote device start task handler. enum sci_status | ||
422 | */ | ||
423 | enum sci_status scic_sds_remote_device_start_task( | ||
424 | struct scic_sds_controller *controller, | ||
425 | struct scic_sds_remote_device *this_device, | ||
426 | struct scic_sds_request *io_request) | ||
427 | { | ||
428 | return this_device->state_handlers->parent.start_task_handler( | ||
429 | &this_device->parent, &io_request->parent); | ||
430 | } | ||
431 | |||
432 | /** | ||
433 | * | ||
434 | * @controller: The controller that is completing the task request. | ||
435 | * @this_device: The remote device for which the complete task handling is | ||
436 | * being requested. | ||
437 | * @io_request: The task request that is being completed. | ||
438 | * | ||
439 | * This method invokes the remote device complete task handler. enum sci_status | ||
440 | */ | ||
441 | |||
442 | /** | ||
443 | * | ||
444 | * @this_device: | ||
445 | * @request: | ||
446 | * | ||
447 | * This method takes the request and bulids an appropriate SCU context for the | ||
448 | * request and then requests the controller to post the request. none | ||
449 | */ | ||
450 | void scic_sds_remote_device_post_request( | ||
451 | struct scic_sds_remote_device *this_device, | ||
452 | u32 request) | ||
453 | { | ||
454 | u32 context; | ||
455 | |||
456 | context = scic_sds_remote_device_build_command_context(this_device, request); | ||
457 | |||
458 | scic_sds_controller_post_request( | ||
459 | scic_sds_remote_device_get_controller(this_device), | ||
460 | context | ||
461 | ); | ||
462 | } | ||
463 | |||
464 | #if !defined(DISABLE_ATAPI) | ||
465 | /** | ||
466 | * | ||
467 | * @this_device: The device to be checked. | ||
468 | * | ||
469 | * This method check the signature fis of a stp device to decide whether a | ||
470 | * device is atapi or not. true if a device is atapi device. False if a device | ||
471 | * is not atapi. | ||
472 | */ | ||
473 | bool scic_sds_remote_device_is_atapi( | ||
474 | struct scic_sds_remote_device *this_device) | ||
475 | { | ||
476 | if (!this_device->target_protocols.u.bits.attached_stp_target) | ||
477 | return false; | ||
478 | else if (this_device->is_direct_attached) { | ||
479 | struct scic_sds_phy *phy; | ||
480 | struct scic_sata_phy_properties properties; | ||
481 | struct sata_fis_reg_d2h *signature_fis; | ||
482 | phy = scic_sds_port_get_a_connected_phy(this_device->owning_port); | ||
483 | scic_sata_phy_get_properties(phy, &properties); | ||
484 | |||
485 | /* decode the signature fis. */ | ||
486 | signature_fis = &(properties.signature_fis); | ||
487 | |||
488 | if ((signature_fis->sector_count == 0x01) | ||
489 | && (signature_fis->lba_low == 0x01) | ||
490 | && (signature_fis->lba_mid == 0x14) | ||
491 | && (signature_fis->lba_high == 0xEB) | ||
492 | && ((signature_fis->device & 0x5F) == 0x00) | ||
493 | ) { | ||
494 | /* An ATA device supporting the PACKET command set. */ | ||
495 | return true; | ||
496 | } else | ||
497 | return false; | ||
498 | } else { | ||
499 | /* Expander supported ATAPI device is not currently supported. */ | ||
500 | return false; | ||
501 | } | ||
502 | } | ||
503 | #endif | ||
504 | /* | ||
505 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
506 | * redistributing this file, you may do so under either license. | ||
507 | * | ||
508 | * GPL LICENSE SUMMARY | ||
509 | * | ||
510 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
511 | * | ||
512 | * This program is free software; you can redistribute it and/or modify | ||
513 | * it under the terms of version 2 of the GNU General Public License as | ||
514 | * published by the Free Software Foundation. | ||
515 | * | ||
516 | * This program is distributed in the hope that it will be useful, but | ||
517 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
518 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
519 | * General Public License for more details. | ||
520 | * | ||
521 | * You should have received a copy of the GNU General Public License | ||
522 | * along with this program; if not, write to the Free Software | ||
523 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
524 | * The full GNU General Public License is included in this distribution | ||
525 | * in the file called LICENSE.GPL. | ||
526 | * | ||
527 | * BSD LICENSE | ||
528 | * | ||
529 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
530 | * All rights reserved. | ||
531 | * | ||
532 | * Redistribution and use in source and binary forms, with or without | ||
533 | * modification, are permitted provided that the following conditions | ||
534 | * are met: | ||
535 | * | ||
536 | * * Redistributions of source code must retain the above copyright | ||
537 | * notice, this list of conditions and the following disclaimer. | ||
538 | * * Redistributions in binary form must reproduce the above copyright | ||
539 | * notice, this list of conditions and the following disclaimer in | ||
540 | * the documentation and/or other materials provided with the | ||
541 | * distribution. | ||
542 | * * Neither the name of Intel Corporation nor the names of its | ||
543 | * contributors may be used to endorse or promote products derived | ||
544 | * from this software without specific prior written permission. | ||
545 | * | ||
546 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
547 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
548 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
549 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
550 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
551 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
552 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
553 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
554 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
555 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
556 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
557 | */ | ||
558 | |||
559 | /** | ||
560 | * This file contains the state handlers for the struct scic_sds_remote_device for the | ||
561 | * base state machine. | ||
562 | * | ||
563 | * | ||
564 | */ | ||
565 | |||
566 | #include "sci_environment.h" | ||
567 | #include "scic_user_callback.h" | ||
568 | #include "scic_controller.h" | ||
569 | #include "scic_sds_remote_device.h" | ||
570 | #include "scic_sds_controller.h" | ||
571 | #include "scic_sds_port.h" | ||
572 | #include "scic_sds_request.h" | ||
573 | #include "scic_sds_remote_node_context.h" | ||
574 | #include "scu_event_codes.h" | ||
575 | |||
576 | /* | ||
577 | * ***************************************************************************** | ||
578 | * * PROTECTED METHODS | ||
579 | * ***************************************************************************** */ | ||
580 | |||
581 | /** | ||
582 | * | ||
583 | * @user_parameter: This is cast to a remote device object. | ||
584 | * | ||
585 | * This method is called once the remote node context is ready to be freed. | ||
586 | * The remote device can now report that its stop operation is complete. none | ||
587 | */ | ||
588 | static void scic_sds_cb_remote_device_rnc_destruct_complete( | ||
589 | void *user_parameter) | ||
590 | { | ||
591 | struct scic_sds_remote_device *this_device; | ||
592 | |||
593 | this_device = (struct scic_sds_remote_device *)user_parameter; | ||
594 | |||
595 | BUG_ON(this_device->started_request_count != 0); | ||
596 | |||
597 | sci_base_state_machine_change_state( | ||
598 | scic_sds_remote_device_get_base_state_machine(this_device), | ||
599 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPED | ||
600 | ); | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * | ||
605 | * @user_parameter: This is cast to a remote device object. | ||
606 | * | ||
607 | * This method is called once the remote node context has transisitioned to a | ||
608 | * ready state. This is the indication that the remote device object can also | ||
609 | * transition to ready. none | ||
610 | */ | ||
611 | static void scic_sds_remote_device_resume_complete_handler( | ||
612 | void *user_parameter) | ||
613 | { | ||
614 | struct scic_sds_remote_device *this_device; | ||
615 | |||
616 | this_device = (struct scic_sds_remote_device *)user_parameter; | ||
617 | |||
618 | if ( | ||
619 | sci_base_state_machine_get_state(&this_device->parent.state_machine) | ||
620 | != SCI_BASE_REMOTE_DEVICE_STATE_READY | ||
621 | ) { | ||
622 | sci_base_state_machine_change_state( | ||
623 | &this_device->parent.state_machine, | ||
624 | SCI_BASE_REMOTE_DEVICE_STATE_READY | ||
625 | ); | ||
626 | } | ||
627 | } | ||
628 | |||
629 | /** | ||
630 | * | ||
631 | * @device: This parameter specifies the device for which the request is being | ||
632 | * started. | ||
633 | * @request: This parameter specifies the request being started. | ||
634 | * @status: This parameter specifies the current start operation status. | ||
635 | * | ||
636 | * This method will perform the STP request start processing common to IO | ||
637 | * requests and task requests of all types. none | ||
638 | */ | ||
639 | void scic_sds_remote_device_start_request( | ||
640 | struct scic_sds_remote_device *this_device, | ||
641 | struct scic_sds_request *the_request, | ||
642 | enum sci_status status) | ||
643 | { | ||
644 | /* We still have a fault in starting the io complete it on the port */ | ||
645 | if (status == SCI_SUCCESS) | ||
646 | scic_sds_remote_device_increment_request_count(this_device); | ||
647 | else{ | ||
648 | this_device->owning_port->state_handlers->complete_io_handler( | ||
649 | this_device->owning_port, this_device, the_request | ||
650 | ); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | |||
655 | /** | ||
656 | * | ||
657 | * @request: This parameter specifies the request being continued. | ||
658 | * | ||
659 | * This method will continue to post tc for a STP request. This method usually | ||
660 | * serves as a callback when RNC gets resumed during a task management | ||
661 | * sequence. none | ||
662 | */ | ||
663 | void scic_sds_remote_device_continue_request( | ||
664 | struct scic_sds_remote_device *this_device) | ||
665 | { | ||
666 | /* we need to check if this request is still valid to continue. */ | ||
667 | if (this_device->working_request != NULL) { | ||
668 | struct scic_sds_request *this_request = this_device->working_request; | ||
669 | struct scic_sds_controller *scic = this_request->owning_controller; | ||
670 | u32 state = scic->parent.state_machine.current_state_id; | ||
671 | sci_base_controller_request_handler_t continue_io; | ||
672 | |||
673 | continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; | ||
674 | continue_io(&scic->parent, &this_request->target_device->parent, | ||
675 | &this_request->parent); | ||
676 | } | ||
677 | } | ||
678 | |||
679 | /** | ||
680 | * | ||
681 | * @user_parameter: This is cast to a remote device object. | ||
682 | * | ||
683 | * This method is called once the remote node context has reached a suspended | ||
684 | * state. The remote device can now report that its suspend operation is | ||
685 | * complete. none | ||
686 | */ | ||
687 | |||
688 | /** | ||
689 | * This method will terminate all of the IO requests in the controllers IO | ||
690 | * request table that were targeted for this device. | ||
691 | * @this_device: This parameter specifies the remote device for which to | ||
692 | * attempt to terminate all requests. | ||
693 | * | ||
694 | * This method returns an indication as to whether all requests were | ||
695 | * successfully terminated. If a single request fails to be terminated, then | ||
696 | * this method will return the failure. | ||
697 | */ | ||
698 | static enum sci_status scic_sds_remote_device_terminate_requests( | ||
699 | struct scic_sds_remote_device *this_device) | ||
700 | { | ||
701 | enum sci_status status = SCI_SUCCESS; | ||
702 | enum sci_status terminate_status = SCI_SUCCESS; | ||
703 | struct scic_sds_request *the_request; | ||
704 | u32 index; | ||
705 | u32 request_count = this_device->started_request_count; | ||
706 | |||
707 | for (index = 0; | ||
708 | (index < SCI_MAX_IO_REQUESTS) && (request_count > 0); | ||
709 | index++) { | ||
710 | the_request = this_device->owning_port->owning_controller->io_request_table[index]; | ||
711 | |||
712 | if ((the_request != NULL) && (the_request->target_device == this_device)) { | ||
713 | terminate_status = scic_controller_terminate_request( | ||
714 | this_device->owning_port->owning_controller, | ||
715 | this_device, | ||
716 | the_request | ||
717 | ); | ||
718 | |||
719 | if (terminate_status != SCI_SUCCESS) | ||
720 | status = terminate_status; | ||
721 | |||
722 | request_count--; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | return status; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * ***************************************************************************** | ||
731 | * * DEFAULT STATE HANDLERS | ||
732 | * ***************************************************************************** */ | ||
733 | |||
734 | /** | ||
735 | * | ||
736 | * @device: The struct sci_base_remote_device which is then cast into a | ||
737 | * struct scic_sds_remote_device. | ||
738 | * | ||
739 | * This method is the default start handler. It logs a warning and returns a | ||
740 | * failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
741 | */ | ||
742 | enum sci_status scic_sds_remote_device_default_start_handler( | ||
743 | struct sci_base_remote_device *device) | ||
744 | { | ||
745 | struct scic_sds_remote_device *sds_device = | ||
746 | (struct scic_sds_remote_device *)device; | ||
747 | |||
748 | dev_warn(scirdev_to_dev(sds_device), | ||
749 | "%s: SCIC Remote Device requested to start while in wrong " | ||
750 | "state %d\n", | ||
751 | __func__, | ||
752 | sci_base_state_machine_get_state( | ||
753 | scic_sds_remote_device_get_base_state_machine( | ||
754 | sds_device))); | ||
755 | |||
756 | return SCI_FAILURE_INVALID_STATE; | ||
757 | } | ||
758 | |||
759 | /** | ||
760 | * | ||
761 | * @device: The struct sci_base_remote_device which is then cast into a | ||
762 | * struct scic_sds_remote_device. | ||
763 | * | ||
764 | * This method is the default stop handler. It logs a warning and returns a | ||
765 | * failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
766 | */ | ||
767 | static enum sci_status scic_sds_remote_device_default_stop_handler( | ||
768 | struct sci_base_remote_device *device) | ||
769 | { | ||
770 | struct scic_sds_remote_device *sds_device = | ||
771 | (struct scic_sds_remote_device *)device; | ||
772 | |||
773 | dev_warn(scirdev_to_dev(sds_device), | ||
774 | "%s: SCIC Remote Device requested to stop while in wrong " | ||
775 | "state %d\n", | ||
776 | __func__, | ||
777 | sci_base_state_machine_get_state( | ||
778 | scic_sds_remote_device_get_base_state_machine( | ||
779 | sds_device))); | ||
780 | |||
781 | return SCI_FAILURE_INVALID_STATE; | ||
782 | } | ||
783 | |||
784 | /** | ||
785 | * | ||
786 | * @device: The struct sci_base_remote_device which is then cast into a | ||
787 | * struct scic_sds_remote_device. | ||
788 | * | ||
789 | * This method is the default fail handler. It logs a warning and returns a | ||
790 | * failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
791 | */ | ||
792 | enum sci_status scic_sds_remote_device_default_fail_handler( | ||
793 | struct sci_base_remote_device *device) | ||
794 | { | ||
795 | struct scic_sds_remote_device *sds_device = | ||
796 | (struct scic_sds_remote_device *)device; | ||
797 | |||
798 | dev_warn(scirdev_to_dev(sds_device), | ||
799 | "%s: SCIC Remote Device requested to fail while in wrong " | ||
800 | "state %d\n", | ||
801 | __func__, | ||
802 | sci_base_state_machine_get_state( | ||
803 | scic_sds_remote_device_get_base_state_machine( | ||
804 | sds_device))); | ||
805 | |||
806 | return SCI_FAILURE_INVALID_STATE; | ||
807 | } | ||
808 | |||
809 | /** | ||
810 | * | ||
811 | * @device: The struct sci_base_remote_device which is then cast into a | ||
812 | * struct scic_sds_remote_device. | ||
813 | * | ||
814 | * This method is the default destruct handler. It logs a warning and returns | ||
815 | * a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
816 | */ | ||
817 | enum sci_status scic_sds_remote_device_default_destruct_handler( | ||
818 | struct sci_base_remote_device *device) | ||
819 | { | ||
820 | struct scic_sds_remote_device *sds_device = | ||
821 | (struct scic_sds_remote_device *)device; | ||
822 | |||
823 | dev_warn(scirdev_to_dev(sds_device), | ||
824 | "%s: SCIC Remote Device requested to destroy while in " | ||
825 | "wrong state %d\n", | ||
826 | __func__, | ||
827 | sci_base_state_machine_get_state( | ||
828 | scic_sds_remote_device_get_base_state_machine( | ||
829 | sds_device))); | ||
830 | |||
831 | return SCI_FAILURE_INVALID_STATE; | ||
832 | } | ||
833 | |||
834 | /** | ||
835 | * | ||
836 | * @device: The struct sci_base_remote_device which is then cast into a | ||
837 | * struct scic_sds_remote_device. | ||
838 | * | ||
839 | * This method is the default reset handler. It logs a warning and returns a | ||
840 | * failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
841 | */ | ||
842 | enum sci_status scic_sds_remote_device_default_reset_handler( | ||
843 | struct sci_base_remote_device *device) | ||
844 | { | ||
845 | struct scic_sds_remote_device *sds_device = | ||
846 | (struct scic_sds_remote_device *)device; | ||
847 | |||
848 | dev_warn(scirdev_to_dev(sds_device), | ||
849 | "%s: SCIC Remote Device requested to reset while in wrong " | ||
850 | "state %d\n", | ||
851 | __func__, | ||
852 | sci_base_state_machine_get_state( | ||
853 | scic_sds_remote_device_get_base_state_machine( | ||
854 | sds_device))); | ||
855 | |||
856 | return SCI_FAILURE_INVALID_STATE; | ||
857 | } | ||
858 | |||
859 | /** | ||
860 | * | ||
861 | * @device: The struct sci_base_remote_device which is then cast into a | ||
862 | * struct scic_sds_remote_device. | ||
863 | * | ||
864 | * This method is the default reset complete handler. It logs a warning and | ||
865 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
866 | */ | ||
867 | enum sci_status scic_sds_remote_device_default_reset_complete_handler( | ||
868 | struct sci_base_remote_device *device) | ||
869 | { | ||
870 | struct scic_sds_remote_device *sds_device = | ||
871 | (struct scic_sds_remote_device *)device; | ||
872 | |||
873 | dev_warn(scirdev_to_dev(sds_device), | ||
874 | "%s: SCIC Remote Device requested to complete reset while " | ||
875 | "in wrong state %d\n", | ||
876 | __func__, | ||
877 | sci_base_state_machine_get_state( | ||
878 | scic_sds_remote_device_get_base_state_machine( | ||
879 | sds_device))); | ||
880 | |||
881 | return SCI_FAILURE_INVALID_STATE; | ||
882 | } | ||
883 | |||
884 | /** | ||
885 | * | ||
886 | * @device: The struct sci_base_remote_device which is then cast into a | ||
887 | * struct scic_sds_remote_device. | ||
888 | * | ||
889 | * This method is the default suspend handler. It logs a warning and returns a | ||
890 | * failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
891 | */ | ||
892 | enum sci_status scic_sds_remote_device_default_suspend_handler( | ||
893 | struct scic_sds_remote_device *this_device, | ||
894 | u32 suspend_type) | ||
895 | { | ||
896 | dev_warn(scirdev_to_dev(this_device), | ||
897 | "%s: SCIC Remote Device 0x%p requested to suspend %d while " | ||
898 | "in wrong state %d\n", | ||
899 | __func__, | ||
900 | this_device, | ||
901 | suspend_type, | ||
902 | sci_base_state_machine_get_state( | ||
903 | scic_sds_remote_device_get_base_state_machine( | ||
904 | this_device))); | ||
905 | |||
906 | return SCI_FAILURE_INVALID_STATE; | ||
907 | } | ||
908 | |||
909 | /** | ||
910 | * | ||
911 | * @device: The struct sci_base_remote_device which is then cast into a | ||
912 | * struct scic_sds_remote_device. | ||
913 | * | ||
914 | * This method is the default resume handler. It logs a warning and returns a | ||
915 | * failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
916 | */ | ||
917 | enum sci_status scic_sds_remote_device_default_resume_handler( | ||
918 | struct scic_sds_remote_device *this_device) | ||
919 | { | ||
920 | dev_warn(scirdev_to_dev(this_device), | ||
921 | "%s: SCIC Remote Device requested to resume while in " | ||
922 | "wrong state %d\n", | ||
923 | __func__, | ||
924 | sci_base_state_machine_get_state( | ||
925 | scic_sds_remote_device_get_base_state_machine( | ||
926 | this_device))); | ||
927 | |||
928 | return SCI_FAILURE_INVALID_STATE; | ||
929 | } | ||
930 | |||
931 | /** | ||
932 | * | ||
933 | * @device: The struct sci_base_remote_device which is then cast into a | ||
934 | * struct scic_sds_remote_device. | ||
935 | * @event_code: The event code that the struct scic_sds_controller wants the device | ||
936 | * object to process. | ||
937 | * | ||
938 | * This method is the default event handler. It will call the RNC state | ||
939 | * machine handler for any RNC events otherwise it will log a warning and | ||
940 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
941 | */ | ||
942 | static enum sci_status scic_sds_remote_device_core_event_handler( | ||
943 | struct scic_sds_remote_device *this_device, | ||
944 | u32 event_code, | ||
945 | bool is_ready_state) | ||
946 | { | ||
947 | enum sci_status status; | ||
948 | |||
949 | switch (scu_get_event_type(event_code)) { | ||
950 | case SCU_EVENT_TYPE_RNC_OPS_MISC: | ||
951 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX: | ||
952 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: | ||
953 | status = scic_sds_remote_node_context_event_handler(this_device->rnc, event_code); | ||
954 | break; | ||
955 | case SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT: | ||
956 | |||
957 | if (scu_get_event_code(event_code) == SCU_EVENT_IT_NEXUS_TIMEOUT) { | ||
958 | status = SCI_SUCCESS; | ||
959 | |||
960 | /* Suspend the associated RNC */ | ||
961 | scic_sds_remote_node_context_suspend(this_device->rnc, | ||
962 | SCI_SOFTWARE_SUSPENSION, | ||
963 | NULL, NULL); | ||
964 | |||
965 | dev_dbg(scirdev_to_dev(this_device), | ||
966 | "%s: device: %p event code: %x: %s\n", | ||
967 | __func__, this_device, event_code, | ||
968 | (is_ready_state) | ||
969 | ? "I_T_Nexus_Timeout event" | ||
970 | : "I_T_Nexus_Timeout event in wrong state"); | ||
971 | |||
972 | break; | ||
973 | } | ||
974 | /* Else, fall through and treat as unhandled... */ | ||
975 | |||
976 | default: | ||
977 | dev_dbg(scirdev_to_dev(this_device), | ||
978 | "%s: device: %p event code: %x: %s\n", | ||
979 | __func__, this_device, event_code, | ||
980 | (is_ready_state) | ||
981 | ? "unexpected event" | ||
982 | : "unexpected event in wrong state"); | ||
983 | status = SCI_FAILURE_INVALID_STATE; | ||
984 | break; | ||
985 | } | ||
986 | |||
987 | return status; | ||
988 | } | ||
989 | /** | ||
990 | * | ||
991 | * @device: The struct sci_base_remote_device which is then cast into a | ||
992 | * struct scic_sds_remote_device. | ||
993 | * @event_code: The event code that the struct scic_sds_controller wants the device | ||
994 | * object to process. | ||
995 | * | ||
996 | * This method is the default event handler. It will call the RNC state | ||
997 | * machine handler for any RNC events otherwise it will log a warning and | ||
998 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
999 | */ | ||
1000 | static enum sci_status scic_sds_remote_device_default_event_handler( | ||
1001 | struct scic_sds_remote_device *this_device, | ||
1002 | u32 event_code) | ||
1003 | { | ||
1004 | return scic_sds_remote_device_core_event_handler(this_device, | ||
1005 | event_code, | ||
1006 | false); | ||
1007 | } | ||
1008 | |||
1009 | /** | ||
1010 | * | ||
1011 | * @device: The struct sci_base_remote_device which is then cast into a | ||
1012 | * struct scic_sds_remote_device. | ||
1013 | * @frame_index: The frame index for which the struct scic_sds_controller wants this | ||
1014 | * device object to process. | ||
1015 | * | ||
1016 | * This method is the default unsolicited frame handler. It logs a warning, | ||
1017 | * releases the frame and returns a failure. enum sci_status | ||
1018 | * SCI_FAILURE_INVALID_STATE | ||
1019 | */ | ||
1020 | enum sci_status scic_sds_remote_device_default_frame_handler( | ||
1021 | struct scic_sds_remote_device *this_device, | ||
1022 | u32 frame_index) | ||
1023 | { | ||
1024 | dev_warn(scirdev_to_dev(this_device), | ||
1025 | "%s: SCIC Remote Device requested to handle frame %x " | ||
1026 | "while in wrong state %d\n", | ||
1027 | __func__, | ||
1028 | frame_index, | ||
1029 | sci_base_state_machine_get_state( | ||
1030 | &this_device->parent.state_machine)); | ||
1031 | |||
1032 | /* Return the frame back to the controller */ | ||
1033 | scic_sds_controller_release_frame( | ||
1034 | scic_sds_remote_device_get_controller(this_device), frame_index | ||
1035 | ); | ||
1036 | |||
1037 | return SCI_FAILURE_INVALID_STATE; | ||
1038 | } | ||
1039 | |||
1040 | /** | ||
1041 | * | ||
1042 | * @device: The struct sci_base_remote_device which is then cast into a | ||
1043 | * struct scic_sds_remote_device. | ||
1044 | * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST | ||
1045 | * to start. | ||
1046 | * | ||
1047 | * This method is the default start io handler. It logs a warning and returns | ||
1048 | * a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1049 | */ | ||
1050 | enum sci_status scic_sds_remote_device_default_start_request_handler( | ||
1051 | struct sci_base_remote_device *device, | ||
1052 | struct sci_base_request *request) | ||
1053 | { | ||
1054 | struct scic_sds_remote_device *sds_device = | ||
1055 | (struct scic_sds_remote_device *)device; | ||
1056 | |||
1057 | dev_warn(scirdev_to_dev(sds_device), | ||
1058 | "%s: SCIC Remote Device requested to start io request %p " | ||
1059 | "while in wrong state %d\n", | ||
1060 | __func__, | ||
1061 | request, | ||
1062 | sci_base_state_machine_get_state( | ||
1063 | scic_sds_remote_device_get_base_state_machine( | ||
1064 | (struct scic_sds_remote_device *)device))); | ||
1065 | |||
1066 | return SCI_FAILURE_INVALID_STATE; | ||
1067 | } | ||
1068 | |||
1069 | /** | ||
1070 | * | ||
1071 | * @device: The struct sci_base_remote_device which is then cast into a | ||
1072 | * struct scic_sds_remote_device. | ||
1073 | * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST | ||
1074 | * to complete. | ||
1075 | * | ||
1076 | * This method is the default complete io handler. It logs a warning and | ||
1077 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1078 | */ | ||
1079 | enum sci_status scic_sds_remote_device_default_complete_request_handler( | ||
1080 | struct sci_base_remote_device *device, | ||
1081 | struct sci_base_request *request) | ||
1082 | { | ||
1083 | struct scic_sds_remote_device *sds_device = | ||
1084 | (struct scic_sds_remote_device *)device; | ||
1085 | |||
1086 | dev_warn(scirdev_to_dev(sds_device), | ||
1087 | "%s: SCIC Remote Device requested to complete io_request %p " | ||
1088 | "while in wrong state %d\n", | ||
1089 | __func__, | ||
1090 | request, | ||
1091 | sci_base_state_machine_get_state( | ||
1092 | scic_sds_remote_device_get_base_state_machine( | ||
1093 | sds_device))); | ||
1094 | |||
1095 | return SCI_FAILURE_INVALID_STATE; | ||
1096 | } | ||
1097 | |||
1098 | /** | ||
1099 | * | ||
1100 | * @device: The struct sci_base_remote_device which is then cast into a | ||
1101 | * struct scic_sds_remote_device. | ||
1102 | * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST | ||
1103 | * to continue. | ||
1104 | * | ||
1105 | * This method is the default continue io handler. It logs a warning and | ||
1106 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1107 | */ | ||
1108 | enum sci_status scic_sds_remote_device_default_continue_request_handler( | ||
1109 | struct sci_base_remote_device *device, | ||
1110 | struct sci_base_request *request) | ||
1111 | { | ||
1112 | struct scic_sds_remote_device *sds_device = | ||
1113 | (struct scic_sds_remote_device *)device; | ||
1114 | |||
1115 | dev_warn(scirdev_to_dev(sds_device), | ||
1116 | "%s: SCIC Remote Device requested to continue io request %p " | ||
1117 | "while in wrong state %d\n", | ||
1118 | __func__, | ||
1119 | request, | ||
1120 | sci_base_state_machine_get_state( | ||
1121 | scic_sds_remote_device_get_base_state_machine( | ||
1122 | sds_device))); | ||
1123 | |||
1124 | return SCI_FAILURE_INVALID_STATE; | ||
1125 | } | ||
1126 | |||
1127 | /** | ||
1128 | * | ||
1129 | * @device: The struct sci_base_remote_device which is then cast into a | ||
1130 | * struct scic_sds_remote_device. | ||
1131 | * @request: The struct sci_base_request which is then cast into a SCIC_SDS_IO_REQUEST | ||
1132 | * to complete. | ||
1133 | * | ||
1134 | * This method is the default complete task handler. It logs a warning and | ||
1135 | * returns a failure. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1136 | */ | ||
1137 | |||
1138 | /* | ||
1139 | * ***************************************************************************** | ||
1140 | * * NORMAL STATE HANDLERS | ||
1141 | * ***************************************************************************** */ | ||
1142 | |||
1143 | /** | ||
1144 | * | ||
1145 | * @device: The struct sci_base_remote_device which is then cast into a | ||
1146 | * struct scic_sds_remote_device. | ||
1147 | * @frame_index: The frame index for which the struct scic_sds_controller wants this | ||
1148 | * device object to process. | ||
1149 | * | ||
1150 | * This method is a general ssp frame handler. In most cases the device object | ||
1151 | * needs to route the unsolicited frame processing to the io request object. | ||
1152 | * This method decodes the tag for the io request object and routes the | ||
1153 | * unsolicited frame to that object. enum sci_status SCI_FAILURE_INVALID_STATE | ||
1154 | */ | ||
1155 | enum sci_status scic_sds_remote_device_general_frame_handler( | ||
1156 | struct scic_sds_remote_device *this_device, | ||
1157 | u32 frame_index) | ||
1158 | { | ||
1159 | enum sci_status result; | ||
1160 | struct sci_ssp_frame_header *frame_header; | ||
1161 | struct scic_sds_request *io_request; | ||
1162 | |||
1163 | result = scic_sds_unsolicited_frame_control_get_header( | ||
1164 | &(scic_sds_remote_device_get_controller(this_device)->uf_control), | ||
1165 | frame_index, | ||
1166 | (void **)&frame_header | ||
1167 | ); | ||
1168 | |||
1169 | if (SCI_SUCCESS == result) { | ||
1170 | io_request = scic_sds_controller_get_io_request_from_tag( | ||
1171 | scic_sds_remote_device_get_controller(this_device), frame_header->tag); | ||
1172 | |||
1173 | if ((io_request == SCI_INVALID_HANDLE) | ||
1174 | || (io_request->target_device != this_device)) { | ||
1175 | /* | ||
1176 | * We could not map this tag to a valid IO request | ||
1177 | * Just toss the frame and continue */ | ||
1178 | scic_sds_controller_release_frame( | ||
1179 | scic_sds_remote_device_get_controller(this_device), frame_index | ||
1180 | ); | ||
1181 | } else { | ||
1182 | /* The IO request is now in charge of releasing the frame */ | ||
1183 | result = io_request->state_handlers->frame_handler( | ||
1184 | io_request, frame_index); | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | return result; | ||
1189 | } | ||
1190 | |||
1191 | /** | ||
1192 | * | ||
1193 | * @[in]: this_device This is the device object that is receiving the event. | ||
1194 | * @[in]: event_code The event code to process. | ||
1195 | * | ||
1196 | * This is a common method for handling events reported to the remote device | ||
1197 | * from the controller object. enum sci_status | ||
1198 | */ | ||
1199 | enum sci_status scic_sds_remote_device_general_event_handler( | ||
1200 | struct scic_sds_remote_device *this_device, | ||
1201 | u32 event_code) | ||
1202 | { | ||
1203 | return scic_sds_remote_device_core_event_handler(this_device, | ||
1204 | event_code, | ||
1205 | true); | ||
1206 | } | ||
1207 | |||
1208 | /* | ||
1209 | * ***************************************************************************** | ||
1210 | * * STOPPED STATE HANDLERS | ||
1211 | * ***************************************************************************** */ | ||
1212 | |||
1213 | /** | ||
1214 | * | ||
1215 | * @device: | ||
1216 | * | ||
1217 | * This method takes the struct scic_sds_remote_device from a stopped state and | ||
1218 | * attempts to start it. The RNC buffer for the device is constructed and the | ||
1219 | * device state machine is transitioned to the | ||
1220 | * SCIC_BASE_REMOTE_DEVICE_STATE_STARTING. enum sci_status SCI_SUCCESS if there is | ||
1221 | * an RNC buffer available to construct the remote device. | ||
1222 | * SCI_FAILURE_INSUFFICIENT_RESOURCES if there is no RNC buffer available in | ||
1223 | * which to construct the remote device. | ||
1224 | */ | ||
1225 | static enum sci_status scic_sds_remote_device_stopped_state_start_handler( | ||
1226 | struct sci_base_remote_device *device) | ||
1227 | { | ||
1228 | enum sci_status status; | ||
1229 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1230 | |||
1231 | status = scic_sds_remote_node_context_resume( | ||
1232 | this_device->rnc, | ||
1233 | scic_sds_remote_device_resume_complete_handler, | ||
1234 | this_device | ||
1235 | ); | ||
1236 | |||
1237 | if (status == SCI_SUCCESS) { | ||
1238 | sci_base_state_machine_change_state( | ||
1239 | scic_sds_remote_device_get_base_state_machine(this_device), | ||
1240 | SCI_BASE_REMOTE_DEVICE_STATE_STARTING | ||
1241 | ); | ||
1242 | } | ||
1243 | |||
1244 | return status; | ||
1245 | } | ||
1246 | |||
1247 | /** | ||
1248 | * | ||
1249 | * @this_device: The struct sci_base_remote_device which is cast into a | ||
1250 | * struct scic_sds_remote_device. | ||
1251 | * | ||
1252 | * This method will stop a struct scic_sds_remote_device that is already in a stopped | ||
1253 | * state. This is not considered an error since the device is already stopped. | ||
1254 | * enum sci_status SCI_SUCCESS | ||
1255 | */ | ||
1256 | static enum sci_status scic_sds_remote_device_stopped_state_stop_handler( | ||
1257 | struct sci_base_remote_device *this_device) | ||
1258 | { | ||
1259 | return SCI_SUCCESS; | ||
1260 | } | ||
1261 | |||
1262 | /** | ||
1263 | * | ||
1264 | * @this_device: The struct sci_base_remote_device which is cast into a | ||
1265 | * struct scic_sds_remote_device. | ||
1266 | * | ||
1267 | * This method will destruct a struct scic_sds_remote_device that is in a stopped | ||
1268 | * state. This is the only state from which a destruct request will succeed. | ||
1269 | * The RNi for this struct scic_sds_remote_device is returned to the free pool and the | ||
1270 | * device object transitions to the SCI_BASE_REMOTE_DEVICE_STATE_FINAL. | ||
1271 | * enum sci_status SCI_SUCCESS | ||
1272 | */ | ||
1273 | static enum sci_status scic_sds_remote_device_stopped_state_destruct_handler( | ||
1274 | struct sci_base_remote_device *device) | ||
1275 | { | ||
1276 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1277 | |||
1278 | scic_sds_controller_free_remote_node_context( | ||
1279 | scic_sds_remote_device_get_controller(this_device), | ||
1280 | this_device, | ||
1281 | this_device->rnc->remote_node_index | ||
1282 | ); | ||
1283 | |||
1284 | scic_sds_remote_node_context_set_remote_node_index( | ||
1285 | this_device->rnc, | ||
1286 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | ||
1287 | ); | ||
1288 | |||
1289 | scic_sds_port_set_direct_attached_device_id( | ||
1290 | this_device->owning_port, | ||
1291 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | ||
1292 | ); | ||
1293 | |||
1294 | sci_base_state_machine_change_state( | ||
1295 | scic_sds_remote_device_get_base_state_machine(this_device), | ||
1296 | SCI_BASE_REMOTE_DEVICE_STATE_FINAL | ||
1297 | ); | ||
1298 | |||
1299 | return SCI_SUCCESS; | ||
1300 | } | ||
1301 | |||
1302 | /* | ||
1303 | * ***************************************************************************** | ||
1304 | * * STARTING STATE HANDLERS | ||
1305 | * ***************************************************************************** */ | ||
1306 | |||
1307 | static enum sci_status scic_sds_remote_device_starting_state_stop_handler( | ||
1308 | struct sci_base_remote_device *device) | ||
1309 | { | ||
1310 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1311 | |||
1312 | /* | ||
1313 | * This device has not yet started so there had better be no IO requests | ||
1314 | */ | ||
1315 | BUG_ON(this_device->started_request_count != 0); | ||
1316 | |||
1317 | /* | ||
1318 | * Destroy the remote node context | ||
1319 | */ | ||
1320 | scic_sds_remote_node_context_destruct( | ||
1321 | this_device->rnc, | ||
1322 | scic_sds_cb_remote_device_rnc_destruct_complete, | ||
1323 | this_device | ||
1324 | ); | ||
1325 | |||
1326 | /* | ||
1327 | * Transition to the stopping state and wait for the remote node to | ||
1328 | * complete being posted and invalidated. | ||
1329 | */ | ||
1330 | sci_base_state_machine_change_state( | ||
1331 | scic_sds_remote_device_get_base_state_machine(this_device), | ||
1332 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING | ||
1333 | ); | ||
1334 | |||
1335 | return SCI_SUCCESS; | ||
1336 | } | ||
1337 | |||
1338 | /* | ||
1339 | * ***************************************************************************** | ||
1340 | * * INITIALIZING STATE HANDLERS | ||
1341 | * ***************************************************************************** */ | ||
1342 | |||
1343 | /* There is nothing to do here for SSP devices */ | ||
1344 | |||
1345 | /* | ||
1346 | * ***************************************************************************** | ||
1347 | * * READY STATE HANDLERS | ||
1348 | * ***************************************************************************** */ | ||
1349 | |||
1350 | /** | ||
1351 | * | ||
1352 | * @this_device: The struct scic_sds_remote_device object to be suspended. | ||
1353 | * | ||
1354 | * This method is the resume handler for the struct scic_sds_remote_device object. It | ||
1355 | * will post an RNC resume to the SCU hardware. enum sci_status SCI_SUCCESS | ||
1356 | */ | ||
1357 | |||
1358 | /** | ||
1359 | * | ||
1360 | * @device: The struct sci_base_remote_device object which is cast to a | ||
1361 | * struct scic_sds_remote_device object. | ||
1362 | * | ||
1363 | * This method is the default stop handler for the struct scic_sds_remote_device ready | ||
1364 | * substate machine. It will stop the current substate machine and transition | ||
1365 | * the base state machine to SCI_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status | ||
1366 | * SCI_SUCCESS | ||
1367 | */ | ||
1368 | enum sci_status scic_sds_remote_device_ready_state_stop_handler( | ||
1369 | struct sci_base_remote_device *device) | ||
1370 | { | ||
1371 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1372 | enum sci_status status = SCI_SUCCESS; | ||
1373 | |||
1374 | /* Request the parent state machine to transition to the stopping state */ | ||
1375 | sci_base_state_machine_change_state( | ||
1376 | scic_sds_remote_device_get_base_state_machine(this_device), | ||
1377 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING | ||
1378 | ); | ||
1379 | |||
1380 | if (this_device->started_request_count == 0) { | ||
1381 | scic_sds_remote_node_context_destruct( | ||
1382 | this_device->rnc, | ||
1383 | scic_sds_cb_remote_device_rnc_destruct_complete, | ||
1384 | this_device | ||
1385 | ); | ||
1386 | } else | ||
1387 | status = scic_sds_remote_device_terminate_requests(this_device); | ||
1388 | |||
1389 | return status; | ||
1390 | } | ||
1391 | |||
1392 | /** | ||
1393 | * | ||
1394 | * @device: The struct sci_base_remote_device object which is cast to a | ||
1395 | * struct scic_sds_remote_device object. | ||
1396 | * | ||
1397 | * This is the ready state device reset handler enum sci_status | ||
1398 | */ | ||
1399 | enum sci_status scic_sds_remote_device_ready_state_reset_handler( | ||
1400 | struct sci_base_remote_device *device) | ||
1401 | { | ||
1402 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1403 | |||
1404 | /* Request the parent state machine to transition to the stopping state */ | ||
1405 | sci_base_state_machine_change_state( | ||
1406 | scic_sds_remote_device_get_base_state_machine(this_device), | ||
1407 | SCI_BASE_REMOTE_DEVICE_STATE_RESETTING | ||
1408 | ); | ||
1409 | |||
1410 | return SCI_SUCCESS; | ||
1411 | } | ||
1412 | |||
1413 | /** | ||
1414 | * | ||
1415 | * @device: The struct sci_base_remote_device object which is cast to a | ||
1416 | * struct scic_sds_remote_device object. | ||
1417 | * | ||
1418 | * This is the default fail handler for the struct scic_sds_remote_device ready | ||
1419 | * substate machine. It will stop the current ready substate and transition | ||
1420 | * the remote device object to the SCI_BASE_REMOTE_DEVICE_STATE_FAILED. | ||
1421 | * enum sci_status SCI_SUCCESS | ||
1422 | */ | ||
1423 | |||
1424 | /** | ||
1425 | * | ||
1426 | * @device: The struct sci_base_remote_device which is cast to a | ||
1427 | * struct scic_sds_remote_device for which the request is to be started. | ||
1428 | * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that | ||
1429 | * is to be started. | ||
1430 | * | ||
1431 | * This method will attempt to start a task request for this device object. The | ||
1432 | * remote device object will issue the start request for the task and if | ||
1433 | * successful it will start the request for the port object then increment its | ||
1434 | * own requet count. enum sci_status SCI_SUCCESS if the task request is started for | ||
1435 | * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request | ||
1436 | * object could not get the resources to start. | ||
1437 | */ | ||
1438 | static enum sci_status scic_sds_remote_device_ready_state_start_task_handler( | ||
1439 | struct sci_base_remote_device *device, | ||
1440 | struct sci_base_request *request) | ||
1441 | { | ||
1442 | enum sci_status result; | ||
1443 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1444 | struct scic_sds_request *task_request = (struct scic_sds_request *)request; | ||
1445 | |||
1446 | /* See if the port is in a state where we can start the IO request */ | ||
1447 | result = scic_sds_port_start_io( | ||
1448 | scic_sds_remote_device_get_port(this_device), this_device, task_request); | ||
1449 | |||
1450 | if (result == SCI_SUCCESS) { | ||
1451 | result = scic_sds_remote_node_context_start_task( | ||
1452 | this_device->rnc, task_request | ||
1453 | ); | ||
1454 | |||
1455 | if (result == SCI_SUCCESS) { | ||
1456 | result = scic_sds_request_start(task_request); | ||
1457 | } | ||
1458 | |||
1459 | scic_sds_remote_device_start_request(this_device, task_request, result); | ||
1460 | } | ||
1461 | |||
1462 | return result; | ||
1463 | } | ||
1464 | |||
1465 | /** | ||
1466 | * | ||
1467 | * @device: The struct sci_base_remote_device which is cast to a | ||
1468 | * struct scic_sds_remote_device for which the request is to be started. | ||
1469 | * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that | ||
1470 | * is to be started. | ||
1471 | * | ||
1472 | * This method will attempt to start an io request for this device object. The | ||
1473 | * remote device object will issue the start request for the io and if | ||
1474 | * successful it will start the request for the port object then increment its | ||
1475 | * own requet count. enum sci_status SCI_SUCCESS if the io request is started for | ||
1476 | * this device object. SCI_FAILURE_INSUFFICIENT_RESOURCES if the io request | ||
1477 | * object could not get the resources to start. | ||
1478 | */ | ||
1479 | static enum sci_status scic_sds_remote_device_ready_state_start_io_handler( | ||
1480 | struct sci_base_remote_device *device, | ||
1481 | struct sci_base_request *request) | ||
1482 | { | ||
1483 | enum sci_status result; | ||
1484 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1485 | struct scic_sds_request *io_request = (struct scic_sds_request *)request; | ||
1486 | |||
1487 | /* See if the port is in a state where we can start the IO request */ | ||
1488 | result = scic_sds_port_start_io( | ||
1489 | scic_sds_remote_device_get_port(this_device), this_device, io_request); | ||
1490 | |||
1491 | if (result == SCI_SUCCESS) { | ||
1492 | result = scic_sds_remote_node_context_start_io( | ||
1493 | this_device->rnc, io_request | ||
1494 | ); | ||
1495 | |||
1496 | if (result == SCI_SUCCESS) { | ||
1497 | result = scic_sds_request_start(io_request); | ||
1498 | } | ||
1499 | |||
1500 | scic_sds_remote_device_start_request(this_device, io_request, result); | ||
1501 | } | ||
1502 | |||
1503 | return result; | ||
1504 | } | ||
1505 | |||
1506 | /** | ||
1507 | * | ||
1508 | * @device: The struct sci_base_remote_device which is cast to a | ||
1509 | * struct scic_sds_remote_device for which the request is to be completed. | ||
1510 | * @request: The struct sci_base_request which is cast to a SCIC_SDS_IO_REQUEST that | ||
1511 | * is to be completed. | ||
1512 | * | ||
1513 | * This method will complete the request for the remote device object. The | ||
1514 | * method will call the completion handler for the request object and if | ||
1515 | * successful it will complete the request on the port object then decrement | ||
1516 | * its own started_request_count. enum sci_status | ||
1517 | */ | ||
1518 | static enum sci_status scic_sds_remote_device_ready_state_complete_request_handler( | ||
1519 | struct sci_base_remote_device *device, | ||
1520 | struct sci_base_request *request) | ||
1521 | { | ||
1522 | enum sci_status result; | ||
1523 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1524 | struct scic_sds_request *the_request = (struct scic_sds_request *)request; | ||
1525 | |||
1526 | result = scic_sds_request_complete(the_request); | ||
1527 | |||
1528 | if (result == SCI_SUCCESS) { | ||
1529 | /* See if the port is in a state where we can start the IO request */ | ||
1530 | result = scic_sds_port_complete_io( | ||
1531 | scic_sds_remote_device_get_port(this_device), this_device, the_request); | ||
1532 | |||
1533 | if (result == SCI_SUCCESS) { | ||
1534 | scic_sds_remote_device_decrement_request_count(this_device); | ||
1535 | } | ||
1536 | } | ||
1537 | |||
1538 | return result; | ||
1539 | } | ||
1540 | |||
1541 | /* | ||
1542 | * ***************************************************************************** | ||
1543 | * * STOPPING STATE HANDLERS | ||
1544 | * ***************************************************************************** */ | ||
1545 | |||
1546 | /** | ||
1547 | * | ||
1548 | * @this_device: The struct sci_base_remote_device which is cast into a | ||
1549 | * struct scic_sds_remote_device. | ||
1550 | * | ||
1551 | * This method will stop a struct scic_sds_remote_device that is already in the | ||
1552 | * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This is not considered an error | ||
1553 | * since we allow a stop request on a device that is alreay stopping or | ||
1554 | * stopped. enum sci_status SCI_SUCCESS | ||
1555 | */ | ||
1556 | static enum sci_status scic_sds_remote_device_stopping_state_stop_handler( | ||
1557 | struct sci_base_remote_device *device) | ||
1558 | { | ||
1559 | /* | ||
1560 | * All requests should have been terminated, but if there is an | ||
1561 | * attempt to stop a device already in the stopping state, then | ||
1562 | * try again to terminate. */ | ||
1563 | return scic_sds_remote_device_terminate_requests( | ||
1564 | (struct scic_sds_remote_device *)device); | ||
1565 | } | ||
1566 | |||
1567 | |||
1568 | /** | ||
1569 | * | ||
1570 | * @device: The device object for which the request is completing. | ||
1571 | * @request: The task request that is being completed. | ||
1572 | * | ||
1573 | * This method completes requests for this struct scic_sds_remote_device while it is | ||
1574 | * in the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING state. This method calls the | ||
1575 | * complete method for the request object and if that is successful the port | ||
1576 | * object is called to complete the task request. Then the device object itself | ||
1577 | * completes the task request. If struct scic_sds_remote_device started_request_count | ||
1578 | * goes to 0 and the invalidate RNC request has completed the device object can | ||
1579 | * transition to the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED. enum sci_status | ||
1580 | */ | ||
1581 | static enum sci_status scic_sds_remote_device_stopping_state_complete_request_handler( | ||
1582 | struct sci_base_remote_device *device, | ||
1583 | struct sci_base_request *request) | ||
1584 | { | ||
1585 | enum sci_status status = SCI_SUCCESS; | ||
1586 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
1587 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1588 | |||
1589 | status = scic_sds_request_complete(this_request); | ||
1590 | if (status == SCI_SUCCESS) { | ||
1591 | status = scic_sds_port_complete_io( | ||
1592 | scic_sds_remote_device_get_port(this_device), | ||
1593 | this_device, | ||
1594 | this_request | ||
1595 | ); | ||
1596 | |||
1597 | if (status == SCI_SUCCESS) { | ||
1598 | scic_sds_remote_device_decrement_request_count(this_device); | ||
1599 | |||
1600 | if (scic_sds_remote_device_get_request_count(this_device) == 0) { | ||
1601 | scic_sds_remote_node_context_destruct( | ||
1602 | this_device->rnc, | ||
1603 | scic_sds_cb_remote_device_rnc_destruct_complete, | ||
1604 | this_device | ||
1605 | ); | ||
1606 | } | ||
1607 | } | ||
1608 | } | ||
1609 | |||
1610 | return status; | ||
1611 | } | ||
1612 | |||
1613 | /* | ||
1614 | * ***************************************************************************** | ||
1615 | * * RESETTING STATE HANDLERS | ||
1616 | * ***************************************************************************** */ | ||
1617 | |||
1618 | /** | ||
1619 | * | ||
1620 | * @device: The struct sci_base_remote_device which is to be cast into a | ||
1621 | * struct scic_sds_remote_device object. | ||
1622 | * | ||
1623 | * This method will complete the reset operation when the device is in the | ||
1624 | * resetting state. enum sci_status | ||
1625 | */ | ||
1626 | static enum sci_status scic_sds_remote_device_resetting_state_reset_complete_handler( | ||
1627 | struct sci_base_remote_device *device) | ||
1628 | { | ||
1629 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1630 | |||
1631 | sci_base_state_machine_change_state( | ||
1632 | &this_device->parent.state_machine, | ||
1633 | SCI_BASE_REMOTE_DEVICE_STATE_READY | ||
1634 | ); | ||
1635 | |||
1636 | return SCI_SUCCESS; | ||
1637 | } | ||
1638 | |||
1639 | /** | ||
1640 | * | ||
1641 | * @device: The struct sci_base_remote_device which is to be cast into a | ||
1642 | * struct scic_sds_remote_device object. | ||
1643 | * | ||
1644 | * This method will stop the remote device while in the resetting state. | ||
1645 | * enum sci_status | ||
1646 | */ | ||
1647 | static enum sci_status scic_sds_remote_device_resetting_state_stop_handler( | ||
1648 | struct sci_base_remote_device *device) | ||
1649 | { | ||
1650 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1651 | |||
1652 | sci_base_state_machine_change_state( | ||
1653 | &this_device->parent.state_machine, | ||
1654 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING | ||
1655 | ); | ||
1656 | |||
1657 | return SCI_SUCCESS; | ||
1658 | } | ||
1659 | |||
1660 | /** | ||
1661 | * | ||
1662 | * @device: The device object for which the request is completing. | ||
1663 | * @request: The task request that is being completed. | ||
1664 | * | ||
1665 | * This method completes requests for this struct scic_sds_remote_device while it is | ||
1666 | * in the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING state. This method calls the | ||
1667 | * complete method for the request object and if that is successful the port | ||
1668 | * object is called to complete the task request. Then the device object itself | ||
1669 | * completes the task request. enum sci_status | ||
1670 | */ | ||
1671 | static enum sci_status scic_sds_remote_device_resetting_state_complete_request_handler( | ||
1672 | struct sci_base_remote_device *device, | ||
1673 | struct sci_base_request *request) | ||
1674 | { | ||
1675 | enum sci_status status = SCI_SUCCESS; | ||
1676 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
1677 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
1678 | |||
1679 | status = scic_sds_request_complete(this_request); | ||
1680 | |||
1681 | if (status == SCI_SUCCESS) { | ||
1682 | status = scic_sds_port_complete_io( | ||
1683 | scic_sds_remote_device_get_port(this_device), this_device, this_request); | ||
1684 | |||
1685 | if (status == SCI_SUCCESS) { | ||
1686 | scic_sds_remote_device_decrement_request_count(this_device); | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | return status; | ||
1691 | } | ||
1692 | |||
1693 | /* | ||
1694 | * ***************************************************************************** | ||
1695 | * * FAILED STATE HANDLERS | ||
1696 | * ***************************************************************************** */ | ||
1697 | |||
1698 | /** | ||
1699 | * | ||
1700 | * @device: The struct sci_base_remote_device which is to be cast into a | ||
1701 | * struct scic_sds_remote_device object. | ||
1702 | * | ||
1703 | * This method handles the remove request for a failed struct scic_sds_remote_device | ||
1704 | * object. The method will transition the device object to the | ||
1705 | * SCIC_BASE_REMOTE_DEVICE_STATE_STOPPING. enum sci_status SCI_SUCCESS | ||
1706 | */ | ||
1707 | |||
1708 | /* --------------------------------------------------------------------------- */ | ||
1709 | |||
1710 | struct scic_sds_remote_device_state_handler | ||
1711 | scic_sds_remote_device_state_handler_table[SCI_BASE_REMOTE_DEVICE_MAX_STATES] = | ||
1712 | { | ||
1713 | /* SCI_BASE_REMOTE_DEVICE_STATE_INITIAL */ | ||
1714 | { | ||
1715 | { | ||
1716 | scic_sds_remote_device_default_start_handler, | ||
1717 | scic_sds_remote_device_default_stop_handler, | ||
1718 | scic_sds_remote_device_default_fail_handler, | ||
1719 | scic_sds_remote_device_default_destruct_handler, | ||
1720 | scic_sds_remote_device_default_reset_handler, | ||
1721 | scic_sds_remote_device_default_reset_complete_handler, | ||
1722 | scic_sds_remote_device_default_start_request_handler, | ||
1723 | scic_sds_remote_device_default_complete_request_handler, | ||
1724 | scic_sds_remote_device_default_continue_request_handler, | ||
1725 | scic_sds_remote_device_default_start_request_handler, | ||
1726 | scic_sds_remote_device_default_complete_request_handler | ||
1727 | }, | ||
1728 | scic_sds_remote_device_default_suspend_handler, | ||
1729 | scic_sds_remote_device_default_resume_handler, | ||
1730 | scic_sds_remote_device_default_event_handler, | ||
1731 | scic_sds_remote_device_default_frame_handler | ||
1732 | }, | ||
1733 | /* SCI_BASE_REMOTE_DEVICE_STATE_STOPPED */ | ||
1734 | { | ||
1735 | { | ||
1736 | scic_sds_remote_device_stopped_state_start_handler, | ||
1737 | scic_sds_remote_device_stopped_state_stop_handler, | ||
1738 | scic_sds_remote_device_default_fail_handler, | ||
1739 | scic_sds_remote_device_stopped_state_destruct_handler, | ||
1740 | scic_sds_remote_device_default_reset_handler, | ||
1741 | scic_sds_remote_device_default_reset_complete_handler, | ||
1742 | scic_sds_remote_device_default_start_request_handler, | ||
1743 | scic_sds_remote_device_default_complete_request_handler, | ||
1744 | scic_sds_remote_device_default_continue_request_handler, | ||
1745 | scic_sds_remote_device_default_start_request_handler, | ||
1746 | scic_sds_remote_device_default_complete_request_handler | ||
1747 | }, | ||
1748 | scic_sds_remote_device_default_suspend_handler, | ||
1749 | scic_sds_remote_device_default_resume_handler, | ||
1750 | scic_sds_remote_device_default_event_handler, | ||
1751 | scic_sds_remote_device_default_frame_handler | ||
1752 | }, | ||
1753 | /* SCI_BASE_REMOTE_DEVICE_STATE_STARTING */ | ||
1754 | { | ||
1755 | { | ||
1756 | scic_sds_remote_device_default_start_handler, | ||
1757 | scic_sds_remote_device_starting_state_stop_handler, | ||
1758 | scic_sds_remote_device_default_fail_handler, | ||
1759 | scic_sds_remote_device_default_destruct_handler, | ||
1760 | scic_sds_remote_device_default_reset_handler, | ||
1761 | scic_sds_remote_device_default_reset_complete_handler, | ||
1762 | scic_sds_remote_device_default_start_request_handler, | ||
1763 | scic_sds_remote_device_default_complete_request_handler, | ||
1764 | scic_sds_remote_device_default_continue_request_handler, | ||
1765 | scic_sds_remote_device_default_start_request_handler, | ||
1766 | scic_sds_remote_device_default_complete_request_handler | ||
1767 | }, | ||
1768 | scic_sds_remote_device_default_suspend_handler, | ||
1769 | scic_sds_remote_device_default_resume_handler, | ||
1770 | scic_sds_remote_device_general_event_handler, | ||
1771 | scic_sds_remote_device_default_frame_handler | ||
1772 | }, | ||
1773 | /* SCI_BASE_REMOTE_DEVICE_STATE_READY */ | ||
1774 | { | ||
1775 | { | ||
1776 | scic_sds_remote_device_default_start_handler, | ||
1777 | scic_sds_remote_device_ready_state_stop_handler, | ||
1778 | scic_sds_remote_device_default_fail_handler, | ||
1779 | scic_sds_remote_device_default_destruct_handler, | ||
1780 | scic_sds_remote_device_ready_state_reset_handler, | ||
1781 | scic_sds_remote_device_default_reset_complete_handler, | ||
1782 | scic_sds_remote_device_ready_state_start_io_handler, | ||
1783 | scic_sds_remote_device_ready_state_complete_request_handler, | ||
1784 | scic_sds_remote_device_default_continue_request_handler, | ||
1785 | scic_sds_remote_device_ready_state_start_task_handler, | ||
1786 | scic_sds_remote_device_ready_state_complete_request_handler | ||
1787 | }, | ||
1788 | scic_sds_remote_device_default_suspend_handler, | ||
1789 | scic_sds_remote_device_default_resume_handler, | ||
1790 | scic_sds_remote_device_general_event_handler, | ||
1791 | scic_sds_remote_device_general_frame_handler, | ||
1792 | }, | ||
1793 | /* SCI_BASE_REMOTE_DEVICE_STATE_STOPPING */ | ||
1794 | { | ||
1795 | { | ||
1796 | scic_sds_remote_device_default_start_handler, | ||
1797 | scic_sds_remote_device_stopping_state_stop_handler, | ||
1798 | scic_sds_remote_device_default_fail_handler, | ||
1799 | scic_sds_remote_device_default_destruct_handler, | ||
1800 | scic_sds_remote_device_default_reset_handler, | ||
1801 | scic_sds_remote_device_default_reset_complete_handler, | ||
1802 | scic_sds_remote_device_default_start_request_handler, | ||
1803 | scic_sds_remote_device_stopping_state_complete_request_handler, | ||
1804 | scic_sds_remote_device_default_continue_request_handler, | ||
1805 | scic_sds_remote_device_default_start_request_handler, | ||
1806 | scic_sds_remote_device_stopping_state_complete_request_handler | ||
1807 | }, | ||
1808 | scic_sds_remote_device_default_suspend_handler, | ||
1809 | scic_sds_remote_device_default_resume_handler, | ||
1810 | scic_sds_remote_device_general_event_handler, | ||
1811 | scic_sds_remote_device_general_frame_handler | ||
1812 | }, | ||
1813 | /* SCI_BASE_REMOTE_DEVICE_STATE_FAILED */ | ||
1814 | { | ||
1815 | { | ||
1816 | scic_sds_remote_device_default_start_handler, | ||
1817 | scic_sds_remote_device_default_stop_handler, | ||
1818 | scic_sds_remote_device_default_fail_handler, | ||
1819 | scic_sds_remote_device_default_destruct_handler, | ||
1820 | scic_sds_remote_device_default_reset_handler, | ||
1821 | scic_sds_remote_device_default_reset_complete_handler, | ||
1822 | scic_sds_remote_device_default_start_request_handler, | ||
1823 | scic_sds_remote_device_default_complete_request_handler, | ||
1824 | scic_sds_remote_device_default_continue_request_handler, | ||
1825 | scic_sds_remote_device_default_start_request_handler, | ||
1826 | scic_sds_remote_device_default_complete_request_handler | ||
1827 | }, | ||
1828 | scic_sds_remote_device_default_suspend_handler, | ||
1829 | scic_sds_remote_device_default_resume_handler, | ||
1830 | scic_sds_remote_device_default_event_handler, | ||
1831 | scic_sds_remote_device_general_frame_handler | ||
1832 | }, | ||
1833 | /* SCI_BASE_REMOTE_DEVICE_STATE_RESETTING */ | ||
1834 | { | ||
1835 | { | ||
1836 | scic_sds_remote_device_default_start_handler, | ||
1837 | scic_sds_remote_device_resetting_state_stop_handler, | ||
1838 | scic_sds_remote_device_default_fail_handler, | ||
1839 | scic_sds_remote_device_default_destruct_handler, | ||
1840 | scic_sds_remote_device_default_reset_handler, | ||
1841 | scic_sds_remote_device_resetting_state_reset_complete_handler, | ||
1842 | scic_sds_remote_device_default_start_request_handler, | ||
1843 | scic_sds_remote_device_resetting_state_complete_request_handler, | ||
1844 | scic_sds_remote_device_default_continue_request_handler, | ||
1845 | scic_sds_remote_device_default_start_request_handler, | ||
1846 | scic_sds_remote_device_resetting_state_complete_request_handler | ||
1847 | }, | ||
1848 | scic_sds_remote_device_default_suspend_handler, | ||
1849 | scic_sds_remote_device_default_resume_handler, | ||
1850 | scic_sds_remote_device_default_event_handler, | ||
1851 | scic_sds_remote_device_general_frame_handler | ||
1852 | }, | ||
1853 | /* SCI_BASE_REMOTE_DEVICE_STATE_FINAL */ | ||
1854 | { | ||
1855 | { | ||
1856 | scic_sds_remote_device_default_start_handler, | ||
1857 | scic_sds_remote_device_default_stop_handler, | ||
1858 | scic_sds_remote_device_default_fail_handler, | ||
1859 | scic_sds_remote_device_default_destruct_handler, | ||
1860 | scic_sds_remote_device_default_reset_handler, | ||
1861 | scic_sds_remote_device_default_reset_complete_handler, | ||
1862 | scic_sds_remote_device_default_start_request_handler, | ||
1863 | scic_sds_remote_device_default_complete_request_handler, | ||
1864 | scic_sds_remote_device_default_continue_request_handler, | ||
1865 | scic_sds_remote_device_default_start_request_handler, | ||
1866 | scic_sds_remote_device_default_complete_request_handler | ||
1867 | }, | ||
1868 | scic_sds_remote_device_default_suspend_handler, | ||
1869 | scic_sds_remote_device_default_resume_handler, | ||
1870 | scic_sds_remote_device_default_event_handler, | ||
1871 | scic_sds_remote_device_default_frame_handler | ||
1872 | } | ||
1873 | }; | ||
1874 | |||
1875 | /* | ||
1876 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
1877 | * redistributing this file, you may do so under either license. | ||
1878 | * | ||
1879 | * GPL LICENSE SUMMARY | ||
1880 | * | ||
1881 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
1882 | * | ||
1883 | * This program is free software; you can redistribute it and/or modify | ||
1884 | * it under the terms of version 2 of the GNU General Public License as | ||
1885 | * published by the Free Software Foundation. | ||
1886 | * | ||
1887 | * This program is distributed in the hope that it will be useful, but | ||
1888 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1889 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
1890 | * General Public License for more details. | ||
1891 | * | ||
1892 | * You should have received a copy of the GNU General Public License | ||
1893 | * along with this program; if not, write to the Free Software | ||
1894 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
1895 | * The full GNU General Public License is included in this distribution | ||
1896 | * in the file called LICENSE.GPL. | ||
1897 | * | ||
1898 | * BSD LICENSE | ||
1899 | * | ||
1900 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
1901 | * All rights reserved. | ||
1902 | * | ||
1903 | * Redistribution and use in source and binary forms, with or without | ||
1904 | * modification, are permitted provided that the following conditions | ||
1905 | * are met: | ||
1906 | * | ||
1907 | * * Redistributions of source code must retain the above copyright | ||
1908 | * notice, this list of conditions and the following disclaimer. | ||
1909 | * * Redistributions in binary form must reproduce the above copyright | ||
1910 | * notice, this list of conditions and the following disclaimer in | ||
1911 | * the documentation and/or other materials provided with the | ||
1912 | * distribution. | ||
1913 | * * Neither the name of Intel Corporation nor the names of its | ||
1914 | * contributors may be used to endorse or promote products derived | ||
1915 | * from this software without specific prior written permission. | ||
1916 | * | ||
1917 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
1918 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
1919 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
1920 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
1921 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
1922 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
1923 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
1924 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
1925 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
1926 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
1927 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
1928 | */ | ||
1929 | |||
1930 | /** | ||
1931 | * This file contains the operations that are taken on the enter and exit state | ||
1932 | * transitions for the struct sci_base_remote_device state machine. | ||
1933 | * | ||
1934 | * | ||
1935 | */ | ||
1936 | |||
1937 | #include "scic_remote_device.h" | ||
1938 | #include "scic_user_callback.h" | ||
1939 | #include "scic_sds_controller.h" | ||
1940 | #include "scic_sds_remote_device.h" | ||
1941 | #include "scic_sds_request.h" | ||
1942 | #include "scic_sds_controller.h" | ||
1943 | #include "scic_sds_port.h" | ||
1944 | |||
1945 | /** | ||
1946 | * | ||
1947 | * @object: This is the struct sci_base_object that is cast into a | ||
1948 | * struct scic_sds_remote_device. | ||
1949 | * | ||
1950 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it | ||
1951 | * immediatly transitions the remote device object to the stopped state. none | ||
1952 | */ | ||
1953 | static void scic_sds_remote_device_initial_state_enter( | ||
1954 | struct sci_base_object *object) | ||
1955 | { | ||
1956 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
1957 | |||
1958 | SET_STATE_HANDLER( | ||
1959 | this_device, | ||
1960 | scic_sds_remote_device_state_handler_table, | ||
1961 | SCI_BASE_REMOTE_DEVICE_STATE_INITIAL | ||
1962 | ); | ||
1963 | |||
1964 | /* Initial state is a transitional state to the stopped state */ | ||
1965 | sci_base_state_machine_change_state( | ||
1966 | scic_sds_remote_device_get_base_state_machine(this_device), | ||
1967 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPED | ||
1968 | ); | ||
1969 | } | ||
1970 | |||
1971 | /** | ||
1972 | * | ||
1973 | * @object: This is the struct sci_base_object that is cast into a | ||
1974 | * struct scic_sds_remote_device. | ||
1975 | * | ||
1976 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_INITIAL it | ||
1977 | * sets the stopped state handlers and if this state is entered from the | ||
1978 | * SCI_BASE_REMOTE_DEVICE_STATE_STOPPING then the SCI User is informed that the | ||
1979 | * device stop is complete. none | ||
1980 | */ | ||
1981 | static void scic_sds_remote_device_stopped_state_enter( | ||
1982 | struct sci_base_object *object) | ||
1983 | { | ||
1984 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
1985 | |||
1986 | SET_STATE_HANDLER( | ||
1987 | this_device, | ||
1988 | scic_sds_remote_device_state_handler_table, | ||
1989 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPED | ||
1990 | ); | ||
1991 | |||
1992 | /* | ||
1993 | * If we are entering from the stopping state let the SCI User know that | ||
1994 | * the stop operation has completed. */ | ||
1995 | if (this_device->parent.state_machine.previous_state_id | ||
1996 | == SCI_BASE_REMOTE_DEVICE_STATE_STOPPING) { | ||
1997 | scic_cb_remote_device_stop_complete( | ||
1998 | scic_sds_remote_device_get_controller(this_device), | ||
1999 | this_device, | ||
2000 | SCI_SUCCESS | ||
2001 | ); | ||
2002 | } | ||
2003 | } | ||
2004 | |||
2005 | /** | ||
2006 | * | ||
2007 | * @object: This is the struct sci_base_object that is cast into a | ||
2008 | * struct scic_sds_remote_device. | ||
2009 | * | ||
2010 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it | ||
2011 | * sets the starting state handlers, sets the device not ready, and posts the | ||
2012 | * remote node context to the hardware. none | ||
2013 | */ | ||
2014 | static void scic_sds_remote_device_starting_state_enter( | ||
2015 | struct sci_base_object *object) | ||
2016 | { | ||
2017 | struct scic_sds_controller *the_controller; | ||
2018 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2019 | |||
2020 | the_controller = scic_sds_remote_device_get_controller(this_device); | ||
2021 | |||
2022 | SET_STATE_HANDLER( | ||
2023 | this_device, | ||
2024 | scic_sds_remote_device_state_handler_table, | ||
2025 | SCI_BASE_REMOTE_DEVICE_STATE_STARTING | ||
2026 | ); | ||
2027 | |||
2028 | scic_cb_remote_device_not_ready( | ||
2029 | the_controller, | ||
2030 | this_device, | ||
2031 | SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED | ||
2032 | ); | ||
2033 | } | ||
2034 | |||
2035 | /** | ||
2036 | * | ||
2037 | * @object: This is the struct sci_base_object that is cast into a | ||
2038 | * struct scic_sds_remote_device. | ||
2039 | * | ||
2040 | * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_STARTING it | ||
2041 | * reports that the device start is complete. none | ||
2042 | */ | ||
2043 | static void scic_sds_remote_device_starting_state_exit( | ||
2044 | struct sci_base_object *object) | ||
2045 | { | ||
2046 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2047 | |||
2048 | /* | ||
2049 | * / @todo Check the device object for the proper return code for this | ||
2050 | * / callback */ | ||
2051 | scic_cb_remote_device_start_complete( | ||
2052 | scic_sds_remote_device_get_controller(this_device), | ||
2053 | this_device, | ||
2054 | SCI_SUCCESS | ||
2055 | ); | ||
2056 | } | ||
2057 | |||
2058 | /** | ||
2059 | * | ||
2060 | * @object: This is the struct sci_base_object that is cast into a | ||
2061 | * struct scic_sds_remote_device. | ||
2062 | * | ||
2063 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it sets | ||
2064 | * the ready state handlers, and starts the ready substate machine. none | ||
2065 | */ | ||
2066 | static void scic_sds_remote_device_ready_state_enter( | ||
2067 | struct sci_base_object *object) | ||
2068 | { | ||
2069 | struct scic_sds_controller *the_controller; | ||
2070 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2071 | |||
2072 | the_controller = scic_sds_remote_device_get_controller(this_device); | ||
2073 | |||
2074 | SET_STATE_HANDLER( | ||
2075 | this_device, | ||
2076 | scic_sds_remote_device_state_handler_table, | ||
2077 | SCI_BASE_REMOTE_DEVICE_STATE_READY | ||
2078 | ); | ||
2079 | |||
2080 | the_controller->remote_device_sequence[this_device->rnc->remote_node_index]++; | ||
2081 | |||
2082 | if (this_device->has_ready_substate_machine) { | ||
2083 | sci_base_state_machine_start(&this_device->ready_substate_machine); | ||
2084 | } else { | ||
2085 | scic_cb_remote_device_ready(the_controller, this_device); | ||
2086 | } | ||
2087 | } | ||
2088 | |||
2089 | /** | ||
2090 | * | ||
2091 | * @object: This is the struct sci_base_object that is cast into a | ||
2092 | * struct scic_sds_remote_device. | ||
2093 | * | ||
2094 | * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_READY it does | ||
2095 | * nothing. none | ||
2096 | */ | ||
2097 | static void scic_sds_remote_device_ready_state_exit( | ||
2098 | struct sci_base_object *object) | ||
2099 | { | ||
2100 | struct scic_sds_controller *the_controller; | ||
2101 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2102 | |||
2103 | the_controller = scic_sds_remote_device_get_controller(this_device); | ||
2104 | |||
2105 | if (this_device->has_ready_substate_machine) { | ||
2106 | sci_base_state_machine_stop(&this_device->ready_substate_machine); | ||
2107 | } else { | ||
2108 | scic_cb_remote_device_not_ready( | ||
2109 | the_controller, | ||
2110 | this_device, | ||
2111 | SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED | ||
2112 | ); | ||
2113 | } | ||
2114 | } | ||
2115 | |||
2116 | /** | ||
2117 | * | ||
2118 | * @object: This is the struct sci_base_object that is cast into a | ||
2119 | * struct scic_sds_remote_device. | ||
2120 | * | ||
2121 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_STOPPING it | ||
2122 | * sets the stopping state handlers and posts an RNC invalidate request to the | ||
2123 | * SCU hardware. none | ||
2124 | */ | ||
2125 | static void scic_sds_remote_device_stopping_state_enter( | ||
2126 | struct sci_base_object *object) | ||
2127 | { | ||
2128 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2129 | |||
2130 | SET_STATE_HANDLER( | ||
2131 | this_device, | ||
2132 | scic_sds_remote_device_state_handler_table, | ||
2133 | SCI_BASE_REMOTE_DEVICE_STATE_STOPPING | ||
2134 | ); | ||
2135 | } | ||
2136 | |||
2137 | /** | ||
2138 | * | ||
2139 | * @object: This is the struct sci_base_object that is cast into a | ||
2140 | * struct scic_sds_remote_device. | ||
2141 | * | ||
2142 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FAILED it sets | ||
2143 | * the stopping state handlers. none | ||
2144 | */ | ||
2145 | static void scic_sds_remote_device_failed_state_enter( | ||
2146 | struct sci_base_object *object) | ||
2147 | { | ||
2148 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2149 | |||
2150 | SET_STATE_HANDLER( | ||
2151 | this_device, | ||
2152 | scic_sds_remote_device_state_handler_table, | ||
2153 | SCI_BASE_REMOTE_DEVICE_STATE_FAILED | ||
2154 | ); | ||
2155 | } | ||
2156 | |||
2157 | /** | ||
2158 | * | ||
2159 | * @object: This is the struct sci_base_object that is cast into a | ||
2160 | * struct scic_sds_remote_device. | ||
2161 | * | ||
2162 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it | ||
2163 | * sets the resetting state handlers. none | ||
2164 | */ | ||
2165 | static void scic_sds_remote_device_resetting_state_enter( | ||
2166 | struct sci_base_object *object) | ||
2167 | { | ||
2168 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2169 | |||
2170 | SET_STATE_HANDLER( | ||
2171 | this_device, | ||
2172 | scic_sds_remote_device_state_handler_table, | ||
2173 | SCI_BASE_REMOTE_DEVICE_STATE_RESETTING | ||
2174 | ); | ||
2175 | |||
2176 | scic_sds_remote_node_context_suspend( | ||
2177 | this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); | ||
2178 | } | ||
2179 | |||
2180 | /** | ||
2181 | * | ||
2182 | * @object: This is the struct sci_base_object that is cast into a | ||
2183 | * struct scic_sds_remote_device. | ||
2184 | * | ||
2185 | * This is the exit method for the SCI_BASE_REMOTE_DEVICE_STATE_RESETTING it | ||
2186 | * does nothing. none | ||
2187 | */ | ||
2188 | static void scic_sds_remote_device_resetting_state_exit( | ||
2189 | struct sci_base_object *object) | ||
2190 | { | ||
2191 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2192 | |||
2193 | scic_sds_port_set_direct_attached_device_id( | ||
2194 | scic_sds_remote_device_get_port(this_device), | ||
2195 | this_device->rnc->remote_node_index | ||
2196 | ); | ||
2197 | |||
2198 | scic_sds_remote_node_context_resume(this_device->rnc, NULL, NULL); | ||
2199 | } | ||
2200 | |||
2201 | /** | ||
2202 | * | ||
2203 | * @object: This is the struct sci_base_object that is cast into a | ||
2204 | * struct scic_sds_remote_device. | ||
2205 | * | ||
2206 | * This is the enter method for the SCI_BASE_REMOTE_DEVICE_STATE_FINAL it sets | ||
2207 | * the final state handlers. none | ||
2208 | */ | ||
2209 | static void scic_sds_remote_device_final_state_enter( | ||
2210 | struct sci_base_object *object) | ||
2211 | { | ||
2212 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
2213 | |||
2214 | SET_STATE_HANDLER( | ||
2215 | this_device, | ||
2216 | scic_sds_remote_device_state_handler_table, | ||
2217 | SCI_BASE_REMOTE_DEVICE_STATE_FINAL | ||
2218 | ); | ||
2219 | } | ||
2220 | |||
2221 | /* --------------------------------------------------------------------------- */ | ||
2222 | |||
2223 | const struct sci_base_state scic_sds_remote_device_state_table[] = { | ||
2224 | [SCI_BASE_REMOTE_DEVICE_STATE_INITIAL] = { | ||
2225 | .enter_state = scic_sds_remote_device_initial_state_enter, | ||
2226 | }, | ||
2227 | [SCI_BASE_REMOTE_DEVICE_STATE_STOPPED] = { | ||
2228 | .enter_state = scic_sds_remote_device_stopped_state_enter, | ||
2229 | }, | ||
2230 | [SCI_BASE_REMOTE_DEVICE_STATE_STARTING] = { | ||
2231 | .enter_state = scic_sds_remote_device_starting_state_enter, | ||
2232 | .exit_state = scic_sds_remote_device_starting_state_exit | ||
2233 | }, | ||
2234 | [SCI_BASE_REMOTE_DEVICE_STATE_READY] = { | ||
2235 | .enter_state = scic_sds_remote_device_ready_state_enter, | ||
2236 | .exit_state = scic_sds_remote_device_ready_state_exit | ||
2237 | }, | ||
2238 | [SCI_BASE_REMOTE_DEVICE_STATE_STOPPING] = { | ||
2239 | .enter_state = scic_sds_remote_device_stopping_state_enter, | ||
2240 | }, | ||
2241 | [SCI_BASE_REMOTE_DEVICE_STATE_FAILED] = { | ||
2242 | .enter_state = scic_sds_remote_device_failed_state_enter, | ||
2243 | }, | ||
2244 | [SCI_BASE_REMOTE_DEVICE_STATE_RESETTING] = { | ||
2245 | .enter_state = scic_sds_remote_device_resetting_state_enter, | ||
2246 | .exit_state = scic_sds_remote_device_resetting_state_exit | ||
2247 | }, | ||
2248 | [SCI_BASE_REMOTE_DEVICE_STATE_FINAL] = { | ||
2249 | .enter_state = scic_sds_remote_device_final_state_enter, | ||
2250 | }, | ||
2251 | }; | ||
2252 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_remote_device.h b/drivers/scsi/isci/core/scic_sds_remote_device.h new file mode 100644 index 000000000000..44185a2738ec --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_device.h | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_REMOTE_DEVICE_H_ | ||
57 | #define _SCIC_SDS_REMOTE_DEVICE_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants, and prototypes for the | ||
61 | * struct scic_sds_remote_device object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "intel_sas.h" | ||
67 | #include "sci_base_remote_device.h" | ||
68 | #include "sci_base_request.h" | ||
69 | #include "scu_remote_node_context.h" | ||
70 | #include "scic_sds_remote_node_context.h" | ||
71 | |||
72 | struct scic_sds_controller; | ||
73 | struct scic_sds_port; | ||
74 | struct scic_sds_request; | ||
75 | struct scic_sds_remote_device_state_handler; | ||
76 | |||
77 | /** | ||
78 | * enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES - | ||
79 | * | ||
80 | * This is the enumeration of the ready substates for the | ||
81 | * struct scic_sds_remote_device. | ||
82 | */ | ||
83 | enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES { | ||
84 | /** | ||
85 | * This is the initial state for the remote device ready substate. | ||
86 | */ | ||
87 | SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL, | ||
88 | |||
89 | /** | ||
90 | * This is the ready operational substate for the remote device. This is the | ||
91 | * normal operational state for a remote device. | ||
92 | */ | ||
93 | SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL, | ||
94 | |||
95 | /** | ||
96 | * This is the suspended state for the remote device. This is the state that | ||
97 | * the device is placed in when a RNC suspend is received by the SCU hardware. | ||
98 | */ | ||
99 | SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED, | ||
100 | |||
101 | /** | ||
102 | * This is the final state that the device is placed in before a change to the | ||
103 | * base state machine. | ||
104 | */ | ||
105 | SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL, | ||
106 | |||
107 | SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES | ||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES - | ||
112 | * | ||
113 | * This is the enumeration for the struct scic_sds_remote_device ready substates for | ||
114 | * the STP remote device. | ||
115 | */ | ||
116 | enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES { | ||
117 | /** | ||
118 | * This is the idle substate for the stp remote device. When there are no | ||
119 | * active IO for the device it is is in this state. | ||
120 | */ | ||
121 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, | ||
122 | |||
123 | /** | ||
124 | * This is the command state for for the STP remote device. This state is | ||
125 | * entered when the device is processing a non-NCQ command. The device object | ||
126 | * will fail any new start IO requests until this command is complete. | ||
127 | */ | ||
128 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD, | ||
129 | |||
130 | /** | ||
131 | * This is the NCQ state for the STP remote device. This state is entered | ||
132 | * when the device is processing an NCQ reuqest. It will remain in this state | ||
133 | * so long as there is one or more NCQ requests being processed. | ||
134 | */ | ||
135 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ, | ||
136 | |||
137 | /** | ||
138 | * This is the NCQ error state for the STP remote device. This state is | ||
139 | * entered when an SDB error FIS is received by the device object while in the | ||
140 | * NCQ state. The device object will only accept a READ LOG command while in | ||
141 | * this state. | ||
142 | */ | ||
143 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR, | ||
144 | |||
145 | #if !defined(DISABLE_ATAPI) | ||
146 | /** | ||
147 | * This is the ATAPI error state for the STP ATAPI remote device. This state is | ||
148 | * entered when ATAPI device sends error status FIS without data while the device | ||
149 | * object is in CMD state. A suspension event is expected in this state. The device | ||
150 | * object will resume right away. | ||
151 | */ | ||
152 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR, | ||
153 | #endif | ||
154 | |||
155 | /** | ||
156 | * This is the READY substate indicates the device is waiting for the RESET task | ||
157 | * coming to be recovered from certain hardware specific error. | ||
158 | */ | ||
159 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET, | ||
160 | |||
161 | SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES | ||
162 | }; | ||
163 | |||
164 | |||
165 | /** | ||
166 | * enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES - | ||
167 | * | ||
168 | * This is the enumeration of the ready substates for the SMP REMOTE DEVICE. | ||
169 | */ | ||
170 | |||
171 | enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES { | ||
172 | /** | ||
173 | * This is the ready operational substate for the remote device. This is the | ||
174 | * normal operational state for a remote device. | ||
175 | */ | ||
176 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE, | ||
177 | |||
178 | /** | ||
179 | * This is the suspended state for the remote device. This is the state that | ||
180 | * the device is placed in when a RNC suspend is received by the SCU hardware. | ||
181 | */ | ||
182 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD, | ||
183 | |||
184 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES | ||
185 | }; | ||
186 | |||
187 | |||
188 | |||
189 | |||
190 | /** | ||
191 | * struct scic_sds_remote_device - This structure contains the data for an SCU | ||
192 | * implementation of the SCU Core device data. | ||
193 | * | ||
194 | * | ||
195 | */ | ||
196 | struct scic_sds_remote_device { | ||
197 | /** | ||
198 | * This field is the common base for all remote device objects. | ||
199 | */ | ||
200 | struct sci_base_remote_device parent; | ||
201 | |||
202 | /** | ||
203 | * This field is the programmed device port width. This value is written to | ||
204 | * the RCN data structure to tell the SCU how many open connections this | ||
205 | * device can have. | ||
206 | */ | ||
207 | u32 device_port_width; | ||
208 | |||
209 | /** | ||
210 | * This field is the programmed connection rate for this remote device. It is | ||
211 | * used to program the TC with the maximum allowed connection rate. | ||
212 | */ | ||
213 | enum sci_sas_link_rate connection_rate; | ||
214 | |||
215 | /** | ||
216 | * This field contains the allowed target protocols for this remote device. | ||
217 | */ | ||
218 | struct smp_discover_response_protocols target_protocols; | ||
219 | |||
220 | /** | ||
221 | * This field contains the device SAS address. | ||
222 | */ | ||
223 | struct sci_sas_address device_address; | ||
224 | |||
225 | /** | ||
226 | * This filed is assinged the value of true if the device is directly attached | ||
227 | * to the port. | ||
228 | */ | ||
229 | bool is_direct_attached; | ||
230 | |||
231 | #if !defined(DISABLE_ATAPI) | ||
232 | /** | ||
233 | * This filed is assinged the value of true if the device is an ATAPI device. | ||
234 | */ | ||
235 | bool is_atapi; | ||
236 | #endif | ||
237 | |||
238 | /** | ||
239 | * This filed contains a pointer back to the port to which this device is | ||
240 | * assigned. | ||
241 | */ | ||
242 | struct scic_sds_port *owning_port; | ||
243 | |||
244 | /** | ||
245 | * This field contains the SCU silicon remote node context specific | ||
246 | * information. | ||
247 | */ | ||
248 | struct scic_sds_remote_node_context *rnc; | ||
249 | |||
250 | /** | ||
251 | * This field contains the stated request count for the remote device. The | ||
252 | * device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all | ||
253 | * requests are complete and the rnc_posted value is false. | ||
254 | */ | ||
255 | u32 started_request_count; | ||
256 | |||
257 | /** | ||
258 | * This field contains a pointer to the working request object. It is only | ||
259 | * used only for SATA requests since the unsolicited frames we get from the | ||
260 | * hardware have no Tag value to look up the io request object. | ||
261 | */ | ||
262 | struct scic_sds_request *working_request; | ||
263 | |||
264 | /** | ||
265 | * This field contains the reason for the remote device going not_ready. It is | ||
266 | * assigned in the state handlers and used in the state transition. | ||
267 | */ | ||
268 | u32 not_ready_reason; | ||
269 | |||
270 | /** | ||
271 | * This field is true if this remote device has an initialzied ready substate | ||
272 | * machine. SSP devices do not have a ready substate machine and STP devices | ||
273 | * have a ready substate machine. | ||
274 | */ | ||
275 | bool has_ready_substate_machine; | ||
276 | |||
277 | /** | ||
278 | * This field contains the state machine for the ready substate machine for | ||
279 | * this struct scic_sds_remote_device object. | ||
280 | */ | ||
281 | struct sci_base_state_machine ready_substate_machine; | ||
282 | |||
283 | /** | ||
284 | * This field maintains the set of state handlers for the remote device | ||
285 | * object. These are changed each time the remote device enters a new state. | ||
286 | */ | ||
287 | struct scic_sds_remote_device_state_handler *state_handlers; | ||
288 | }; | ||
289 | |||
290 | |||
291 | typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_HANDLER_T)( | ||
292 | struct scic_sds_remote_device *this_device); | ||
293 | |||
294 | typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T)( | ||
295 | struct scic_sds_remote_device *this_device, | ||
296 | u32 suspend_type); | ||
297 | |||
298 | typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T)( | ||
299 | struct scic_sds_remote_device *this_device); | ||
300 | |||
301 | typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T)( | ||
302 | struct scic_sds_remote_device *this_device, | ||
303 | u32 frame_index); | ||
304 | |||
305 | typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T)( | ||
306 | struct scic_sds_remote_device *this_device, | ||
307 | u32 event_code); | ||
308 | |||
309 | typedef void (*SCIC_SDS_REMOTE_DEVICE_READY_NOT_READY_HANDLER_T)( | ||
310 | struct scic_sds_remote_device *this_device); | ||
311 | |||
312 | /** | ||
313 | * struct scic_sds_remote_device_state_handler - This structure conains the | ||
314 | * state handlers that are needed to process requests for the SCU remote | ||
315 | * device objects. | ||
316 | * | ||
317 | * | ||
318 | */ | ||
319 | struct scic_sds_remote_device_state_handler { | ||
320 | struct sci_base_remote_device_state_handler parent; | ||
321 | |||
322 | SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T suspend_handler; | ||
323 | SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T resume_handler; | ||
324 | |||
325 | SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T event_handler; | ||
326 | SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T frame_handler; | ||
327 | |||
328 | }; | ||
329 | |||
330 | |||
331 | extern const struct sci_base_state scic_sds_remote_device_state_table[]; | ||
332 | extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[]; | ||
333 | extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[]; | ||
334 | extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[]; | ||
335 | |||
336 | extern struct scic_sds_remote_device_state_handler | ||
337 | scic_sds_remote_device_state_handler_table[]; | ||
338 | extern struct scic_sds_remote_device_state_handler | ||
339 | scic_sds_ssp_remote_device_ready_substate_handler_table[]; | ||
340 | extern struct scic_sds_remote_device_state_handler | ||
341 | scic_sds_stp_remote_device_ready_substate_handler_table[]; | ||
342 | extern struct scic_sds_remote_device_state_handler | ||
343 | scic_sds_smp_remote_device_ready_substate_handler_table[]; | ||
344 | |||
345 | /** | ||
346 | * scic_sds_remote_device_increment_request_count() - | ||
347 | * | ||
348 | * This macro incrments the request count for this device | ||
349 | */ | ||
350 | #define scic_sds_remote_device_increment_request_count(this_device) \ | ||
351 | ((this_device)->started_request_count++) | ||
352 | |||
353 | /** | ||
354 | * scic_sds_remote_device_decrement_request_count() - | ||
355 | * | ||
356 | * This macro decrements the request count for this device. This count will | ||
357 | * never decrment past 0. | ||
358 | */ | ||
359 | #define scic_sds_remote_device_decrement_request_count(this_device) \ | ||
360 | ((this_device)->started_request_count > 0 ? \ | ||
361 | (this_device)->started_request_count-- : 0) | ||
362 | |||
363 | /** | ||
364 | * scic_sds_remote_device_get_request_count() - | ||
365 | * | ||
366 | * This is a helper macro to return the current device request count. | ||
367 | */ | ||
368 | #define scic_sds_remote_device_get_request_count(this_device) \ | ||
369 | ((this_device)->started_request_count) | ||
370 | |||
371 | /** | ||
372 | * scic_sds_remote_device_get_port() - | ||
373 | * | ||
374 | * This macro returns the owning port of this remote device obejct. | ||
375 | */ | ||
376 | #define scic_sds_remote_device_get_port(this_device) \ | ||
377 | ((this_device)->owning_port) | ||
378 | |||
379 | /** | ||
380 | * scic_sds_remote_device_get_controller() - | ||
381 | * | ||
382 | * This macro returns the controller object that contains this device object | ||
383 | */ | ||
384 | #define scic_sds_remote_device_get_controller(this_device) \ | ||
385 | scic_sds_port_get_controller(scic_sds_remote_device_get_port(this_device)) | ||
386 | |||
387 | /** | ||
388 | * scic_sds_remote_device_set_state_handlers() - | ||
389 | * | ||
390 | * This macro sets the remote device state handlers pointer and is set on entry | ||
391 | * to each device state. | ||
392 | */ | ||
393 | #define scic_sds_remote_device_set_state_handlers(this_device, handlers) \ | ||
394 | ((this_device)->state_handlers = (handlers)) | ||
395 | |||
396 | /** | ||
397 | * scic_sds_remote_device_get_base_state_machine() - | ||
398 | * | ||
399 | * This macro returns the base sate machine object for the remote device. | ||
400 | */ | ||
401 | #define scic_sds_remote_device_get_base_state_machine(this_device) \ | ||
402 | (&(this_device)->parent.state_machine) | ||
403 | |||
404 | /** | ||
405 | * scic_sds_remote_device_get_ready_substate_machine() - | ||
406 | * | ||
407 | * This macro returns the remote device ready substate machine | ||
408 | */ | ||
409 | #define scic_sds_remote_device_get_ready_substate_machine(this_device) \ | ||
410 | (&(this_device)->ready_substate_machine) | ||
411 | |||
412 | /** | ||
413 | * scic_sds_remote_device_get_port() - | ||
414 | * | ||
415 | * This macro returns the owning port of this device | ||
416 | */ | ||
417 | #define scic_sds_remote_device_get_port(this_device) \ | ||
418 | ((this_device)->owning_port) | ||
419 | |||
420 | /** | ||
421 | * scic_sds_remote_device_get_sequence() - | ||
422 | * | ||
423 | * This macro returns the remote device sequence value | ||
424 | */ | ||
425 | #define scic_sds_remote_device_get_sequence(this_device) \ | ||
426 | (\ | ||
427 | scic_sds_remote_device_get_controller(this_device)-> \ | ||
428 | remote_device_sequence[(this_device)->rnc->remote_node_index] \ | ||
429 | ) | ||
430 | |||
431 | /** | ||
432 | * scic_sds_remote_device_get_controller_peg() - | ||
433 | * | ||
434 | * This macro returns the controllers protocol engine group | ||
435 | */ | ||
436 | #define scic_sds_remote_device_get_controller_peg(this_device) \ | ||
437 | (\ | ||
438 | scic_sds_controller_get_protocol_engine_group(\ | ||
439 | scic_sds_port_get_controller(\ | ||
440 | scic_sds_remote_device_get_port(this_device) \ | ||
441 | ) \ | ||
442 | ) \ | ||
443 | ) | ||
444 | |||
445 | /** | ||
446 | * scic_sds_remote_device_get_port_index() - | ||
447 | * | ||
448 | * This macro returns the port index for the devices owning port | ||
449 | */ | ||
450 | #define scic_sds_remote_device_get_port_index(this_device) \ | ||
451 | (scic_sds_port_get_index(scic_sds_remote_device_get_port(this_device))) | ||
452 | |||
453 | /** | ||
454 | * scic_sds_remote_device_get_index() - | ||
455 | * | ||
456 | * This macro returns the remote node index for this device object | ||
457 | */ | ||
458 | #define scic_sds_remote_device_get_index(this_device) \ | ||
459 | ((this_device)->rnc->remote_node_index) | ||
460 | |||
461 | /** | ||
462 | * scic_sds_remote_device_build_command_context() - | ||
463 | * | ||
464 | * This macro builds a remote device context for the SCU post request operation | ||
465 | */ | ||
466 | #define scic_sds_remote_device_build_command_context(device, command) \ | ||
467 | ((command) \ | ||
468 | | (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \ | ||
469 | | (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \ | ||
470 | | (scic_sds_remote_device_get_index((device))) \ | ||
471 | ) | ||
472 | |||
473 | /** | ||
474 | * scic_sds_remote_device_set_working_request() - | ||
475 | * | ||
476 | * This macro makes the working request assingment for the remote device | ||
477 | * object. To clear the working request use this macro with a NULL request | ||
478 | * object. | ||
479 | */ | ||
480 | #define scic_sds_remote_device_set_working_request(device, request) \ | ||
481 | ((device)->working_request = (request)) | ||
482 | |||
483 | /* --------------------------------------------------------------------------- */ | ||
484 | |||
485 | |||
486 | |||
487 | enum sci_status scic_sds_remote_device_frame_handler( | ||
488 | struct scic_sds_remote_device *this_device, | ||
489 | u32 frame_index); | ||
490 | |||
491 | enum sci_status scic_sds_remote_device_event_handler( | ||
492 | struct scic_sds_remote_device *this_device, | ||
493 | u32 event_code); | ||
494 | |||
495 | enum sci_status scic_sds_remote_device_start_io( | ||
496 | struct scic_sds_controller *controller, | ||
497 | struct scic_sds_remote_device *this_device, | ||
498 | struct scic_sds_request *io_request); | ||
499 | |||
500 | enum sci_status scic_sds_remote_device_complete_io( | ||
501 | struct scic_sds_controller *controller, | ||
502 | struct scic_sds_remote_device *this_device, | ||
503 | struct scic_sds_request *io_request); | ||
504 | |||
505 | enum sci_status scic_sds_remote_device_resume( | ||
506 | struct scic_sds_remote_device *this_device); | ||
507 | |||
508 | enum sci_status scic_sds_remote_device_suspend( | ||
509 | struct scic_sds_remote_device *this_device, | ||
510 | u32 suspend_type); | ||
511 | |||
512 | enum sci_status scic_sds_remote_device_start_task( | ||
513 | struct scic_sds_controller *controller, | ||
514 | struct scic_sds_remote_device *this_device, | ||
515 | struct scic_sds_request *io_request); | ||
516 | |||
517 | void scic_sds_remote_device_post_request( | ||
518 | struct scic_sds_remote_device *this_device, | ||
519 | u32 request); | ||
520 | |||
521 | #if !defined(DISABLE_ATAPI) | ||
522 | bool scic_sds_remote_device_is_atapi( | ||
523 | struct scic_sds_remote_device *this_device); | ||
524 | #else /* !defined(DISABLE_ATAPI) */ | ||
525 | #define scic_sds_remote_device_is_atapi(this_device) false | ||
526 | #endif /* !defined(DISABLE_ATAPI) */ | ||
527 | |||
528 | /* --------------------------------------------------------------------------- */ | ||
529 | |||
530 | /* --------------------------------------------------------------------------- */ | ||
531 | |||
532 | void scic_sds_remote_device_start_request( | ||
533 | struct scic_sds_remote_device *this_device, | ||
534 | struct scic_sds_request *the_request, | ||
535 | enum sci_status status); | ||
536 | |||
537 | void scic_sds_remote_device_continue_request( | ||
538 | struct scic_sds_remote_device *this_device); | ||
539 | |||
540 | enum sci_status scic_sds_remote_device_default_start_handler( | ||
541 | struct sci_base_remote_device *this_device); | ||
542 | |||
543 | |||
544 | enum sci_status scic_sds_remote_device_default_fail_handler( | ||
545 | struct sci_base_remote_device *this_device); | ||
546 | |||
547 | enum sci_status scic_sds_remote_device_default_destruct_handler( | ||
548 | struct sci_base_remote_device *this_device); | ||
549 | |||
550 | enum sci_status scic_sds_remote_device_default_reset_handler( | ||
551 | struct sci_base_remote_device *device); | ||
552 | |||
553 | enum sci_status scic_sds_remote_device_default_reset_complete_handler( | ||
554 | struct sci_base_remote_device *device); | ||
555 | |||
556 | enum sci_status scic_sds_remote_device_default_start_request_handler( | ||
557 | struct sci_base_remote_device *device, | ||
558 | struct sci_base_request *request); | ||
559 | |||
560 | enum sci_status scic_sds_remote_device_default_complete_request_handler( | ||
561 | struct sci_base_remote_device *device, | ||
562 | struct sci_base_request *request); | ||
563 | |||
564 | enum sci_status scic_sds_remote_device_default_continue_request_handler( | ||
565 | struct sci_base_remote_device *device, | ||
566 | struct sci_base_request *request); | ||
567 | |||
568 | enum sci_status scic_sds_remote_device_default_suspend_handler( | ||
569 | struct scic_sds_remote_device *this_device, | ||
570 | u32 suspend_type); | ||
571 | |||
572 | enum sci_status scic_sds_remote_device_default_resume_handler( | ||
573 | struct scic_sds_remote_device *this_device); | ||
574 | |||
575 | |||
576 | enum sci_status scic_sds_remote_device_default_frame_handler( | ||
577 | struct scic_sds_remote_device *this_device, | ||
578 | u32 frame_index); | ||
579 | |||
580 | /* --------------------------------------------------------------------------- */ | ||
581 | |||
582 | enum sci_status scic_sds_remote_device_ready_state_stop_handler( | ||
583 | struct sci_base_remote_device *device); | ||
584 | |||
585 | enum sci_status scic_sds_remote_device_ready_state_reset_handler( | ||
586 | struct sci_base_remote_device *device); | ||
587 | |||
588 | enum sci_status scic_sds_remote_device_general_frame_handler( | ||
589 | struct scic_sds_remote_device *this_device, | ||
590 | u32 frame_index); | ||
591 | |||
592 | enum sci_status scic_sds_remote_device_general_event_handler( | ||
593 | struct scic_sds_remote_device *this_device, | ||
594 | u32 event_code); | ||
595 | |||
596 | enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler( | ||
597 | struct scic_sds_remote_device *this_device); | ||
598 | |||
599 | /* --------------------------------------------------------------------------- */ | ||
600 | |||
601 | |||
602 | #endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.c b/drivers/scsi/isci/core/scic_sds_remote_node_context.c new file mode 100644 index 000000000000..79fe9a8cd1ed --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.c | |||
@@ -0,0 +1,1244 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "sci_base_state_machine.h" | ||
57 | #include "scic_remote_device.h" | ||
58 | #include "scic_sds_controller.h" | ||
59 | #include "scic_sds_port.h" | ||
60 | #include "scic_sds_remote_device.h" | ||
61 | #include "scic_sds_remote_node_context.h" | ||
62 | #include "sci_environment.h" | ||
63 | #include "sci_util.h" | ||
64 | #include "scu_event_codes.h" | ||
65 | #include "scu_task_context.h" | ||
66 | |||
67 | void scic_sds_remote_node_context_construct( | ||
68 | struct scic_sds_remote_device *device, | ||
69 | struct scic_sds_remote_node_context *rnc, | ||
70 | u16 remote_node_index) | ||
71 | { | ||
72 | memset(rnc, 0, sizeof(struct scic_sds_remote_node_context)); | ||
73 | |||
74 | rnc->remote_node_index = remote_node_index; | ||
75 | rnc->device = device; | ||
76 | rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; | ||
77 | |||
78 | sci_base_state_machine_construct( | ||
79 | &rnc->state_machine, | ||
80 | &rnc->parent, | ||
81 | scic_sds_remote_node_context_state_table, | ||
82 | SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE | ||
83 | ); | ||
84 | |||
85 | sci_base_state_machine_start(&rnc->state_machine); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * | ||
90 | * @this_rnc: The RNC for which the is posted request is being made. | ||
91 | * | ||
92 | * This method will return true if the RNC is not in the initial state. In all | ||
93 | * other states the RNC is considered active and this will return true. The | ||
94 | * destroy request of the state machine drives the RNC back to the initial | ||
95 | * state. If the state machine changes then this routine will also have to be | ||
96 | * changed. bool true if the state machine is not in the initial state false if | ||
97 | * the state machine is in the initial state | ||
98 | */ | ||
99 | |||
100 | /** | ||
101 | * | ||
102 | * @this_rnc: The state of the remote node context object to check. | ||
103 | * | ||
104 | * This method will return true if the remote node context is in a READY state | ||
105 | * otherwise it will return false bool true if the remote node context is in | ||
106 | * the ready state. false if the remote node context is not in the ready state. | ||
107 | */ | ||
108 | bool scic_sds_remote_node_context_is_ready( | ||
109 | struct scic_sds_remote_node_context *this_rnc) | ||
110 | { | ||
111 | u32 current_state = sci_base_state_machine_get_state(&this_rnc->state_machine); | ||
112 | |||
113 | if (current_state == SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE) { | ||
114 | return true; | ||
115 | } | ||
116 | |||
117 | return false; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * | ||
122 | * @this_device: The remote device to use to construct the RNC buffer. | ||
123 | * @rnc: The buffer into which the remote device data will be copied. | ||
124 | * | ||
125 | * This method will construct the RNC buffer for this remote device object. none | ||
126 | */ | ||
127 | void scic_sds_remote_node_context_construct_buffer( | ||
128 | struct scic_sds_remote_node_context *this_rnc) | ||
129 | { | ||
130 | union scu_remote_node_context *rnc; | ||
131 | struct scic_sds_controller *the_controller; | ||
132 | |||
133 | the_controller = scic_sds_remote_device_get_controller(this_rnc->device); | ||
134 | |||
135 | rnc = scic_sds_controller_get_remote_node_context_buffer( | ||
136 | the_controller, this_rnc->remote_node_index); | ||
137 | |||
138 | memset( | ||
139 | rnc, | ||
140 | 0x00, | ||
141 | sizeof(union scu_remote_node_context) | ||
142 | * scic_sds_remote_device_node_count(this_rnc->device) | ||
143 | ); | ||
144 | |||
145 | rnc->ssp.remote_node_index = this_rnc->remote_node_index; | ||
146 | rnc->ssp.remote_node_port_width = this_rnc->device->device_port_width; | ||
147 | rnc->ssp.logical_port_index = | ||
148 | scic_sds_remote_device_get_port_index(this_rnc->device); | ||
149 | |||
150 | rnc->ssp.remote_sas_address_hi = SCIC_SWAP_DWORD(this_rnc->device->device_address.high); | ||
151 | rnc->ssp.remote_sas_address_lo = SCIC_SWAP_DWORD(this_rnc->device->device_address.low); | ||
152 | |||
153 | rnc->ssp.nexus_loss_timer_enable = true; | ||
154 | rnc->ssp.check_bit = false; | ||
155 | rnc->ssp.is_valid = false; | ||
156 | rnc->ssp.is_remote_node_context = true; | ||
157 | rnc->ssp.function_number = 0; | ||
158 | |||
159 | rnc->ssp.arbitration_wait_time = 0; | ||
160 | |||
161 | |||
162 | if ( | ||
163 | this_rnc->device->target_protocols.u.bits.attached_sata_device | ||
164 | || this_rnc->device->target_protocols.u.bits.attached_stp_target | ||
165 | ) { | ||
166 | rnc->ssp.connection_occupancy_timeout = | ||
167 | the_controller->user_parameters.sds1.stp_max_occupancy_timeout; | ||
168 | rnc->ssp.connection_inactivity_timeout = | ||
169 | the_controller->user_parameters.sds1.stp_inactivity_timeout; | ||
170 | } else { | ||
171 | rnc->ssp.connection_occupancy_timeout = | ||
172 | the_controller->user_parameters.sds1.ssp_max_occupancy_timeout; | ||
173 | rnc->ssp.connection_inactivity_timeout = | ||
174 | the_controller->user_parameters.sds1.ssp_inactivity_timeout; | ||
175 | } | ||
176 | |||
177 | rnc->ssp.initial_arbitration_wait_time = 0; | ||
178 | |||
179 | /* Open Address Frame Parameters */ | ||
180 | rnc->ssp.oaf_connection_rate = this_rnc->device->connection_rate; | ||
181 | rnc->ssp.oaf_features = 0; | ||
182 | rnc->ssp.oaf_source_zone_group = 0; | ||
183 | rnc->ssp.oaf_more_compatibility_features = 0; | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * | ||
188 | * @this_rnc: | ||
189 | * @the_callback: | ||
190 | * @callback_parameter: | ||
191 | * | ||
192 | * This method will setup the remote node context object so it will transition | ||
193 | * to its ready state. If the remote node context is already setup to | ||
194 | * transition to its final state then this function does nothing. none | ||
195 | */ | ||
196 | static void scic_sds_remote_node_context_setup_to_resume( | ||
197 | struct scic_sds_remote_node_context *this_rnc, | ||
198 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
199 | void *callback_parameter) | ||
200 | { | ||
201 | if (this_rnc->destination_state != SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { | ||
202 | this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY; | ||
203 | this_rnc->user_callback = the_callback; | ||
204 | this_rnc->user_cookie = callback_parameter; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * | ||
210 | * @this_rnc: | ||
211 | * @the_callback: | ||
212 | * @callback_parameter: | ||
213 | * | ||
214 | * This method will setup the remote node context object so it will transistion | ||
215 | * to its final state. none | ||
216 | */ | ||
217 | static void scic_sds_remote_node_context_setup_to_destory( | ||
218 | struct scic_sds_remote_node_context *this_rnc, | ||
219 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
220 | void *callback_parameter) | ||
221 | { | ||
222 | this_rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL; | ||
223 | this_rnc->user_callback = the_callback; | ||
224 | this_rnc->user_cookie = callback_parameter; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * | ||
229 | * @this_rnc: | ||
230 | * @the_callback: | ||
231 | * | ||
232 | * This method will continue to resume a remote node context. This is used in | ||
233 | * the states where a resume is requested while a resume is in progress. | ||
234 | */ | ||
235 | static enum sci_status scic_sds_remote_node_context_continue_to_resume_handler( | ||
236 | struct scic_sds_remote_node_context *this_rnc, | ||
237 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
238 | void *callback_parameter) | ||
239 | { | ||
240 | if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { | ||
241 | this_rnc->user_callback = the_callback; | ||
242 | this_rnc->user_cookie = callback_parameter; | ||
243 | |||
244 | return SCI_SUCCESS; | ||
245 | } | ||
246 | |||
247 | return SCI_FAILURE_INVALID_STATE; | ||
248 | } | ||
249 | |||
250 | /* --------------------------------------------------------------------------- */ | ||
251 | |||
252 | static enum sci_status scic_sds_remote_node_context_default_destruct_handler( | ||
253 | struct scic_sds_remote_node_context *this_rnc, | ||
254 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
255 | void *callback_parameter) | ||
256 | { | ||
257 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
258 | "%s: SCIC Remote Node Context 0x%p requested to stop while " | ||
259 | "in unexpected state %d\n", | ||
260 | __func__, | ||
261 | this_rnc, | ||
262 | sci_base_state_machine_get_state(&this_rnc->state_machine)); | ||
263 | |||
264 | /* | ||
265 | * We have decided that the destruct request on the remote node context can not fail | ||
266 | * since it is either in the initial/destroyed state or is can be destroyed. */ | ||
267 | return SCI_SUCCESS; | ||
268 | } | ||
269 | |||
270 | static enum sci_status scic_sds_remote_node_context_default_suspend_handler( | ||
271 | struct scic_sds_remote_node_context *this_rnc, | ||
272 | u32 suspend_type, | ||
273 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
274 | void *callback_parameter) | ||
275 | { | ||
276 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
277 | "%s: SCIC Remote Node Context 0x%p requested to suspend " | ||
278 | "while in wrong state %d\n", | ||
279 | __func__, | ||
280 | this_rnc, | ||
281 | sci_base_state_machine_get_state(&this_rnc->state_machine)); | ||
282 | |||
283 | return SCI_FAILURE_INVALID_STATE; | ||
284 | } | ||
285 | |||
286 | static enum sci_status scic_sds_remote_node_context_default_resume_handler( | ||
287 | struct scic_sds_remote_node_context *this_rnc, | ||
288 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
289 | void *callback_parameter) | ||
290 | { | ||
291 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
292 | "%s: SCIC Remote Node Context 0x%p requested to resume " | ||
293 | "while in wrong state %d\n", | ||
294 | __func__, | ||
295 | this_rnc, | ||
296 | sci_base_state_machine_get_state(&this_rnc->state_machine)); | ||
297 | |||
298 | return SCI_FAILURE_INVALID_STATE; | ||
299 | } | ||
300 | |||
301 | static enum sci_status scic_sds_remote_node_context_default_start_io_handler( | ||
302 | struct scic_sds_remote_node_context *this_rnc, | ||
303 | struct scic_sds_request *the_request) | ||
304 | { | ||
305 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
306 | "%s: SCIC Remote Node Context 0x%p requested to start io " | ||
307 | "0x%p while in wrong state %d\n", | ||
308 | __func__, | ||
309 | this_rnc, | ||
310 | the_request, | ||
311 | sci_base_state_machine_get_state(&this_rnc->state_machine)); | ||
312 | |||
313 | return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; | ||
314 | } | ||
315 | |||
316 | static enum sci_status scic_sds_remote_node_context_default_start_task_handler( | ||
317 | struct scic_sds_remote_node_context *this_rnc, | ||
318 | struct scic_sds_request *the_request) | ||
319 | { | ||
320 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
321 | "%s: SCIC Remote Node Context 0x%p requested to start " | ||
322 | "task 0x%p while in wrong state %d\n", | ||
323 | __func__, | ||
324 | this_rnc, | ||
325 | the_request, | ||
326 | sci_base_state_machine_get_state(&this_rnc->state_machine)); | ||
327 | |||
328 | return SCI_FAILURE; | ||
329 | } | ||
330 | |||
331 | static enum sci_status scic_sds_remote_node_context_default_event_handler( | ||
332 | struct scic_sds_remote_node_context *this_rnc, | ||
333 | u32 event_code) | ||
334 | { | ||
335 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
336 | "%s: SCIC Remote Node Context 0x%p requested to process " | ||
337 | "event 0x%x while in wrong state %d\n", | ||
338 | __func__, | ||
339 | this_rnc, | ||
340 | event_code, | ||
341 | sci_base_state_machine_get_state(&this_rnc->state_machine)); | ||
342 | |||
343 | return SCI_FAILURE_INVALID_STATE; | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * | ||
348 | * @this_rnc: The rnc for which the task request is targeted. | ||
349 | * @the_request: The request which is going to be started. | ||
350 | * | ||
351 | * This method determines if the task request can be started by the SCU | ||
352 | * hardware. When the RNC is in the ready state any task can be started. | ||
353 | * enum sci_status SCI_SUCCESS | ||
354 | */ | ||
355 | static enum sci_status scic_sds_remote_node_context_success_start_task_handler( | ||
356 | struct scic_sds_remote_node_context *this_rnc, | ||
357 | struct scic_sds_request *the_request) | ||
358 | { | ||
359 | return SCI_SUCCESS; | ||
360 | } | ||
361 | |||
362 | /** | ||
363 | * | ||
364 | * @this_rnc: | ||
365 | * @the_callback: | ||
366 | * @callback_parameter: | ||
367 | * | ||
368 | * This method handles destruct calls from the various state handlers. The | ||
369 | * remote node context can be requested to destroy from any state. If there was | ||
370 | * a user callback it is always replaced with the request to destroy user | ||
371 | * callback. enum sci_status | ||
372 | */ | ||
373 | static enum sci_status scic_sds_remote_node_context_general_destruct_handler( | ||
374 | struct scic_sds_remote_node_context *this_rnc, | ||
375 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
376 | void *callback_parameter) | ||
377 | { | ||
378 | scic_sds_remote_node_context_setup_to_destory( | ||
379 | this_rnc, the_callback, callback_parameter | ||
380 | ); | ||
381 | |||
382 | sci_base_state_machine_change_state( | ||
383 | &this_rnc->state_machine, | ||
384 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE | ||
385 | ); | ||
386 | |||
387 | return SCI_SUCCESS; | ||
388 | } | ||
389 | |||
390 | /* --------------------------------------------------------------------------- */ | ||
391 | |||
392 | static enum sci_status scic_sds_remote_node_context_initial_state_resume_handler( | ||
393 | struct scic_sds_remote_node_context *this_rnc, | ||
394 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
395 | void *callback_parameter) | ||
396 | { | ||
397 | if (this_rnc->remote_node_index != SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { | ||
398 | scic_sds_remote_node_context_setup_to_resume( | ||
399 | this_rnc, the_callback, callback_parameter | ||
400 | ); | ||
401 | |||
402 | scic_sds_remote_node_context_construct_buffer(this_rnc); | ||
403 | |||
404 | sci_base_state_machine_change_state( | ||
405 | &this_rnc->state_machine, | ||
406 | SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE | ||
407 | ); | ||
408 | |||
409 | return SCI_SUCCESS; | ||
410 | } | ||
411 | |||
412 | return SCI_FAILURE_INVALID_STATE; | ||
413 | } | ||
414 | |||
415 | /* --------------------------------------------------------------------------- */ | ||
416 | |||
417 | static enum sci_status scic_sds_remote_node_context_posting_state_event_handler( | ||
418 | struct scic_sds_remote_node_context *this_rnc, | ||
419 | u32 event_code) | ||
420 | { | ||
421 | enum sci_status status; | ||
422 | |||
423 | switch (scu_get_event_code(event_code)) { | ||
424 | case SCU_EVENT_POST_RNC_COMPLETE: | ||
425 | status = SCI_SUCCESS; | ||
426 | |||
427 | sci_base_state_machine_change_state( | ||
428 | &this_rnc->state_machine, | ||
429 | SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE | ||
430 | ); | ||
431 | break; | ||
432 | |||
433 | default: | ||
434 | status = SCI_FAILURE; | ||
435 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
436 | "%s: SCIC Remote Node Context 0x%p requested to " | ||
437 | "process unexpected event 0x%x while in posting " | ||
438 | "state\n", | ||
439 | __func__, | ||
440 | this_rnc, | ||
441 | event_code); | ||
442 | break; | ||
443 | } | ||
444 | |||
445 | return status; | ||
446 | } | ||
447 | |||
448 | /* --------------------------------------------------------------------------- */ | ||
449 | |||
450 | static enum sci_status scic_sds_remote_node_context_invalidating_state_destruct_handler( | ||
451 | struct scic_sds_remote_node_context *this_rnc, | ||
452 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
453 | void *callback_parameter) | ||
454 | { | ||
455 | scic_sds_remote_node_context_setup_to_destory( | ||
456 | this_rnc, the_callback, callback_parameter | ||
457 | ); | ||
458 | |||
459 | return SCI_SUCCESS; | ||
460 | } | ||
461 | |||
462 | static enum sci_status scic_sds_remote_node_context_invalidating_state_event_handler( | ||
463 | struct scic_sds_remote_node_context *this_rnc, | ||
464 | u32 event_code) | ||
465 | { | ||
466 | enum sci_status status; | ||
467 | |||
468 | if (scu_get_event_code(event_code) == SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE) { | ||
469 | status = SCI_SUCCESS; | ||
470 | |||
471 | if (this_rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL) { | ||
472 | sci_base_state_machine_change_state( | ||
473 | &this_rnc->state_machine, | ||
474 | SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE | ||
475 | ); | ||
476 | } else { | ||
477 | sci_base_state_machine_change_state( | ||
478 | &this_rnc->state_machine, | ||
479 | SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE | ||
480 | ); | ||
481 | } | ||
482 | } else { | ||
483 | switch (scu_get_event_type(event_code)) { | ||
484 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX: | ||
485 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: | ||
486 | /* | ||
487 | * We really dont care if the hardware is going to suspend | ||
488 | * the device since it's being invalidated anyway */ | ||
489 | dev_dbg(scirdev_to_dev(this_rnc->device), | ||
490 | "%s: SCIC Remote Node Context 0x%p was " | ||
491 | "suspeneded by hardware while being " | ||
492 | "invalidated.\n", | ||
493 | __func__, | ||
494 | this_rnc); | ||
495 | status = SCI_SUCCESS; | ||
496 | break; | ||
497 | |||
498 | default: | ||
499 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
500 | "%s: SCIC Remote Node Context 0x%p " | ||
501 | "requested to process event 0x%x while " | ||
502 | "in state %d.\n", | ||
503 | __func__, | ||
504 | this_rnc, | ||
505 | event_code, | ||
506 | sci_base_state_machine_get_state( | ||
507 | &this_rnc->state_machine)); | ||
508 | status = SCI_FAILURE; | ||
509 | break; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | return status; | ||
514 | } | ||
515 | |||
516 | /* --------------------------------------------------------------------------- */ | ||
517 | |||
518 | |||
519 | static enum sci_status scic_sds_remote_node_context_resuming_state_event_handler( | ||
520 | struct scic_sds_remote_node_context *this_rnc, | ||
521 | u32 event_code) | ||
522 | { | ||
523 | enum sci_status status; | ||
524 | |||
525 | if (scu_get_event_code(event_code) == SCU_EVENT_POST_RCN_RELEASE) { | ||
526 | status = SCI_SUCCESS; | ||
527 | |||
528 | sci_base_state_machine_change_state( | ||
529 | &this_rnc->state_machine, | ||
530 | SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE | ||
531 | ); | ||
532 | } else { | ||
533 | switch (scu_get_event_type(event_code)) { | ||
534 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX: | ||
535 | case SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX: | ||
536 | /* | ||
537 | * We really dont care if the hardware is going to suspend | ||
538 | * the device since it's being resumed anyway */ | ||
539 | dev_dbg(scirdev_to_dev(this_rnc->device), | ||
540 | "%s: SCIC Remote Node Context 0x%p was " | ||
541 | "suspeneded by hardware while being resumed.\n", | ||
542 | __func__, | ||
543 | this_rnc); | ||
544 | status = SCI_SUCCESS; | ||
545 | break; | ||
546 | |||
547 | default: | ||
548 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
549 | "%s: SCIC Remote Node Context 0x%p requested " | ||
550 | "to process event 0x%x while in state %d.\n", | ||
551 | __func__, | ||
552 | this_rnc, | ||
553 | event_code, | ||
554 | sci_base_state_machine_get_state( | ||
555 | &this_rnc->state_machine)); | ||
556 | status = SCI_FAILURE; | ||
557 | break; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | return status; | ||
562 | } | ||
563 | |||
564 | /* --------------------------------------------------------------------------- */ | ||
565 | |||
566 | /** | ||
567 | * | ||
568 | * @this_rnc: The remote node context object being suspended. | ||
569 | * @the_callback: The callback when the suspension is complete. | ||
570 | * @callback_parameter: The parameter that is to be passed into the callback. | ||
571 | * | ||
572 | * This method will handle the suspend requests from the ready state. | ||
573 | * SCI_SUCCESS | ||
574 | */ | ||
575 | static enum sci_status scic_sds_remote_node_context_ready_state_suspend_handler( | ||
576 | struct scic_sds_remote_node_context *this_rnc, | ||
577 | u32 suspend_type, | ||
578 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
579 | void *callback_parameter) | ||
580 | { | ||
581 | this_rnc->user_callback = the_callback; | ||
582 | this_rnc->user_cookie = callback_parameter; | ||
583 | this_rnc->suspension_code = suspend_type; | ||
584 | |||
585 | if (suspend_type == SCI_SOFTWARE_SUSPENSION) { | ||
586 | scic_sds_remote_device_post_request( | ||
587 | this_rnc->device, | ||
588 | SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX | ||
589 | ); | ||
590 | } | ||
591 | |||
592 | sci_base_state_machine_change_state( | ||
593 | &this_rnc->state_machine, | ||
594 | SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE | ||
595 | ); | ||
596 | |||
597 | return SCI_SUCCESS; | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * | ||
602 | * @this_rnc: The rnc for which the io request is targeted. | ||
603 | * @the_request: The request which is going to be started. | ||
604 | * | ||
605 | * This method determines if the io request can be started by the SCU hardware. | ||
606 | * When the RNC is in the ready state any io request can be started. enum sci_status | ||
607 | * SCI_SUCCESS | ||
608 | */ | ||
609 | static enum sci_status scic_sds_remote_node_context_ready_state_start_io_handler( | ||
610 | struct scic_sds_remote_node_context *this_rnc, | ||
611 | struct scic_sds_request *the_request) | ||
612 | { | ||
613 | return SCI_SUCCESS; | ||
614 | } | ||
615 | |||
616 | |||
617 | static enum sci_status scic_sds_remote_node_context_ready_state_event_handler( | ||
618 | struct scic_sds_remote_node_context *this_rnc, | ||
619 | u32 event_code) | ||
620 | { | ||
621 | enum sci_status status; | ||
622 | |||
623 | switch (scu_get_event_type(event_code)) { | ||
624 | case SCU_EVENT_TL_RNC_SUSPEND_TX: | ||
625 | sci_base_state_machine_change_state( | ||
626 | &this_rnc->state_machine, | ||
627 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE | ||
628 | ); | ||
629 | |||
630 | this_rnc->suspension_code = scu_get_event_specifier(event_code); | ||
631 | status = SCI_SUCCESS; | ||
632 | break; | ||
633 | |||
634 | case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: | ||
635 | sci_base_state_machine_change_state( | ||
636 | &this_rnc->state_machine, | ||
637 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE | ||
638 | ); | ||
639 | |||
640 | this_rnc->suspension_code = scu_get_event_specifier(event_code); | ||
641 | status = SCI_SUCCESS; | ||
642 | break; | ||
643 | |||
644 | default: | ||
645 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
646 | "%s: SCIC Remote Node Context 0x%p requested to " | ||
647 | "process event 0x%x while in state %d.\n", | ||
648 | __func__, | ||
649 | this_rnc, | ||
650 | event_code, | ||
651 | sci_base_state_machine_get_state( | ||
652 | &this_rnc->state_machine)); | ||
653 | |||
654 | status = SCI_FAILURE; | ||
655 | break; | ||
656 | } | ||
657 | |||
658 | return status; | ||
659 | } | ||
660 | |||
661 | /* --------------------------------------------------------------------------- */ | ||
662 | |||
663 | static enum sci_status scic_sds_remote_node_context_tx_suspended_state_resume_handler( | ||
664 | struct scic_sds_remote_node_context *this_rnc, | ||
665 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
666 | void *callback_parameter) | ||
667 | { | ||
668 | enum sci_status status; | ||
669 | struct smp_discover_response_protocols protocols; | ||
670 | |||
671 | scic_sds_remote_node_context_setup_to_resume( | ||
672 | this_rnc, the_callback, callback_parameter | ||
673 | ); | ||
674 | |||
675 | /* TODO: consider adding a resume action of NONE, INVALIDATE, WRITE_TLCR */ | ||
676 | |||
677 | scic_remote_device_get_protocols(this_rnc->device, &protocols); | ||
678 | |||
679 | if ( | ||
680 | (protocols.u.bits.attached_ssp_target == 1) | ||
681 | || (protocols.u.bits.attached_smp_target == 1) | ||
682 | ) { | ||
683 | sci_base_state_machine_change_state( | ||
684 | &this_rnc->state_machine, | ||
685 | SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE | ||
686 | ); | ||
687 | |||
688 | status = SCI_SUCCESS; | ||
689 | } else if (protocols.u.bits.attached_stp_target == 1) { | ||
690 | if (this_rnc->device->is_direct_attached) { | ||
691 | /* @todo Fix this since I am being silly in writing to the STPTLDARNI register. */ | ||
692 | scic_sds_port_set_direct_attached_device_id( | ||
693 | this_rnc->device->owning_port, | ||
694 | this_rnc->remote_node_index | ||
695 | ); | ||
696 | |||
697 | sci_base_state_machine_change_state( | ||
698 | &this_rnc->state_machine, | ||
699 | SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE | ||
700 | ); | ||
701 | } else { | ||
702 | sci_base_state_machine_change_state( | ||
703 | &this_rnc->state_machine, | ||
704 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE | ||
705 | ); | ||
706 | } | ||
707 | |||
708 | status = SCI_SUCCESS; | ||
709 | } else { | ||
710 | status = SCI_FAILURE; | ||
711 | } | ||
712 | |||
713 | return status; | ||
714 | } | ||
715 | |||
716 | /** | ||
717 | * | ||
718 | * @this_rnc: The remote node context which is to receive the task request. | ||
719 | * @the_request: The task request to be transmitted to to the remote target | ||
720 | * device. | ||
721 | * | ||
722 | * This method will report a success or failure attempt to start a new task | ||
723 | * request to the hardware. Since all task requests are sent on the high | ||
724 | * priority queue they can be sent when the RCN is in a TX suspend state. | ||
725 | * enum sci_status SCI_SUCCESS | ||
726 | */ | ||
727 | static enum sci_status scic_sds_remote_node_context_suspended_start_task_handler( | ||
728 | struct scic_sds_remote_node_context *this_rnc, | ||
729 | struct scic_sds_request *the_request) | ||
730 | { | ||
731 | scic_sds_remote_node_context_resume(this_rnc, NULL, NULL); | ||
732 | |||
733 | return SCI_SUCCESS; | ||
734 | } | ||
735 | |||
736 | /* --------------------------------------------------------------------------- */ | ||
737 | |||
738 | static enum sci_status scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler( | ||
739 | struct scic_sds_remote_node_context *this_rnc, | ||
740 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
741 | void *callback_parameter) | ||
742 | { | ||
743 | scic_sds_remote_node_context_setup_to_resume( | ||
744 | this_rnc, the_callback, callback_parameter | ||
745 | ); | ||
746 | |||
747 | sci_base_state_machine_change_state( | ||
748 | &this_rnc->state_machine, | ||
749 | SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE | ||
750 | ); | ||
751 | |||
752 | return SCI_FAILURE_INVALID_STATE; | ||
753 | } | ||
754 | |||
755 | /* --------------------------------------------------------------------------- */ | ||
756 | |||
757 | /** | ||
758 | * | ||
759 | * | ||
760 | * | ||
761 | */ | ||
762 | static enum sci_status scic_sds_remote_node_context_await_suspension_state_resume_handler( | ||
763 | struct scic_sds_remote_node_context *this_rnc, | ||
764 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
765 | void *callback_parameter) | ||
766 | { | ||
767 | scic_sds_remote_node_context_setup_to_resume( | ||
768 | this_rnc, the_callback, callback_parameter | ||
769 | ); | ||
770 | |||
771 | return SCI_SUCCESS; | ||
772 | } | ||
773 | |||
774 | /** | ||
775 | * | ||
776 | * @this_rnc: The remote node context which is to receive the task request. | ||
777 | * @the_request: The task request to be transmitted to to the remote target | ||
778 | * device. | ||
779 | * | ||
780 | * This method will report a success or failure attempt to start a new task | ||
781 | * request to the hardware. Since all task requests are sent on the high | ||
782 | * priority queue they can be sent when the RCN is in a TX suspend state. | ||
783 | * enum sci_status SCI_SUCCESS | ||
784 | */ | ||
785 | static enum sci_status scic_sds_remote_node_context_await_suspension_state_start_task_handler( | ||
786 | struct scic_sds_remote_node_context *this_rnc, | ||
787 | struct scic_sds_request *the_request) | ||
788 | { | ||
789 | return SCI_SUCCESS; | ||
790 | } | ||
791 | |||
792 | static enum sci_status scic_sds_remote_node_context_await_suspension_state_event_handler( | ||
793 | struct scic_sds_remote_node_context *this_rnc, | ||
794 | u32 event_code) | ||
795 | { | ||
796 | enum sci_status status; | ||
797 | |||
798 | switch (scu_get_event_type(event_code)) { | ||
799 | case SCU_EVENT_TL_RNC_SUSPEND_TX: | ||
800 | sci_base_state_machine_change_state( | ||
801 | &this_rnc->state_machine, | ||
802 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE | ||
803 | ); | ||
804 | |||
805 | this_rnc->suspension_code = scu_get_event_specifier(event_code); | ||
806 | status = SCI_SUCCESS; | ||
807 | break; | ||
808 | |||
809 | case SCU_EVENT_TL_RNC_SUSPEND_TX_RX: | ||
810 | sci_base_state_machine_change_state( | ||
811 | &this_rnc->state_machine, | ||
812 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE | ||
813 | ); | ||
814 | |||
815 | this_rnc->suspension_code = scu_get_event_specifier(event_code); | ||
816 | status = SCI_SUCCESS; | ||
817 | break; | ||
818 | |||
819 | default: | ||
820 | dev_warn(scirdev_to_dev(this_rnc->device), | ||
821 | "%s: SCIC Remote Node Context 0x%p requested to " | ||
822 | "process event 0x%x while in state %d.\n", | ||
823 | __func__, | ||
824 | this_rnc, | ||
825 | event_code, | ||
826 | sci_base_state_machine_get_state( | ||
827 | &this_rnc->state_machine)); | ||
828 | |||
829 | status = SCI_FAILURE; | ||
830 | break; | ||
831 | } | ||
832 | |||
833 | return status; | ||
834 | } | ||
835 | |||
836 | /* --------------------------------------------------------------------------- */ | ||
837 | |||
838 | struct scic_sds_remote_node_context_handlers | ||
839 | scic_sds_remote_node_context_state_handler_table[ | ||
840 | SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES] = | ||
841 | { | ||
842 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE */ | ||
843 | { | ||
844 | scic_sds_remote_node_context_default_destruct_handler, | ||
845 | scic_sds_remote_node_context_default_suspend_handler, | ||
846 | scic_sds_remote_node_context_initial_state_resume_handler, | ||
847 | scic_sds_remote_node_context_default_start_io_handler, | ||
848 | scic_sds_remote_node_context_default_start_task_handler, | ||
849 | scic_sds_remote_node_context_default_event_handler | ||
850 | }, | ||
851 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE */ | ||
852 | { | ||
853 | scic_sds_remote_node_context_general_destruct_handler, | ||
854 | scic_sds_remote_node_context_default_suspend_handler, | ||
855 | scic_sds_remote_node_context_continue_to_resume_handler, | ||
856 | scic_sds_remote_node_context_default_start_io_handler, | ||
857 | scic_sds_remote_node_context_default_start_task_handler, | ||
858 | scic_sds_remote_node_context_posting_state_event_handler | ||
859 | }, | ||
860 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE */ | ||
861 | { | ||
862 | scic_sds_remote_node_context_invalidating_state_destruct_handler, | ||
863 | scic_sds_remote_node_context_default_suspend_handler, | ||
864 | scic_sds_remote_node_context_continue_to_resume_handler, | ||
865 | scic_sds_remote_node_context_default_start_io_handler, | ||
866 | scic_sds_remote_node_context_default_start_task_handler, | ||
867 | scic_sds_remote_node_context_invalidating_state_event_handler | ||
868 | }, | ||
869 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE */ | ||
870 | { | ||
871 | scic_sds_remote_node_context_general_destruct_handler, | ||
872 | scic_sds_remote_node_context_default_suspend_handler, | ||
873 | scic_sds_remote_node_context_continue_to_resume_handler, | ||
874 | scic_sds_remote_node_context_default_start_io_handler, | ||
875 | scic_sds_remote_node_context_success_start_task_handler, | ||
876 | scic_sds_remote_node_context_resuming_state_event_handler | ||
877 | }, | ||
878 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE */ | ||
879 | { | ||
880 | scic_sds_remote_node_context_general_destruct_handler, | ||
881 | scic_sds_remote_node_context_ready_state_suspend_handler, | ||
882 | scic_sds_remote_node_context_default_resume_handler, | ||
883 | scic_sds_remote_node_context_ready_state_start_io_handler, | ||
884 | scic_sds_remote_node_context_success_start_task_handler, | ||
885 | scic_sds_remote_node_context_ready_state_event_handler | ||
886 | }, | ||
887 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE */ | ||
888 | { | ||
889 | scic_sds_remote_node_context_general_destruct_handler, | ||
890 | scic_sds_remote_node_context_default_suspend_handler, | ||
891 | scic_sds_remote_node_context_tx_suspended_state_resume_handler, | ||
892 | scic_sds_remote_node_context_default_start_io_handler, | ||
893 | scic_sds_remote_node_context_suspended_start_task_handler, | ||
894 | scic_sds_remote_node_context_default_event_handler | ||
895 | }, | ||
896 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE */ | ||
897 | { | ||
898 | scic_sds_remote_node_context_general_destruct_handler, | ||
899 | scic_sds_remote_node_context_default_suspend_handler, | ||
900 | scic_sds_remote_node_context_tx_rx_suspended_state_resume_handler, | ||
901 | scic_sds_remote_node_context_default_start_io_handler, | ||
902 | scic_sds_remote_node_context_suspended_start_task_handler, | ||
903 | scic_sds_remote_node_context_default_event_handler | ||
904 | }, | ||
905 | /* SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE */ | ||
906 | { | ||
907 | scic_sds_remote_node_context_general_destruct_handler, | ||
908 | scic_sds_remote_node_context_default_suspend_handler, | ||
909 | scic_sds_remote_node_context_await_suspension_state_resume_handler, | ||
910 | scic_sds_remote_node_context_default_start_io_handler, | ||
911 | scic_sds_remote_node_context_await_suspension_state_start_task_handler, | ||
912 | scic_sds_remote_node_context_await_suspension_state_event_handler | ||
913 | } | ||
914 | }; | ||
915 | |||
916 | /* | ||
917 | * ***************************************************************************** | ||
918 | * * REMOTE NODE CONTEXT PRIVATE METHODS | ||
919 | * ***************************************************************************** */ | ||
920 | |||
921 | /** | ||
922 | * | ||
923 | * | ||
924 | * This method just calls the user callback function and then resets the | ||
925 | * callback. | ||
926 | */ | ||
927 | static void scic_sds_remote_node_context_notify_user( | ||
928 | struct scic_sds_remote_node_context *rnc) | ||
929 | { | ||
930 | if (rnc->user_callback != NULL) { | ||
931 | (*rnc->user_callback)(rnc->user_cookie); | ||
932 | |||
933 | rnc->user_callback = NULL; | ||
934 | rnc->user_cookie = NULL; | ||
935 | } | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * | ||
940 | * | ||
941 | * This method will continue the remote node context state machine by | ||
942 | * requesting to resume the remote node context state machine from its current | ||
943 | * state. | ||
944 | */ | ||
945 | static void scic_sds_remote_node_context_continue_state_transitions( | ||
946 | struct scic_sds_remote_node_context *rnc) | ||
947 | { | ||
948 | if (rnc->destination_state == SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY) { | ||
949 | rnc->state_handlers->resume_handler( | ||
950 | rnc, rnc->user_callback, rnc->user_cookie | ||
951 | ); | ||
952 | } | ||
953 | } | ||
954 | |||
955 | /** | ||
956 | * | ||
957 | * @this_rnc: The remote node context object that is to be validated. | ||
958 | * | ||
959 | * This method will mark the rnc buffer as being valid and post the request to | ||
960 | * the hardware. none | ||
961 | */ | ||
962 | static void scic_sds_remote_node_context_validate_context_buffer( | ||
963 | struct scic_sds_remote_node_context *this_rnc) | ||
964 | { | ||
965 | union scu_remote_node_context *rnc_buffer; | ||
966 | |||
967 | rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( | ||
968 | scic_sds_remote_device_get_controller(this_rnc->device), | ||
969 | this_rnc->remote_node_index | ||
970 | ); | ||
971 | |||
972 | rnc_buffer->ssp.is_valid = true; | ||
973 | |||
974 | if ( | ||
975 | !this_rnc->device->is_direct_attached | ||
976 | && this_rnc->device->target_protocols.u.bits.attached_stp_target | ||
977 | ) { | ||
978 | scic_sds_remote_device_post_request( | ||
979 | this_rnc->device, | ||
980 | SCU_CONTEXT_COMMAND_POST_RNC_96 | ||
981 | ); | ||
982 | } else { | ||
983 | scic_sds_remote_device_post_request( | ||
984 | this_rnc->device, | ||
985 | SCU_CONTEXT_COMMAND_POST_RNC_32 | ||
986 | ); | ||
987 | |||
988 | if (this_rnc->device->is_direct_attached) { | ||
989 | scic_sds_port_set_direct_attached_device_id( | ||
990 | this_rnc->device->owning_port, | ||
991 | this_rnc->remote_node_index | ||
992 | ); | ||
993 | } | ||
994 | } | ||
995 | } | ||
996 | |||
997 | /** | ||
998 | * | ||
999 | * @this_rnc: The remote node context object that is to be invalidated. | ||
1000 | * | ||
1001 | * This method will update the RNC buffer and post the invalidate request. none | ||
1002 | */ | ||
1003 | static void scic_sds_remote_node_context_invalidate_context_buffer( | ||
1004 | struct scic_sds_remote_node_context *this_rnc) | ||
1005 | { | ||
1006 | union scu_remote_node_context *rnc_buffer; | ||
1007 | |||
1008 | rnc_buffer = scic_sds_controller_get_remote_node_context_buffer( | ||
1009 | scic_sds_remote_device_get_controller(this_rnc->device), | ||
1010 | this_rnc->remote_node_index | ||
1011 | ); | ||
1012 | |||
1013 | rnc_buffer->ssp.is_valid = false; | ||
1014 | |||
1015 | scic_sds_remote_device_post_request( | ||
1016 | this_rnc->device, | ||
1017 | SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE | ||
1018 | ); | ||
1019 | |||
1020 | if (this_rnc->device->is_direct_attached) { | ||
1021 | scic_sds_port_set_direct_attached_device_id( | ||
1022 | this_rnc->device->owning_port, | ||
1023 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | ||
1024 | ); | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | /* | ||
1029 | * ***************************************************************************** | ||
1030 | * * REMOTE NODE CONTEXT STATE ENTER AND EXIT METHODS | ||
1031 | * ***************************************************************************** */ | ||
1032 | |||
1033 | /** | ||
1034 | * | ||
1035 | * | ||
1036 | * | ||
1037 | */ | ||
1038 | static void scic_sds_remote_node_context_initial_state_enter( | ||
1039 | struct sci_base_object *object) | ||
1040 | { | ||
1041 | struct scic_sds_remote_node_context *rnc; | ||
1042 | |||
1043 | rnc = (struct scic_sds_remote_node_context *)object; | ||
1044 | |||
1045 | SET_STATE_HANDLER( | ||
1046 | rnc, | ||
1047 | scic_sds_remote_node_context_state_handler_table, | ||
1048 | SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE | ||
1049 | ); | ||
1050 | |||
1051 | /* | ||
1052 | * Check to see if we have gotten back to the initial state because someone | ||
1053 | * requested to destroy the remote node context object. */ | ||
1054 | if ( | ||
1055 | rnc->state_machine.previous_state_id | ||
1056 | == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE | ||
1057 | ) { | ||
1058 | rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; | ||
1059 | |||
1060 | scic_sds_remote_node_context_notify_user(rnc); | ||
1061 | } | ||
1062 | } | ||
1063 | |||
1064 | /** | ||
1065 | * | ||
1066 | * | ||
1067 | * | ||
1068 | */ | ||
1069 | static void scic_sds_remote_node_context_posting_state_enter( | ||
1070 | struct sci_base_object *object) | ||
1071 | { | ||
1072 | struct scic_sds_remote_node_context *this_rnc; | ||
1073 | |||
1074 | this_rnc = (struct scic_sds_remote_node_context *)object; | ||
1075 | |||
1076 | SET_STATE_HANDLER( | ||
1077 | this_rnc, | ||
1078 | scic_sds_remote_node_context_state_handler_table, | ||
1079 | SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE | ||
1080 | ); | ||
1081 | |||
1082 | scic_sds_remote_node_context_validate_context_buffer(this_rnc); | ||
1083 | } | ||
1084 | |||
1085 | /** | ||
1086 | * | ||
1087 | * | ||
1088 | * | ||
1089 | */ | ||
1090 | static void scic_sds_remote_node_context_invalidating_state_enter( | ||
1091 | struct sci_base_object *object) | ||
1092 | { | ||
1093 | struct scic_sds_remote_node_context *rnc; | ||
1094 | |||
1095 | rnc = (struct scic_sds_remote_node_context *)object; | ||
1096 | |||
1097 | SET_STATE_HANDLER( | ||
1098 | rnc, | ||
1099 | scic_sds_remote_node_context_state_handler_table, | ||
1100 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE | ||
1101 | ); | ||
1102 | |||
1103 | scic_sds_remote_node_context_invalidate_context_buffer(rnc); | ||
1104 | } | ||
1105 | |||
1106 | /** | ||
1107 | * | ||
1108 | * | ||
1109 | * | ||
1110 | */ | ||
1111 | static void scic_sds_remote_node_context_resuming_state_enter( | ||
1112 | struct sci_base_object *object) | ||
1113 | { | ||
1114 | struct scic_sds_remote_node_context *rnc; | ||
1115 | |||
1116 | rnc = (struct scic_sds_remote_node_context *)object; | ||
1117 | |||
1118 | SET_STATE_HANDLER( | ||
1119 | rnc, | ||
1120 | scic_sds_remote_node_context_state_handler_table, | ||
1121 | SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE | ||
1122 | ); | ||
1123 | |||
1124 | scic_sds_remote_device_post_request( | ||
1125 | rnc->device, | ||
1126 | SCU_CONTEXT_COMMAND_POST_RNC_RESUME | ||
1127 | ); | ||
1128 | } | ||
1129 | |||
1130 | /** | ||
1131 | * | ||
1132 | * | ||
1133 | * | ||
1134 | */ | ||
1135 | static void scic_sds_remote_node_context_ready_state_enter( | ||
1136 | struct sci_base_object *object) | ||
1137 | { | ||
1138 | struct scic_sds_remote_node_context *rnc; | ||
1139 | |||
1140 | rnc = (struct scic_sds_remote_node_context *)object; | ||
1141 | |||
1142 | SET_STATE_HANDLER( | ||
1143 | rnc, | ||
1144 | scic_sds_remote_node_context_state_handler_table, | ||
1145 | SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE | ||
1146 | ); | ||
1147 | |||
1148 | rnc->destination_state = SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED; | ||
1149 | |||
1150 | if (rnc->user_callback != NULL) { | ||
1151 | scic_sds_remote_node_context_notify_user(rnc); | ||
1152 | } | ||
1153 | } | ||
1154 | |||
1155 | /** | ||
1156 | * | ||
1157 | * | ||
1158 | * | ||
1159 | */ | ||
1160 | static void scic_sds_remote_node_context_tx_suspended_state_enter( | ||
1161 | struct sci_base_object *object) | ||
1162 | { | ||
1163 | struct scic_sds_remote_node_context *rnc; | ||
1164 | |||
1165 | rnc = (struct scic_sds_remote_node_context *)object; | ||
1166 | |||
1167 | SET_STATE_HANDLER( | ||
1168 | rnc, | ||
1169 | scic_sds_remote_node_context_state_handler_table, | ||
1170 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE | ||
1171 | ); | ||
1172 | |||
1173 | scic_sds_remote_node_context_continue_state_transitions(rnc); | ||
1174 | } | ||
1175 | |||
1176 | /** | ||
1177 | * | ||
1178 | * | ||
1179 | * | ||
1180 | */ | ||
1181 | static void scic_sds_remote_node_context_tx_rx_suspended_state_enter( | ||
1182 | struct sci_base_object *object) | ||
1183 | { | ||
1184 | struct scic_sds_remote_node_context *rnc; | ||
1185 | |||
1186 | rnc = (struct scic_sds_remote_node_context *)object; | ||
1187 | |||
1188 | SET_STATE_HANDLER( | ||
1189 | rnc, | ||
1190 | scic_sds_remote_node_context_state_handler_table, | ||
1191 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE | ||
1192 | ); | ||
1193 | |||
1194 | scic_sds_remote_node_context_continue_state_transitions(rnc); | ||
1195 | } | ||
1196 | |||
1197 | /** | ||
1198 | * | ||
1199 | * | ||
1200 | * | ||
1201 | */ | ||
1202 | static void scic_sds_remote_node_context_await_suspension_state_enter( | ||
1203 | struct sci_base_object *object) | ||
1204 | { | ||
1205 | struct scic_sds_remote_node_context *rnc; | ||
1206 | |||
1207 | rnc = (struct scic_sds_remote_node_context *)object; | ||
1208 | |||
1209 | SET_STATE_HANDLER( | ||
1210 | rnc, | ||
1211 | scic_sds_remote_node_context_state_handler_table, | ||
1212 | SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE | ||
1213 | ); | ||
1214 | } | ||
1215 | |||
1216 | /* --------------------------------------------------------------------------- */ | ||
1217 | |||
1218 | const struct sci_base_state scic_sds_remote_node_context_state_table[] = { | ||
1219 | [SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE] = { | ||
1220 | .enter_state = scic_sds_remote_node_context_initial_state_enter, | ||
1221 | }, | ||
1222 | [SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE] = { | ||
1223 | .enter_state = scic_sds_remote_node_context_posting_state_enter, | ||
1224 | }, | ||
1225 | [SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE] = { | ||
1226 | .enter_state = scic_sds_remote_node_context_invalidating_state_enter, | ||
1227 | }, | ||
1228 | [SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE] = { | ||
1229 | .enter_state = scic_sds_remote_node_context_resuming_state_enter, | ||
1230 | }, | ||
1231 | [SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE] = { | ||
1232 | .enter_state = scic_sds_remote_node_context_ready_state_enter, | ||
1233 | }, | ||
1234 | [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE] = { | ||
1235 | .enter_state = scic_sds_remote_node_context_tx_suspended_state_enter, | ||
1236 | }, | ||
1237 | [SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE] = { | ||
1238 | .enter_state = scic_sds_remote_node_context_tx_rx_suspended_state_enter, | ||
1239 | }, | ||
1240 | [SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE] = { | ||
1241 | .enter_state = scic_sds_remote_node_context_await_suspension_state_enter, | ||
1242 | }, | ||
1243 | }; | ||
1244 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_context.h b/drivers/scsi/isci/core/scic_sds_remote_node_context.h new file mode 100644 index 000000000000..59eacf8f400c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_context.h | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ | ||
57 | #define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants, and prototypes associated with | ||
61 | * the remote node context in the silicon. It exists to model and manage | ||
62 | * the remote node context in the silicon. | ||
63 | * | ||
64 | * | ||
65 | */ | ||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_base_state.h" | ||
69 | #include "sci_base_state_machine.h" | ||
70 | |||
71 | /* --------------------------------------------------------------------------- */ | ||
72 | |||
73 | /** | ||
74 | * | ||
75 | * | ||
76 | * This constant represents an invalid remote device id, it is used to program | ||
77 | * the STPDARNI register so the driver knows when it has received a SIGNATURE | ||
78 | * FIS from the SCU. | ||
79 | */ | ||
80 | #define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF | ||
81 | |||
82 | #define SCU_HARDWARE_SUSPENSION (0) | ||
83 | #define SCI_SOFTWARE_SUSPENSION (1) | ||
84 | |||
85 | struct scic_sds_request; | ||
86 | struct scic_sds_remote_device; | ||
87 | struct scic_sds_remote_node_context; | ||
88 | |||
89 | typedef void (*SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)(void *); | ||
90 | |||
91 | typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION)( | ||
92 | struct scic_sds_remote_node_context *this_rnc, | ||
93 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
94 | void *callback_parameter | ||
95 | ); | ||
96 | |||
97 | typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION)( | ||
98 | struct scic_sds_remote_node_context *this_rnc, | ||
99 | u32 suspension_type, | ||
100 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback, | ||
101 | void *callback_parameter | ||
102 | ); | ||
103 | |||
104 | typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST)( | ||
105 | struct scic_sds_remote_node_context *this_rnc, | ||
106 | struct scic_sds_request *the_request | ||
107 | ); | ||
108 | |||
109 | typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER)( | ||
110 | struct scic_sds_remote_node_context *this_rnc, | ||
111 | u32 event_code | ||
112 | ); | ||
113 | |||
114 | /* --------------------------------------------------------------------------- */ | ||
115 | |||
116 | struct scic_sds_remote_node_context_handlers { | ||
117 | /** | ||
118 | * This handle is invoked to stop the RNC. The callback is invoked when after | ||
119 | * the hardware notification that the RNC has been invalidated. | ||
120 | */ | ||
121 | SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION destruct_handler; | ||
122 | |||
123 | /** | ||
124 | * This handler is invoked when there is a request to suspend the RNC. The | ||
125 | * callback is invoked after the hardware notification that the remote node is | ||
126 | * suspended. | ||
127 | */ | ||
128 | SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION suspend_handler; | ||
129 | |||
130 | /** | ||
131 | * This handler is invoked when there is a request to resume the RNC. The | ||
132 | * callback is invoked when after the RNC has reached the ready state. | ||
133 | */ | ||
134 | SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION resume_handler; | ||
135 | |||
136 | /** | ||
137 | * This handler is invoked when there is a request to start an io request | ||
138 | * operation. | ||
139 | */ | ||
140 | SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_io_handler; | ||
141 | |||
142 | /** | ||
143 | * This handler is invoked when there is a request to start a task request | ||
144 | * operation. | ||
145 | */ | ||
146 | SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_task_handler; | ||
147 | |||
148 | /** | ||
149 | * This handler is invoked where there is an RNC event that must be processed. | ||
150 | */ | ||
151 | SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER event_handler; | ||
152 | |||
153 | }; | ||
154 | |||
155 | /* --------------------------------------------------------------------------- */ | ||
156 | |||
157 | /** | ||
158 | * | ||
159 | * | ||
160 | * This is the enumeration of the remote node context states. | ||
161 | */ | ||
162 | enum scis_sds_remote_node_context_states { | ||
163 | /** | ||
164 | * This state is the initial state for a remote node context. On a resume | ||
165 | * request the remote node context will transition to the posting state. | ||
166 | */ | ||
167 | SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE, | ||
168 | |||
169 | /** | ||
170 | * This is a transition state that posts the RNi to the hardware. Once the RNC | ||
171 | * is posted the remote node context will be made ready. | ||
172 | */ | ||
173 | SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE, | ||
174 | |||
175 | /** | ||
176 | * This is a transition state that will post an RNC invalidate to the | ||
177 | * hardware. Once the invalidate is complete the remote node context will | ||
178 | * transition to the posting state. | ||
179 | */ | ||
180 | SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE, | ||
181 | |||
182 | /** | ||
183 | * This is a transition state that will post an RNC resume to the hardare. | ||
184 | * Once the event notification of resume complete is received the remote node | ||
185 | * context will transition to the ready state. | ||
186 | */ | ||
187 | SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE, | ||
188 | |||
189 | /** | ||
190 | * This is the state that the remote node context must be in to accept io | ||
191 | * request operations. | ||
192 | */ | ||
193 | SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE, | ||
194 | |||
195 | /** | ||
196 | * This is the state that the remote node context transitions to when it gets | ||
197 | * a TX suspend notification from the hardware. | ||
198 | */ | ||
199 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE, | ||
200 | |||
201 | /** | ||
202 | * This is the state that the remote node context transitions to when it gets | ||
203 | * a TX RX suspend notification from the hardware. | ||
204 | */ | ||
205 | SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE, | ||
206 | |||
207 | /** | ||
208 | * This state is a wait state for the remote node context that waits for a | ||
209 | * suspend notification from the hardware. This state is entered when either | ||
210 | * there is a request to supend the remote node context or when there is a TC | ||
211 | * completion where the remote node will be suspended by the hardware. | ||
212 | */ | ||
213 | SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE, | ||
214 | |||
215 | SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES | ||
216 | |||
217 | }; | ||
218 | |||
219 | /** | ||
220 | * | ||
221 | * | ||
222 | * This enumeration is used to define the end destination state for the remote | ||
223 | * node context. | ||
224 | */ | ||
225 | enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE { | ||
226 | SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED, | ||
227 | SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY, | ||
228 | SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL | ||
229 | }; | ||
230 | |||
231 | /** | ||
232 | * struct scic_sds_remote_node_context - This structure contains the data | ||
233 | * associated with the remote node context object. The remote node context | ||
234 | * (RNC) object models the the remote device information necessary to manage | ||
235 | * the silicon RNC. | ||
236 | * | ||
237 | * | ||
238 | */ | ||
239 | struct scic_sds_remote_node_context { | ||
240 | /* | ||
241 | * parent object | ||
242 | */ | ||
243 | struct sci_base_object parent; | ||
244 | |||
245 | /** | ||
246 | * This pointer simply points to the remote device object containing | ||
247 | * this RNC. | ||
248 | * | ||
249 | * @todo Consider making the device pointer the associated object of the | ||
250 | * the parent object. | ||
251 | */ | ||
252 | struct scic_sds_remote_device *device; | ||
253 | |||
254 | /** | ||
255 | * This field indicates the remote node index (RNI) associated with | ||
256 | * this RNC. | ||
257 | */ | ||
258 | u16 remote_node_index; | ||
259 | |||
260 | /** | ||
261 | * This field is the recored suspension code or the reason for the remote node | ||
262 | * context suspension. | ||
263 | */ | ||
264 | u32 suspension_code; | ||
265 | |||
266 | /** | ||
267 | * This field is true if the remote node context is resuming from its current | ||
268 | * state. This can cause an automatic resume on receiving a suspension | ||
269 | * notification. | ||
270 | */ | ||
271 | enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE destination_state; | ||
272 | |||
273 | /** | ||
274 | * This field contains the callback function that the user requested to be | ||
275 | * called when the requested state transition is complete. | ||
276 | */ | ||
277 | SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK user_callback; | ||
278 | |||
279 | /** | ||
280 | * This field contains the parameter that is called when the user requested | ||
281 | * state transition is completed. | ||
282 | */ | ||
283 | void *user_cookie; | ||
284 | |||
285 | /** | ||
286 | * This field contains the data for the object's state machine. | ||
287 | */ | ||
288 | struct sci_base_state_machine state_machine; | ||
289 | |||
290 | struct scic_sds_remote_node_context_handlers *state_handlers; | ||
291 | }; | ||
292 | |||
293 | /* --------------------------------------------------------------------------- */ | ||
294 | |||
295 | extern const struct sci_base_state scic_sds_remote_node_context_state_table[]; | ||
296 | |||
297 | extern struct scic_sds_remote_node_context_handlers | ||
298 | scic_sds_remote_node_context_state_handler_table[ | ||
299 | SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES]; | ||
300 | |||
301 | /* --------------------------------------------------------------------------- */ | ||
302 | |||
303 | void scic_sds_remote_node_context_construct( | ||
304 | struct scic_sds_remote_device *device, | ||
305 | struct scic_sds_remote_node_context *rnc, | ||
306 | u16 remote_node_index); | ||
307 | |||
308 | void scic_sds_remote_node_context_construct_buffer( | ||
309 | struct scic_sds_remote_node_context *rnc); | ||
310 | |||
311 | |||
312 | bool scic_sds_remote_node_context_is_ready( | ||
313 | struct scic_sds_remote_node_context *this_rnc); | ||
314 | |||
315 | #define scic_sds_remote_node_context_set_remote_node_index(rnc, rni) \ | ||
316 | ((rnc)->remote_node_index = (rni)) | ||
317 | |||
318 | #define scic_sds_remote_node_context_get_remote_node_index(rcn) \ | ||
319 | ((rnc)->remote_node_index) | ||
320 | |||
321 | #define scic_sds_remote_node_context_event_handler(rnc, event_code) \ | ||
322 | ((rnc)->state_handlers->event_handler(rnc, event_code)) | ||
323 | |||
324 | #define scic_sds_remote_node_context_resume(rnc, callback, parameter) \ | ||
325 | ((rnc)->state_handlers->resume_handler(rnc, callback, parameter)) | ||
326 | |||
327 | #define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \ | ||
328 | ((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter)) | ||
329 | |||
330 | #define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \ | ||
331 | ((rnc)->state_handlers->destruct_handler(rnc, callback, parameter)) | ||
332 | |||
333 | #define scic_sds_remote_node_context_start_io(rnc, request) \ | ||
334 | ((rnc)->state_handlers->start_io_handler(rnc, request)) | ||
335 | |||
336 | #define scic_sds_remote_node_context_start_task(rnc, task) \ | ||
337 | ((rnc)->state_handlers->start_task_handler(rnc, task)) | ||
338 | |||
339 | /* --------------------------------------------------------------------------- */ | ||
340 | |||
341 | #endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */ | ||
342 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.c b/drivers/scsi/isci/core/scic_sds_remote_node_table.c new file mode 100644 index 000000000000..77919a2cf652 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.c | |||
@@ -0,0 +1,600 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the implementation of the SCIC_SDS_REMOTE_NODE_TABLE | ||
58 | * public, protected, and private methods. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | #include "sci_util.h" | ||
63 | #include "sci_environment.h" | ||
64 | #include "scic_sds_remote_node_table.h" | ||
65 | #include "scic_sds_remote_node_context.h" | ||
66 | |||
67 | /** | ||
68 | * | ||
69 | * @remote_node_table: This is the remote node index table from which the | ||
70 | * selection will be made. | ||
71 | * @group_table_index: This is the index to the group table from which to | ||
72 | * search for an available selection. | ||
73 | * | ||
74 | * This routine will find the bit position in absolute bit terms of the next 32 | ||
75 | * + bit position. If there are available bits in the first u32 then it is | ||
76 | * just bit position. u32 This is the absolute bit position for an available | ||
77 | * group. | ||
78 | */ | ||
79 | static u32 scic_sds_remote_node_table_get_group_index( | ||
80 | struct scic_remote_node_table *remote_node_table, | ||
81 | u32 group_table_index) | ||
82 | { | ||
83 | u32 dword_index; | ||
84 | u32 *group_table; | ||
85 | u32 bit_index; | ||
86 | |||
87 | group_table = remote_node_table->remote_node_groups[group_table_index]; | ||
88 | |||
89 | for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) { | ||
90 | if (group_table[dword_index] != 0) { | ||
91 | for (bit_index = 0; bit_index < 32; bit_index++) { | ||
92 | if ((group_table[dword_index] & (1 << bit_index)) != 0) { | ||
93 | return (dword_index * 32) + bit_index; | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | |||
99 | return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * | ||
104 | * @out]: remote_node_table This the remote node table in which to clear the | ||
105 | * selector. | ||
106 | * @set_index: This is the remote node selector in which the change will be | ||
107 | * made. | ||
108 | * @group_index: This is the bit index in the table to be modified. | ||
109 | * | ||
110 | * This method will clear the group index entry in the specified group index | ||
111 | * table. none | ||
112 | */ | ||
113 | static void scic_sds_remote_node_table_clear_group_index( | ||
114 | struct scic_remote_node_table *remote_node_table, | ||
115 | u32 group_table_index, | ||
116 | u32 group_index) | ||
117 | { | ||
118 | u32 dword_index; | ||
119 | u32 bit_index; | ||
120 | u32 *group_table; | ||
121 | |||
122 | BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); | ||
123 | BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); | ||
124 | |||
125 | dword_index = group_index / 32; | ||
126 | bit_index = group_index % 32; | ||
127 | group_table = remote_node_table->remote_node_groups[group_table_index]; | ||
128 | |||
129 | group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * | ||
134 | * @out]: remote_node_table This the remote node table in which to set the | ||
135 | * selector. | ||
136 | * @group_table_index: This is the remote node selector in which the change | ||
137 | * will be made. | ||
138 | * @group_index: This is the bit position in the table to be modified. | ||
139 | * | ||
140 | * This method will set the group index bit entry in the specified gropu index | ||
141 | * table. none | ||
142 | */ | ||
143 | static void scic_sds_remote_node_table_set_group_index( | ||
144 | struct scic_remote_node_table *remote_node_table, | ||
145 | u32 group_table_index, | ||
146 | u32 group_index) | ||
147 | { | ||
148 | u32 dword_index; | ||
149 | u32 bit_index; | ||
150 | u32 *group_table; | ||
151 | |||
152 | BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT); | ||
153 | BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32)); | ||
154 | |||
155 | dword_index = group_index / 32; | ||
156 | bit_index = group_index % 32; | ||
157 | group_table = remote_node_table->remote_node_groups[group_table_index]; | ||
158 | |||
159 | group_table[dword_index] = group_table[dword_index] | (1 << bit_index); | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * | ||
164 | * @out]: remote_node_table This is the remote node table in which to modify | ||
165 | * the remote node availability. | ||
166 | * @remote_node_index: This is the remote node index that is being returned to | ||
167 | * the table. | ||
168 | * | ||
169 | * This method will set the remote to available in the remote node allocation | ||
170 | * table. none | ||
171 | */ | ||
172 | static void scic_sds_remote_node_table_set_node_index( | ||
173 | struct scic_remote_node_table *remote_node_table, | ||
174 | u32 remote_node_index) | ||
175 | { | ||
176 | u32 dword_location; | ||
177 | u32 dword_remainder; | ||
178 | u32 slot_normalized; | ||
179 | u32 slot_position; | ||
180 | |||
181 | BUG_ON( | ||
182 | (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) | ||
183 | <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) | ||
184 | ); | ||
185 | |||
186 | dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; | ||
187 | dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; | ||
188 | slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); | ||
189 | slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; | ||
190 | |||
191 | remote_node_table->available_remote_nodes[dword_location] |= | ||
192 | 1 << (slot_normalized + slot_position); | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * | ||
197 | * @out]: remote_node_table This is the remote node table from which to clear | ||
198 | * the available remote node bit. | ||
199 | * @remote_node_index: This is the remote node index which is to be cleared | ||
200 | * from the table. | ||
201 | * | ||
202 | * This method clears the remote node index from the table of available remote | ||
203 | * nodes. none | ||
204 | */ | ||
205 | static void scic_sds_remote_node_table_clear_node_index( | ||
206 | struct scic_remote_node_table *remote_node_table, | ||
207 | u32 remote_node_index) | ||
208 | { | ||
209 | u32 dword_location; | ||
210 | u32 dword_remainder; | ||
211 | u32 slot_position; | ||
212 | u32 slot_normalized; | ||
213 | |||
214 | BUG_ON( | ||
215 | (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) | ||
216 | <= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT) | ||
217 | ); | ||
218 | |||
219 | dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD; | ||
220 | dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD; | ||
221 | slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32); | ||
222 | slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT; | ||
223 | |||
224 | remote_node_table->available_remote_nodes[dword_location] &= | ||
225 | ~(1 << (slot_normalized + slot_position)); | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * | ||
230 | * @out]: remote_node_table The remote node table from which the slot will be | ||
231 | * cleared. | ||
232 | * @group_index: The index for the slot that is to be cleared. | ||
233 | * | ||
234 | * This method clears the entire table slot at the specified slot index. none | ||
235 | */ | ||
236 | static void scic_sds_remote_node_table_clear_group( | ||
237 | struct scic_remote_node_table *remote_node_table, | ||
238 | u32 group_index) | ||
239 | { | ||
240 | u32 dword_location; | ||
241 | u32 dword_remainder; | ||
242 | u32 dword_value; | ||
243 | |||
244 | BUG_ON( | ||
245 | (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) | ||
246 | <= (group_index / SCU_STP_REMOTE_NODE_COUNT) | ||
247 | ); | ||
248 | |||
249 | dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; | ||
250 | dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; | ||
251 | |||
252 | dword_value = remote_node_table->available_remote_nodes[dword_location]; | ||
253 | dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); | ||
254 | remote_node_table->available_remote_nodes[dword_location] = dword_value; | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * | ||
259 | * @remote_node_table: | ||
260 | * | ||
261 | * THis method sets an entire remote node group in the remote node table. | ||
262 | */ | ||
263 | static void scic_sds_remote_node_table_set_group( | ||
264 | struct scic_remote_node_table *remote_node_table, | ||
265 | u32 group_index) | ||
266 | { | ||
267 | u32 dword_location; | ||
268 | u32 dword_remainder; | ||
269 | u32 dword_value; | ||
270 | |||
271 | BUG_ON( | ||
272 | (remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD) | ||
273 | <= (group_index / SCU_STP_REMOTE_NODE_COUNT) | ||
274 | ); | ||
275 | |||
276 | dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; | ||
277 | dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; | ||
278 | |||
279 | dword_value = remote_node_table->available_remote_nodes[dword_location]; | ||
280 | dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); | ||
281 | remote_node_table->available_remote_nodes[dword_location] = dword_value; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * | ||
286 | * @remote_node_table: This is the remote node table that for which the group | ||
287 | * value is to be returned. | ||
288 | * @group_index: This is the group index to use to find the group value. | ||
289 | * | ||
290 | * This method will return the group value for the specified group index. The | ||
291 | * bit values at the specified remote node group index. | ||
292 | */ | ||
293 | static u8 scic_sds_remote_node_table_get_group_value( | ||
294 | struct scic_remote_node_table *remote_node_table, | ||
295 | u32 group_index) | ||
296 | { | ||
297 | u32 dword_location; | ||
298 | u32 dword_remainder; | ||
299 | u32 dword_value; | ||
300 | |||
301 | dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; | ||
302 | dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD; | ||
303 | |||
304 | dword_value = remote_node_table->available_remote_nodes[dword_location]; | ||
305 | dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4)); | ||
306 | dword_value = dword_value >> (dword_remainder * 4); | ||
307 | |||
308 | return (u8)dword_value; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * | ||
313 | * @out]: remote_node_table The remote that which is to be initialized. | ||
314 | * @remote_node_entries: The number of entries to put in the table. | ||
315 | * | ||
316 | * This method will initialize the remote node table for use. none | ||
317 | */ | ||
318 | void scic_sds_remote_node_table_initialize( | ||
319 | struct scic_remote_node_table *remote_node_table, | ||
320 | u32 remote_node_entries) | ||
321 | { | ||
322 | u32 index; | ||
323 | |||
324 | /* | ||
325 | * Initialize the raw data we could improve the speed by only initializing | ||
326 | * those entries that we are actually going to be used */ | ||
327 | memset( | ||
328 | remote_node_table->available_remote_nodes, | ||
329 | 0x00, | ||
330 | sizeof(remote_node_table->available_remote_nodes) | ||
331 | ); | ||
332 | |||
333 | memset( | ||
334 | remote_node_table->remote_node_groups, | ||
335 | 0x00, | ||
336 | sizeof(remote_node_table->remote_node_groups) | ||
337 | ); | ||
338 | |||
339 | /* Initialize the available remote node sets */ | ||
340 | remote_node_table->available_nodes_array_size = (u16) | ||
341 | (remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD) | ||
342 | + ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0); | ||
343 | |||
344 | |||
345 | /* Initialize each full DWORD to a FULL SET of remote nodes */ | ||
346 | for (index = 0; index < remote_node_entries; index++) { | ||
347 | scic_sds_remote_node_table_set_node_index(remote_node_table, index); | ||
348 | } | ||
349 | |||
350 | remote_node_table->group_array_size = (u16) | ||
351 | (remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32)) | ||
352 | + ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0); | ||
353 | |||
354 | for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) { | ||
355 | /* | ||
356 | * These are all guaranteed to be full slot values so fill them in the | ||
357 | * available sets of 3 remote nodes */ | ||
358 | scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index); | ||
359 | } | ||
360 | |||
361 | /* Now fill in any remainders that we may find */ | ||
362 | if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) { | ||
363 | scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index); | ||
364 | } else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) { | ||
365 | scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * | ||
371 | * @out]: remote_node_table The remote node table from which to allocate a | ||
372 | * remote node. | ||
373 | * @table_index: The group index that is to be used for the search. | ||
374 | * | ||
375 | * This method will allocate a single RNi from the remote node table. The | ||
376 | * table index will determine from which remote node group table to search. | ||
377 | * This search may fail and another group node table can be specified. The | ||
378 | * function is designed to allow a serach of the available single remote node | ||
379 | * group up to the triple remote node group. If an entry is found in the | ||
380 | * specified table the remote node is removed and the remote node groups are | ||
381 | * updated. The RNi value or an invalid remote node context if an RNi can not | ||
382 | * be found. | ||
383 | */ | ||
384 | static u16 scic_sds_remote_node_table_allocate_single_remote_node( | ||
385 | struct scic_remote_node_table *remote_node_table, | ||
386 | u32 group_table_index) | ||
387 | { | ||
388 | u8 index; | ||
389 | u8 group_value; | ||
390 | u32 group_index; | ||
391 | u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; | ||
392 | |||
393 | group_index = scic_sds_remote_node_table_get_group_index( | ||
394 | remote_node_table, group_table_index); | ||
395 | |||
396 | /* We could not find an available slot in the table selector 0 */ | ||
397 | if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { | ||
398 | group_value = scic_sds_remote_node_table_get_group_value( | ||
399 | remote_node_table, group_index); | ||
400 | |||
401 | for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) { | ||
402 | if (((1 << index) & group_value) != 0) { | ||
403 | /* We have selected a bit now clear it */ | ||
404 | remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT | ||
405 | + index); | ||
406 | |||
407 | scic_sds_remote_node_table_clear_group_index( | ||
408 | remote_node_table, group_table_index, group_index | ||
409 | ); | ||
410 | |||
411 | scic_sds_remote_node_table_clear_node_index( | ||
412 | remote_node_table, remote_node_index | ||
413 | ); | ||
414 | |||
415 | if (group_table_index > 0) { | ||
416 | scic_sds_remote_node_table_set_group_index( | ||
417 | remote_node_table, group_table_index - 1, group_index | ||
418 | ); | ||
419 | } | ||
420 | |||
421 | break; | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | |||
426 | return remote_node_index; | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * | ||
431 | * @remote_node_table: This is the remote node table from which to allocate the | ||
432 | * remote node entries. | ||
433 | * @group_table_index: THis is the group table index which must equal two (2) | ||
434 | * for this operation. | ||
435 | * | ||
436 | * This method will allocate three consecutive remote node context entries. If | ||
437 | * there are no remaining triple entries the function will return a failure. | ||
438 | * The remote node index that represents three consecutive remote node entries | ||
439 | * or an invalid remote node context if none can be found. | ||
440 | */ | ||
441 | static u16 scic_sds_remote_node_table_allocate_triple_remote_node( | ||
442 | struct scic_remote_node_table *remote_node_table, | ||
443 | u32 group_table_index) | ||
444 | { | ||
445 | u32 group_index; | ||
446 | u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; | ||
447 | |||
448 | group_index = scic_sds_remote_node_table_get_group_index( | ||
449 | remote_node_table, group_table_index); | ||
450 | |||
451 | if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) { | ||
452 | remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT; | ||
453 | |||
454 | scic_sds_remote_node_table_clear_group_index( | ||
455 | remote_node_table, group_table_index, group_index | ||
456 | ); | ||
457 | |||
458 | scic_sds_remote_node_table_clear_group( | ||
459 | remote_node_table, group_index | ||
460 | ); | ||
461 | } | ||
462 | |||
463 | return remote_node_index; | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * | ||
468 | * @remote_node_table: This is the remote node table from which the remote node | ||
469 | * allocation is to take place. | ||
470 | * @remote_node_count: This is ther remote node count which is one of | ||
471 | * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). | ||
472 | * | ||
473 | * This method will allocate a remote node that mataches the remote node count | ||
474 | * specified by the caller. Valid values for remote node count is | ||
475 | * SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is | ||
476 | * the remote node index that is returned or an invalid remote node context. | ||
477 | */ | ||
478 | u16 scic_sds_remote_node_table_allocate_remote_node( | ||
479 | struct scic_remote_node_table *remote_node_table, | ||
480 | u32 remote_node_count) | ||
481 | { | ||
482 | u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX; | ||
483 | |||
484 | if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { | ||
485 | remote_node_index = | ||
486 | scic_sds_remote_node_table_allocate_single_remote_node( | ||
487 | remote_node_table, 0); | ||
488 | |||
489 | if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { | ||
490 | remote_node_index = | ||
491 | scic_sds_remote_node_table_allocate_single_remote_node( | ||
492 | remote_node_table, 1); | ||
493 | } | ||
494 | |||
495 | if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) { | ||
496 | remote_node_index = | ||
497 | scic_sds_remote_node_table_allocate_single_remote_node( | ||
498 | remote_node_table, 2); | ||
499 | } | ||
500 | } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { | ||
501 | remote_node_index = | ||
502 | scic_sds_remote_node_table_allocate_triple_remote_node( | ||
503 | remote_node_table, 2); | ||
504 | } | ||
505 | |||
506 | return remote_node_index; | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * | ||
511 | * @remote_node_table: | ||
512 | * | ||
513 | * This method will free a single remote node index back to the remote node | ||
514 | * table. This routine will update the remote node groups | ||
515 | */ | ||
516 | static void scic_sds_remote_node_table_release_single_remote_node( | ||
517 | struct scic_remote_node_table *remote_node_table, | ||
518 | u16 remote_node_index) | ||
519 | { | ||
520 | u32 group_index; | ||
521 | u8 group_value; | ||
522 | |||
523 | group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; | ||
524 | |||
525 | group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index); | ||
526 | |||
527 | /* | ||
528 | * Assert that we are not trying to add an entry to a slot that is already | ||
529 | * full. */ | ||
530 | BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE); | ||
531 | |||
532 | if (group_value == 0x00) { | ||
533 | /* | ||
534 | * There are no entries in this slot so it must be added to the single | ||
535 | * slot table. */ | ||
536 | scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index); | ||
537 | } else if ((group_value & (group_value - 1)) == 0) { | ||
538 | /* | ||
539 | * There is only one entry in this slot so it must be moved from the | ||
540 | * single slot table to the dual slot table */ | ||
541 | scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index); | ||
542 | scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index); | ||
543 | } else { | ||
544 | /* | ||
545 | * There are two entries in the slot so it must be moved from the dual | ||
546 | * slot table to the tripple slot table. */ | ||
547 | scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index); | ||
548 | scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index); | ||
549 | } | ||
550 | |||
551 | scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index); | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * | ||
556 | * @remote_node_table: This is the remote node table to which the remote node | ||
557 | * index is to be freed. | ||
558 | * | ||
559 | * This method will release a group of three consecutive remote nodes back to | ||
560 | * the free remote nodes. | ||
561 | */ | ||
562 | static void scic_sds_remote_node_table_release_triple_remote_node( | ||
563 | struct scic_remote_node_table *remote_node_table, | ||
564 | u16 remote_node_index) | ||
565 | { | ||
566 | u32 group_index; | ||
567 | |||
568 | group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT; | ||
569 | |||
570 | scic_sds_remote_node_table_set_group_index( | ||
571 | remote_node_table, 2, group_index | ||
572 | ); | ||
573 | |||
574 | scic_sds_remote_node_table_set_group(remote_node_table, group_index); | ||
575 | } | ||
576 | |||
577 | /** | ||
578 | * | ||
579 | * @remote_node_table: The remote node table to which the remote node index is | ||
580 | * to be freed. | ||
581 | * @remote_node_count: This is the count of consecutive remote nodes that are | ||
582 | * to be freed. | ||
583 | * | ||
584 | * This method will release the remote node index back into the remote node | ||
585 | * table free pool. | ||
586 | */ | ||
587 | void scic_sds_remote_node_table_release_remote_node_index( | ||
588 | struct scic_remote_node_table *remote_node_table, | ||
589 | u32 remote_node_count, | ||
590 | u16 remote_node_index) | ||
591 | { | ||
592 | if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) { | ||
593 | scic_sds_remote_node_table_release_single_remote_node( | ||
594 | remote_node_table, remote_node_index); | ||
595 | } else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) { | ||
596 | scic_sds_remote_node_table_release_triple_remote_node( | ||
597 | remote_node_table, remote_node_index); | ||
598 | } | ||
599 | } | ||
600 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_remote_node_table.h b/drivers/scsi/isci/core/scic_sds_remote_node_table.h new file mode 100644 index 000000000000..6ee5fbab25dd --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_remote_node_table.h | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_ | ||
57 | #define _SCIC_SDS_REMOTE_NODE_TABLE_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants and prototypes used for the | ||
61 | * remote node table. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_types.h" | ||
67 | #include "sci_controller_constants.h" | ||
68 | |||
69 | /** | ||
70 | * | ||
71 | * | ||
72 | * Remote node sets are sets of remote node index in the remtoe node table The | ||
73 | * SCU hardware requires that STP remote node entries take three consecutive | ||
74 | * remote node index so the table is arranged in sets of three. The bits are | ||
75 | * used as 0111 0111 to make a byte and the bits define the set of three remote | ||
76 | * nodes to use as a sequence. | ||
77 | */ | ||
78 | #define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2 | ||
79 | |||
80 | /** | ||
81 | * | ||
82 | * | ||
83 | * Since the remote node table is organized as DWORDS take the remote node sets | ||
84 | * in bytes and represent them in DWORDs. The lowest ordered bits are the ones | ||
85 | * used in case full DWORD is not being used. i.e. 0000 0000 0000 0000 0111 | ||
86 | * 0111 0111 0111 // if only a single WORD is in use in the DWORD. | ||
87 | */ | ||
88 | #define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \ | ||
89 | (sizeof(u32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) | ||
90 | /** | ||
91 | * | ||
92 | * | ||
93 | * This is a count of the numeber of remote nodes that can be represented in a | ||
94 | * byte | ||
95 | */ | ||
96 | #define SCIC_SDS_REMOTE_NODES_PER_BYTE \ | ||
97 | (SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE) | ||
98 | |||
99 | /** | ||
100 | * | ||
101 | * | ||
102 | * This is a count of the number of remote nodes that can be represented in a | ||
103 | * DWROD | ||
104 | */ | ||
105 | #define SCIC_SDS_REMOTE_NODES_PER_DWORD \ | ||
106 | (sizeof(u32) * SCIC_SDS_REMOTE_NODES_PER_BYTE) | ||
107 | |||
108 | /** | ||
109 | * | ||
110 | * | ||
111 | * This is the number of bits in a remote node group | ||
112 | */ | ||
113 | #define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP 4 | ||
114 | |||
115 | #define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX (0xFFFFFFFF) | ||
116 | #define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE (0x07) | ||
117 | #define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE (0x00) | ||
118 | |||
119 | /** | ||
120 | * | ||
121 | * | ||
122 | * Expander attached sata remote node count | ||
123 | */ | ||
124 | #define SCU_STP_REMOTE_NODE_COUNT 3 | ||
125 | |||
126 | /** | ||
127 | * | ||
128 | * | ||
129 | * Expander or direct attached ssp remote node count | ||
130 | */ | ||
131 | #define SCU_SSP_REMOTE_NODE_COUNT 1 | ||
132 | |||
133 | /** | ||
134 | * | ||
135 | * | ||
136 | * Direct attached STP remote node count | ||
137 | */ | ||
138 | #define SCU_SATA_REMOTE_NODE_COUNT 1 | ||
139 | |||
140 | /** | ||
141 | * struct scic_remote_node_table - | ||
142 | * | ||
143 | * | ||
144 | */ | ||
145 | struct scic_remote_node_table { | ||
146 | /** | ||
147 | * This field contains the array size in dwords | ||
148 | */ | ||
149 | u16 available_nodes_array_size; | ||
150 | |||
151 | /** | ||
152 | * This field contains the array size of the | ||
153 | */ | ||
154 | u16 group_array_size; | ||
155 | |||
156 | /** | ||
157 | * This field is the array of available remote node entries in bits. | ||
158 | * Because of the way STP remote node data is allocated on the SCU hardware | ||
159 | * the remote nodes must occupy three consecutive remote node context | ||
160 | * entries. For ease of allocation and de-allocation we have broken the | ||
161 | * sets of three into a single nibble. When the STP RNi is allocated all | ||
162 | * of the bits in the nibble are cleared. This math results in a table size | ||
163 | * of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte. | ||
164 | */ | ||
165 | u32 available_remote_nodes[ | ||
166 | (SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD) | ||
167 | + ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)]; | ||
168 | |||
169 | /** | ||
170 | * This field is the nibble selector for the above table. There are three | ||
171 | * possible selectors each for fast lookup when trying to find one, two or | ||
172 | * three remote node entries. | ||
173 | */ | ||
174 | u32 remote_node_groups[ | ||
175 | SCU_STP_REMOTE_NODE_COUNT][ | ||
176 | (SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT)) | ||
177 | + ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)]; | ||
178 | |||
179 | }; | ||
180 | |||
181 | /* --------------------------------------------------------------------------- */ | ||
182 | |||
183 | void scic_sds_remote_node_table_initialize( | ||
184 | struct scic_remote_node_table *remote_node_table, | ||
185 | u32 remote_node_entries); | ||
186 | |||
187 | u16 scic_sds_remote_node_table_allocate_remote_node( | ||
188 | struct scic_remote_node_table *remote_node_table, | ||
189 | u32 remote_node_count); | ||
190 | |||
191 | void scic_sds_remote_node_table_release_remote_node_index( | ||
192 | struct scic_remote_node_table *remote_node_table, | ||
193 | u32 remote_node_count, | ||
194 | u16 remote_node_index); | ||
195 | |||
196 | #endif /* _SCIC_SDS_REMOTE_NODE_TABLE_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_request.c b/drivers/scsi/isci/core/scic_sds_request.c new file mode 100644 index 000000000000..c696d246ea5a --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_request.c | |||
@@ -0,0 +1,2179 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | |||
57 | #include "intel_sas.h" | ||
58 | #include "intel_sata.h" | ||
59 | #include "intel_sat.h" | ||
60 | #include "sci_base_request.h" | ||
61 | #include "scic_controller.h" | ||
62 | #include "scic_io_request.h" | ||
63 | #include "scic_remote_device.h" | ||
64 | #include "scic_sds_controller.h" | ||
65 | #include "scic_sds_controller_registers.h" | ||
66 | #include "scic_sds_pci.h" | ||
67 | #include "scic_sds_port.h" | ||
68 | #include "scic_sds_remote_device.h" | ||
69 | #include "scic_sds_request.h" | ||
70 | #include "scic_sds_smp_request.h" | ||
71 | #include "scic_sds_stp_request.h" | ||
72 | #include "scic_sds_unsolicited_frame_control.h" | ||
73 | #include "scic_user_callback.h" | ||
74 | #include "sci_environment.h" | ||
75 | #include "sci_types.h" | ||
76 | #include "sci_util.h" | ||
77 | #include "scu_completion_codes.h" | ||
78 | #include "scu_constants.h" | ||
79 | #include "scu_task_context.h" | ||
80 | |||
81 | #if !defined(DISABLE_ATAPI) | ||
82 | #include "scic_sds_stp_packet_request.h" | ||
83 | #endif | ||
84 | |||
85 | /* | ||
86 | * **************************************************************************** | ||
87 | * * SCIC SDS IO REQUEST CONSTANTS | ||
88 | * **************************************************************************** */ | ||
89 | |||
90 | /** | ||
91 | * | ||
92 | * | ||
93 | * We have no timer requirements for IO requests right now | ||
94 | */ | ||
95 | #define SCIC_SDS_IO_REQUEST_MINIMUM_TIMER_COUNT (0) | ||
96 | #define SCIC_SDS_IO_REQUEST_MAXIMUM_TIMER_COUNT (0) | ||
97 | |||
98 | /* | ||
99 | * **************************************************************************** | ||
100 | * * SCIC SDS IO REQUEST MACROS | ||
101 | * **************************************************************************** */ | ||
102 | |||
103 | /** | ||
104 | * scic_sds_request_get_user_request() - | ||
105 | * | ||
106 | * This is a helper macro to return the os handle for this request object. | ||
107 | */ | ||
108 | #define scic_sds_request_get_user_request(request) \ | ||
109 | ((request)->user_request) | ||
110 | |||
111 | |||
112 | /** | ||
113 | * scic_ssp_io_request_get_object_size() - | ||
114 | * | ||
115 | * This macro returns the sizeof memory required to store the an SSP IO | ||
116 | * request. This does not include the size of the SGL or SCU Task Context | ||
117 | * memory. | ||
118 | */ | ||
119 | #define scic_ssp_io_request_get_object_size() \ | ||
120 | (\ | ||
121 | sizeof(struct sci_ssp_command_iu) \ | ||
122 | + sizeof(struct sci_ssp_response_iu) \ | ||
123 | ) | ||
124 | |||
125 | /** | ||
126 | * scic_sds_ssp_request_get_command_buffer() - | ||
127 | * | ||
128 | * This macro returns the address of the ssp command buffer in the io request | ||
129 | * memory | ||
130 | */ | ||
131 | #define scic_sds_ssp_request_get_command_buffer(memory) \ | ||
132 | ((struct sci_ssp_command_iu *)(\ | ||
133 | ((char *)(memory)) + sizeof(struct scic_sds_request) \ | ||
134 | )) | ||
135 | |||
136 | /** | ||
137 | * scic_sds_ssp_request_get_response_buffer() - | ||
138 | * | ||
139 | * This macro returns the address of the ssp response buffer in the io request | ||
140 | * memory | ||
141 | */ | ||
142 | #define scic_sds_ssp_request_get_response_buffer(memory) \ | ||
143 | ((struct sci_ssp_response_iu *)(\ | ||
144 | ((char *)(scic_sds_ssp_request_get_command_buffer(memory))) \ | ||
145 | + sizeof(struct sci_ssp_command_iu) \ | ||
146 | )) | ||
147 | |||
148 | /** | ||
149 | * scic_sds_ssp_request_get_task_context_buffer() - | ||
150 | * | ||
151 | * This macro returns the address of the task context buffer in the io request | ||
152 | * memory | ||
153 | */ | ||
154 | #define scic_sds_ssp_request_get_task_context_buffer(memory) \ | ||
155 | ((struct scu_task_context *)(\ | ||
156 | ((char *)(scic_sds_ssp_request_get_response_buffer(memory))) \ | ||
157 | + sizeof(struct sci_ssp_response_iu) \ | ||
158 | )) | ||
159 | |||
160 | /** | ||
161 | * scic_sds_ssp_request_get_sgl_element_buffer() - | ||
162 | * | ||
163 | * This macro returns the address of the sgl elment pairs in the io request | ||
164 | * memory buffer | ||
165 | */ | ||
166 | #define scic_sds_ssp_request_get_sgl_element_buffer(memory) \ | ||
167 | ((struct scu_sgl_element_pair *)(\ | ||
168 | ((char *)(scic_sds_ssp_request_get_task_context_buffer(memory))) \ | ||
169 | + sizeof(struct scu_task_context) \ | ||
170 | )) | ||
171 | |||
172 | |||
173 | /** | ||
174 | * scic_ssp_task_request_get_object_size() - | ||
175 | * | ||
176 | * This macro returns the sizeof of memory required to store an SSP Task | ||
177 | * request. This does not include the size of the SCU Task Context memory. | ||
178 | */ | ||
179 | #define scic_ssp_task_request_get_object_size() \ | ||
180 | (\ | ||
181 | sizeof(struct sci_ssp_task_iu) \ | ||
182 | + sizeof(struct sci_ssp_response_iu) \ | ||
183 | ) | ||
184 | |||
185 | /** | ||
186 | * scic_sds_ssp_task_request_get_command_buffer() - | ||
187 | * | ||
188 | * This macro returns the address of the ssp command buffer in the task request | ||
189 | * memory. Yes its the same as the above macro except for the name. | ||
190 | */ | ||
191 | #define scic_sds_ssp_task_request_get_command_buffer(memory) \ | ||
192 | ((struct sci_ssp_task_iu *)(\ | ||
193 | ((char *)(memory)) + sizeof(struct scic_sds_request) \ | ||
194 | )) | ||
195 | |||
196 | /** | ||
197 | * scic_sds_ssp_task_request_get_response_buffer() - | ||
198 | * | ||
199 | * This macro returns the address of the ssp response buffer in the task | ||
200 | * request memory. | ||
201 | */ | ||
202 | #define scic_sds_ssp_task_request_get_response_buffer(memory) \ | ||
203 | ((struct sci_ssp_response_iu *)(\ | ||
204 | ((char *)(scic_sds_ssp_task_request_get_command_buffer(memory))) \ | ||
205 | + sizeof(struct sci_ssp_task_iu) \ | ||
206 | )) | ||
207 | |||
208 | /** | ||
209 | * scic_sds_ssp_task_request_get_task_context_buffer() - | ||
210 | * | ||
211 | * This macro returs the task context buffer for the SSP task request. | ||
212 | */ | ||
213 | #define scic_sds_ssp_task_request_get_task_context_buffer(memory) \ | ||
214 | ((struct scu_task_context *)(\ | ||
215 | ((char *)(scic_sds_ssp_task_request_get_response_buffer(memory))) \ | ||
216 | + sizeof(struct sci_ssp_response_iu) \ | ||
217 | )) | ||
218 | |||
219 | |||
220 | |||
221 | /* | ||
222 | * **************************************************************************** | ||
223 | * * SCIC SDS IO REQUEST PRIVATE METHODS | ||
224 | * **************************************************************************** */ | ||
225 | |||
226 | /** | ||
227 | * | ||
228 | * | ||
229 | * This method returns the size required to store an SSP IO request object. u32 | ||
230 | */ | ||
231 | static u32 scic_sds_ssp_request_get_object_size(void) | ||
232 | { | ||
233 | return sizeof(struct scic_sds_request) | ||
234 | + scic_ssp_io_request_get_object_size() | ||
235 | + sizeof(struct scu_task_context) | ||
236 | + CACHE_LINE_SIZE | ||
237 | + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * This method returns the sgl element pair for the specificed sgl_pair index. | ||
242 | * @this_request: This parameter specifies the IO request for which to retrieve | ||
243 | * the Scatter-Gather List element pair. | ||
244 | * @sgl_pair_index: This parameter specifies the index into the SGL element | ||
245 | * pair to be retrieved. | ||
246 | * | ||
247 | * This method returns a pointer to an struct scu_sgl_element_pair. | ||
248 | */ | ||
249 | static struct scu_sgl_element_pair *scic_sds_request_get_sgl_element_pair( | ||
250 | struct scic_sds_request *this_request, | ||
251 | u32 sgl_pair_index | ||
252 | ) { | ||
253 | struct scu_task_context *task_context; | ||
254 | |||
255 | task_context = (struct scu_task_context *)this_request->task_context_buffer; | ||
256 | |||
257 | if (sgl_pair_index == 0) { | ||
258 | return &task_context->sgl_pair_ab; | ||
259 | } else if (sgl_pair_index == 1) { | ||
260 | return &task_context->sgl_pair_cd; | ||
261 | } | ||
262 | |||
263 | return &this_request->sgl_element_pair_buffer[sgl_pair_index - 2]; | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * This function will build the SGL list for an IO request. | ||
268 | * @this_request: This parameter specifies the IO request for which to build | ||
269 | * the Scatter-Gather List. | ||
270 | * | ||
271 | */ | ||
272 | void scic_sds_request_build_sgl( | ||
273 | struct scic_sds_request *this_request) | ||
274 | { | ||
275 | void *os_sge; | ||
276 | void *os_handle; | ||
277 | dma_addr_t physical_address; | ||
278 | u32 sgl_pair_index = 0; | ||
279 | struct scu_sgl_element_pair *scu_sgl_list = NULL; | ||
280 | struct scu_sgl_element_pair *previous_pair = NULL; | ||
281 | |||
282 | os_handle = scic_sds_request_get_user_request(this_request); | ||
283 | scic_cb_io_request_get_next_sge(os_handle, NULL, &os_sge); | ||
284 | |||
285 | while (os_sge != NULL) { | ||
286 | scu_sgl_list = | ||
287 | scic_sds_request_get_sgl_element_pair(this_request, sgl_pair_index); | ||
288 | |||
289 | SCU_SGL_COPY(os_handle, scu_sgl_list->A, os_sge); | ||
290 | |||
291 | scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); | ||
292 | |||
293 | if (os_sge != NULL) { | ||
294 | SCU_SGL_COPY(os_handle, scu_sgl_list->B, os_sge); | ||
295 | |||
296 | scic_cb_io_request_get_next_sge(os_handle, os_sge, &os_sge); | ||
297 | } else { | ||
298 | SCU_SGL_ZERO(scu_sgl_list->B); | ||
299 | } | ||
300 | |||
301 | if (previous_pair != NULL) { | ||
302 | scic_cb_io_request_get_physical_address( | ||
303 | scic_sds_request_get_controller(this_request), | ||
304 | this_request, | ||
305 | scu_sgl_list, | ||
306 | &physical_address | ||
307 | ); | ||
308 | |||
309 | previous_pair->next_pair_upper = | ||
310 | upper_32_bits(physical_address); | ||
311 | previous_pair->next_pair_lower = | ||
312 | lower_32_bits(physical_address); | ||
313 | } | ||
314 | |||
315 | previous_pair = scu_sgl_list; | ||
316 | sgl_pair_index++; | ||
317 | } | ||
318 | |||
319 | if (scu_sgl_list != NULL) { | ||
320 | scu_sgl_list->next_pair_upper = 0; | ||
321 | scu_sgl_list->next_pair_lower = 0; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * This method initializes common portions of the io request object. This | ||
327 | * includes construction of the struct sci_base_request parent. | ||
328 | * @the_controller: This parameter specifies the controller for which the | ||
329 | * request is being constructed. | ||
330 | * @the_target: This parameter specifies the remote device for which the | ||
331 | * request is being constructed. | ||
332 | * @io_tag: This parameter specifies the IO tag to be utilized for this | ||
333 | * request. This parameter can be set to SCI_CONTROLLER_INVALID_IO_TAG. | ||
334 | * @user_io_request_object: This parameter specifies the user request object | ||
335 | * for which the request is being constructed. | ||
336 | * @this_request: This parameter specifies the request being constructed. | ||
337 | * | ||
338 | */ | ||
339 | static void scic_sds_general_request_construct( | ||
340 | struct scic_sds_controller *the_controller, | ||
341 | struct scic_sds_remote_device *the_target, | ||
342 | u16 io_tag, | ||
343 | void *user_io_request_object, | ||
344 | struct scic_sds_request *this_request) | ||
345 | { | ||
346 | sci_base_request_construct( | ||
347 | &this_request->parent, | ||
348 | scic_sds_request_state_table | ||
349 | ); | ||
350 | |||
351 | this_request->io_tag = io_tag; | ||
352 | this_request->user_request = user_io_request_object; | ||
353 | this_request->owning_controller = the_controller; | ||
354 | this_request->target_device = the_target; | ||
355 | this_request->has_started_substate_machine = false; | ||
356 | this_request->protocol = SCIC_NO_PROTOCOL; | ||
357 | this_request->saved_rx_frame_index = SCU_INVALID_FRAME_INDEX; | ||
358 | this_request->device_sequence = scic_sds_remote_device_get_sequence(the_target); | ||
359 | |||
360 | this_request->sci_status = SCI_SUCCESS; | ||
361 | this_request->scu_status = 0; | ||
362 | this_request->post_context = 0xFFFFFFFF; | ||
363 | |||
364 | this_request->is_task_management_request = false; | ||
365 | |||
366 | if (io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { | ||
367 | this_request->was_tag_assigned_by_user = false; | ||
368 | this_request->task_context_buffer = NULL; | ||
369 | } else { | ||
370 | this_request->was_tag_assigned_by_user = true; | ||
371 | |||
372 | this_request->task_context_buffer = | ||
373 | scic_sds_controller_get_task_context_buffer( | ||
374 | this_request->owning_controller, io_tag); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * This method build the remainder of the IO request object. | ||
380 | * @this_request: This parameter specifies the request object being constructed. | ||
381 | * | ||
382 | * The scic_sds_general_request_construct() must be called before this call is | ||
383 | * valid. none | ||
384 | */ | ||
385 | static void scic_sds_ssp_io_request_assign_buffers( | ||
386 | struct scic_sds_request *this_request) | ||
387 | { | ||
388 | this_request->command_buffer = | ||
389 | scic_sds_ssp_request_get_command_buffer(this_request); | ||
390 | this_request->response_buffer = | ||
391 | scic_sds_ssp_request_get_response_buffer(this_request); | ||
392 | this_request->sgl_element_pair_buffer = | ||
393 | scic_sds_ssp_request_get_sgl_element_buffer(this_request); | ||
394 | this_request->sgl_element_pair_buffer = | ||
395 | scic_sds_request_align_sgl_element_buffer(this_request->sgl_element_pair_buffer); | ||
396 | |||
397 | if (this_request->was_tag_assigned_by_user == false) { | ||
398 | this_request->task_context_buffer = | ||
399 | scic_sds_ssp_request_get_task_context_buffer(this_request); | ||
400 | this_request->task_context_buffer = | ||
401 | scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * This method constructs the SSP Command IU data for this io request object. | ||
407 | * @this_request: This parameter specifies the request object for which the SSP | ||
408 | * command information unit is being built. | ||
409 | * | ||
410 | */ | ||
411 | static void scic_sds_io_request_build_ssp_command_iu( | ||
412 | struct scic_sds_request *this_request) | ||
413 | { | ||
414 | struct sci_ssp_command_iu *command_frame; | ||
415 | void *os_handle; | ||
416 | u32 cdb_length; | ||
417 | u32 *cdb_buffer; | ||
418 | |||
419 | command_frame = | ||
420 | (struct sci_ssp_command_iu *)this_request->command_buffer; | ||
421 | |||
422 | os_handle = scic_sds_request_get_user_request(this_request); | ||
423 | |||
424 | command_frame->lun_upper = 0; | ||
425 | command_frame->lun_lower = scic_cb_ssp_io_request_get_lun(os_handle); | ||
426 | |||
427 | ((u32 *)command_frame)[2] = 0; | ||
428 | |||
429 | cdb_length = scic_cb_ssp_io_request_get_cdb_length(os_handle); | ||
430 | cdb_buffer = (u32 *)scic_cb_ssp_io_request_get_cdb_address(os_handle); | ||
431 | |||
432 | if (cdb_length > 16) { | ||
433 | command_frame->additional_cdb_length = cdb_length - 16; | ||
434 | } | ||
435 | |||
436 | /* / @todo Is it ok to leave junk at the end of the cdb buffer? */ | ||
437 | scic_word_copy_with_swap( | ||
438 | (u32 *)(&command_frame->cdb), | ||
439 | (u32 *)(cdb_buffer), | ||
440 | (cdb_length + 3) / sizeof(u32) | ||
441 | ); | ||
442 | |||
443 | command_frame->enable_first_burst = 0; | ||
444 | command_frame->task_priority = | ||
445 | scic_cb_ssp_io_request_get_command_priority(os_handle); | ||
446 | command_frame->task_attribute = | ||
447 | scic_cb_ssp_io_request_get_task_attribute(os_handle); | ||
448 | } | ||
449 | |||
450 | |||
451 | /** | ||
452 | * This method constructs the SSP Task IU data for this io request object. | ||
453 | * @this_request: | ||
454 | * | ||
455 | */ | ||
456 | static void scic_sds_task_request_build_ssp_task_iu( | ||
457 | struct scic_sds_request *this_request) | ||
458 | { | ||
459 | struct sci_ssp_task_iu *command_frame; | ||
460 | void *os_handle; | ||
461 | |||
462 | command_frame = | ||
463 | (struct sci_ssp_task_iu *)this_request->command_buffer; | ||
464 | |||
465 | os_handle = scic_sds_request_get_user_request(this_request); | ||
466 | |||
467 | command_frame->lun_upper = 0; | ||
468 | command_frame->lun_lower = scic_cb_ssp_task_request_get_lun(os_handle); | ||
469 | |||
470 | ((u32 *)command_frame)[2] = 0; | ||
471 | |||
472 | command_frame->task_function = | ||
473 | scic_cb_ssp_task_request_get_function(os_handle); | ||
474 | command_frame->task_tag = | ||
475 | scic_cb_ssp_task_request_get_io_tag_to_manage(os_handle); | ||
476 | } | ||
477 | |||
478 | |||
479 | /** | ||
480 | * This method is will fill in the SCU Task Context for any type of SSP request. | ||
481 | * @this_request: | ||
482 | * @task_context: | ||
483 | * | ||
484 | */ | ||
485 | static void scu_ssp_reqeust_construct_task_context( | ||
486 | struct scic_sds_request *this_request, | ||
487 | struct scu_task_context *task_context) | ||
488 | { | ||
489 | dma_addr_t physical_address; | ||
490 | struct scic_sds_controller *owning_controller; | ||
491 | struct scic_sds_remote_device *target_device; | ||
492 | struct scic_sds_port *target_port; | ||
493 | |||
494 | owning_controller = scic_sds_request_get_controller(this_request); | ||
495 | target_device = scic_sds_request_get_device(this_request); | ||
496 | target_port = scic_sds_request_get_port(this_request); | ||
497 | |||
498 | /* Fill in the TC with the its required data */ | ||
499 | task_context->abort = 0; | ||
500 | task_context->priority = 0; | ||
501 | task_context->initiator_request = 1; | ||
502 | task_context->connection_rate = | ||
503 | scic_remote_device_get_connection_rate(target_device); | ||
504 | task_context->protocol_engine_index = | ||
505 | scic_sds_controller_get_protocol_engine_group(owning_controller); | ||
506 | task_context->logical_port_index = | ||
507 | scic_sds_port_get_index(target_port); | ||
508 | task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP; | ||
509 | task_context->valid = SCU_TASK_CONTEXT_VALID; | ||
510 | task_context->context_type = SCU_TASK_CONTEXT_TYPE; | ||
511 | |||
512 | task_context->remote_node_index = | ||
513 | scic_sds_remote_device_get_index(this_request->target_device); | ||
514 | task_context->command_code = 0; | ||
515 | |||
516 | task_context->link_layer_control = 0; | ||
517 | task_context->do_not_dma_ssp_good_response = 1; | ||
518 | task_context->strict_ordering = 0; | ||
519 | task_context->control_frame = 0; | ||
520 | task_context->timeout_enable = 0; | ||
521 | task_context->block_guard_enable = 0; | ||
522 | |||
523 | task_context->address_modifier = 0; | ||
524 | |||
525 | /* task_context->type.ssp.tag = this_request->io_tag; */ | ||
526 | task_context->task_phase = 0x01; | ||
527 | |||
528 | if (this_request->was_tag_assigned_by_user) { | ||
529 | /* Build the task context now since we have already read the data */ | ||
530 | this_request->post_context = ( | ||
531 | SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ||
532 | | ( | ||
533 | scic_sds_controller_get_protocol_engine_group(owning_controller) | ||
534 | << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT | ||
535 | ) | ||
536 | | ( | ||
537 | scic_sds_port_get_index(target_port) | ||
538 | << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ||
539 | ) | ||
540 | | scic_sds_io_tag_get_index(this_request->io_tag) | ||
541 | ); | ||
542 | } else { | ||
543 | /* Build the task context now since we have already read the data */ | ||
544 | this_request->post_context = ( | ||
545 | SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ||
546 | | ( | ||
547 | scic_sds_controller_get_protocol_engine_group(owning_controller) | ||
548 | << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT | ||
549 | ) | ||
550 | | ( | ||
551 | scic_sds_port_get_index(target_port) | ||
552 | << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ||
553 | ) | ||
554 | /* This is not assigned because we have to wait until we get a TCi */ | ||
555 | ); | ||
556 | } | ||
557 | |||
558 | /* Copy the physical address for the command buffer to the SCU Task Context */ | ||
559 | scic_cb_io_request_get_physical_address( | ||
560 | scic_sds_request_get_controller(this_request), | ||
561 | this_request, | ||
562 | this_request->command_buffer, | ||
563 | &physical_address | ||
564 | ); | ||
565 | |||
566 | task_context->command_iu_upper = | ||
567 | upper_32_bits(physical_address); | ||
568 | task_context->command_iu_lower = | ||
569 | lower_32_bits(physical_address); | ||
570 | |||
571 | /* Copy the physical address for the response buffer to the SCU Task Context */ | ||
572 | scic_cb_io_request_get_physical_address( | ||
573 | scic_sds_request_get_controller(this_request), | ||
574 | this_request, | ||
575 | this_request->response_buffer, | ||
576 | &physical_address | ||
577 | ); | ||
578 | |||
579 | task_context->response_iu_upper = | ||
580 | upper_32_bits(physical_address); | ||
581 | task_context->response_iu_lower = | ||
582 | lower_32_bits(physical_address); | ||
583 | } | ||
584 | |||
585 | /** | ||
586 | * This method is will fill in the SCU Task Context for a SSP IO request. | ||
587 | * @this_request: | ||
588 | * | ||
589 | */ | ||
590 | static void scu_ssp_io_request_construct_task_context( | ||
591 | struct scic_sds_request *this_request, | ||
592 | SCI_IO_REQUEST_DATA_DIRECTION data_direction, | ||
593 | u32 transfer_length_bytes) | ||
594 | { | ||
595 | struct scu_task_context *task_context; | ||
596 | |||
597 | task_context = scic_sds_request_get_task_context(this_request); | ||
598 | |||
599 | scu_ssp_reqeust_construct_task_context(this_request, task_context); | ||
600 | |||
601 | task_context->ssp_command_iu_length = sizeof(struct sci_ssp_command_iu) / sizeof(u32); | ||
602 | task_context->type.ssp.frame_type = SCI_SAS_COMMAND_FRAME; | ||
603 | |||
604 | switch (data_direction) { | ||
605 | case SCI_IO_REQUEST_DATA_IN: | ||
606 | case SCI_IO_REQUEST_NO_DATA: | ||
607 | task_context->task_type = SCU_TASK_TYPE_IOREAD; | ||
608 | break; | ||
609 | case SCI_IO_REQUEST_DATA_OUT: | ||
610 | task_context->task_type = SCU_TASK_TYPE_IOWRITE; | ||
611 | break; | ||
612 | } | ||
613 | |||
614 | task_context->transfer_length_bytes = transfer_length_bytes; | ||
615 | |||
616 | if (task_context->transfer_length_bytes > 0) { | ||
617 | scic_sds_request_build_sgl(this_request); | ||
618 | } | ||
619 | } | ||
620 | |||
621 | |||
622 | /** | ||
623 | * This method will fill in the remainder of the io request object for SSP Task | ||
624 | * requests. | ||
625 | * @this_request: | ||
626 | * | ||
627 | */ | ||
628 | static void scic_sds_ssp_task_request_assign_buffers( | ||
629 | struct scic_sds_request *this_request) | ||
630 | { | ||
631 | /* Assign all of the buffer pointers */ | ||
632 | this_request->command_buffer = | ||
633 | scic_sds_ssp_task_request_get_command_buffer(this_request); | ||
634 | this_request->response_buffer = | ||
635 | scic_sds_ssp_task_request_get_response_buffer(this_request); | ||
636 | this_request->sgl_element_pair_buffer = NULL; | ||
637 | |||
638 | if (this_request->was_tag_assigned_by_user == false) { | ||
639 | this_request->task_context_buffer = | ||
640 | scic_sds_ssp_task_request_get_task_context_buffer(this_request); | ||
641 | this_request->task_context_buffer = | ||
642 | scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); | ||
643 | } | ||
644 | } | ||
645 | |||
646 | /** | ||
647 | * This method will fill in the SCU Task Context for a SSP Task request. The | ||
648 | * following important settings are utilized: -# priority == | ||
649 | * SCU_TASK_PRIORITY_HIGH. This ensures that the task request is issued | ||
650 | * ahead of other task destined for the same Remote Node. -# task_type == | ||
651 | * SCU_TASK_TYPE_IOREAD. This simply indicates that a normal request type | ||
652 | * (i.e. non-raw frame) is being utilized to perform task management. -# | ||
653 | * control_frame == 1. This ensures that the proper endianess is set so | ||
654 | * that the bytes are transmitted in the right order for a task frame. | ||
655 | * @this_request: This parameter specifies the task request object being | ||
656 | * constructed. | ||
657 | * | ||
658 | */ | ||
659 | static void scu_ssp_task_request_construct_task_context( | ||
660 | struct scic_sds_request *this_request) | ||
661 | { | ||
662 | struct scu_task_context *task_context; | ||
663 | |||
664 | task_context = scic_sds_request_get_task_context(this_request); | ||
665 | |||
666 | scu_ssp_reqeust_construct_task_context(this_request, task_context); | ||
667 | |||
668 | task_context->control_frame = 1; | ||
669 | task_context->priority = SCU_TASK_PRIORITY_HIGH; | ||
670 | task_context->task_type = SCU_TASK_TYPE_RAW_FRAME; | ||
671 | task_context->transfer_length_bytes = 0; | ||
672 | task_context->type.ssp.frame_type = SCI_SAS_TASK_FRAME; | ||
673 | task_context->ssp_command_iu_length = sizeof(struct sci_ssp_task_iu) / sizeof(u32); | ||
674 | } | ||
675 | |||
676 | |||
677 | /** | ||
678 | * This method constructs the SSP Command IU data for this ssp passthrough | ||
679 | * comand request object. | ||
680 | * @this_request: This parameter specifies the request object for which the SSP | ||
681 | * command information unit is being built. | ||
682 | * | ||
683 | * enum sci_status, returns invalid parameter is cdb > 16 | ||
684 | */ | ||
685 | |||
686 | |||
687 | /** | ||
688 | * This method constructs the SATA request object. | ||
689 | * @this_request: | ||
690 | * @sat_protocol: | ||
691 | * @transfer_length: | ||
692 | * @data_direction: | ||
693 | * @copy_rx_frame: | ||
694 | * | ||
695 | * enum sci_status | ||
696 | */ | ||
697 | static enum sci_status scic_io_request_construct_sata( | ||
698 | struct scic_sds_request *this_request, | ||
699 | u8 sat_protocol, | ||
700 | u32 transfer_length, | ||
701 | SCI_IO_REQUEST_DATA_DIRECTION data_direction, | ||
702 | bool copy_rx_frame) | ||
703 | { | ||
704 | enum sci_status status = SCI_SUCCESS; | ||
705 | |||
706 | switch (sat_protocol) { | ||
707 | case SAT_PROTOCOL_PIO_DATA_IN: | ||
708 | case SAT_PROTOCOL_PIO_DATA_OUT: | ||
709 | status = scic_sds_stp_pio_request_construct(this_request, sat_protocol, copy_rx_frame); | ||
710 | break; | ||
711 | |||
712 | case SAT_PROTOCOL_UDMA_DATA_IN: | ||
713 | case SAT_PROTOCOL_UDMA_DATA_OUT: | ||
714 | status = scic_sds_stp_udma_request_construct(this_request, transfer_length, data_direction); | ||
715 | break; | ||
716 | |||
717 | case SAT_PROTOCOL_ATA_HARD_RESET: | ||
718 | case SAT_PROTOCOL_SOFT_RESET: | ||
719 | status = scic_sds_stp_soft_reset_request_construct(this_request); | ||
720 | break; | ||
721 | |||
722 | case SAT_PROTOCOL_NON_DATA: | ||
723 | status = scic_sds_stp_non_data_request_construct(this_request); | ||
724 | break; | ||
725 | |||
726 | case SAT_PROTOCOL_FPDMA: | ||
727 | status = scic_sds_stp_ncq_request_construct(this_request, transfer_length, data_direction); | ||
728 | break; | ||
729 | |||
730 | #if !defined(DISABLE_ATAPI) | ||
731 | case SAT_PROTOCOL_PACKET_NON_DATA: | ||
732 | case SAT_PROTOCOL_PACKET_DMA_DATA_IN: | ||
733 | case SAT_PROTOCOL_PACKET_DMA_DATA_OUT: | ||
734 | case SAT_PROTOCOL_PACKET_PIO_DATA_IN: | ||
735 | case SAT_PROTOCOL_PACKET_PIO_DATA_OUT: | ||
736 | status = scic_sds_stp_packet_request_construct(this_request); | ||
737 | break; | ||
738 | #endif | ||
739 | |||
740 | case SAT_PROTOCOL_DMA_QUEUED: | ||
741 | case SAT_PROTOCOL_DMA: | ||
742 | case SAT_PROTOCOL_DEVICE_DIAGNOSTIC: | ||
743 | case SAT_PROTOCOL_DEVICE_RESET: | ||
744 | case SAT_PROTOCOL_RETURN_RESPONSE_INFO: | ||
745 | default: | ||
746 | dev_err(scic_to_dev(this_request->owning_controller), | ||
747 | "%s: SCIC IO Request 0x%p received un-handled " | ||
748 | "SAT Protocl %d.\n", | ||
749 | __func__, this_request, sat_protocol); | ||
750 | |||
751 | status = SCI_FAILURE; | ||
752 | break; | ||
753 | } | ||
754 | |||
755 | return status; | ||
756 | } | ||
757 | |||
758 | /* | ||
759 | * **************************************************************************** | ||
760 | * * SCIC Interface Implementation | ||
761 | * **************************************************************************** */ | ||
762 | |||
763 | |||
764 | |||
765 | |||
766 | /* --------------------------------------------------------------------------- */ | ||
767 | |||
768 | u32 scic_io_request_get_object_size(void) | ||
769 | { | ||
770 | u32 ssp_request_size; | ||
771 | u32 stp_request_size; | ||
772 | u32 smp_request_size; | ||
773 | |||
774 | ssp_request_size = scic_sds_ssp_request_get_object_size(); | ||
775 | stp_request_size = scic_sds_stp_request_get_object_size(); | ||
776 | smp_request_size = scic_sds_smp_request_get_object_size(); | ||
777 | |||
778 | return max(ssp_request_size, max(stp_request_size, smp_request_size)); | ||
779 | } | ||
780 | |||
781 | /* --------------------------------------------------------------------------- */ | ||
782 | |||
783 | |||
784 | /* --------------------------------------------------------------------------- */ | ||
785 | |||
786 | |||
787 | /* --------------------------------------------------------------------------- */ | ||
788 | |||
789 | |||
790 | /* --------------------------------------------------------------------------- */ | ||
791 | |||
792 | enum sci_status scic_io_request_construct( | ||
793 | struct scic_sds_controller *scic_controller, | ||
794 | struct scic_sds_remote_device *scic_remote_device, | ||
795 | u16 io_tag, | ||
796 | void *user_io_request_object, | ||
797 | void *scic_io_request_memory, | ||
798 | struct scic_sds_request **new_scic_io_request_handle) | ||
799 | { | ||
800 | enum sci_status status = SCI_SUCCESS; | ||
801 | struct scic_sds_request *this_request; | ||
802 | struct smp_discover_response_protocols device_protocol; | ||
803 | |||
804 | this_request = (struct scic_sds_request *)scic_io_request_memory; | ||
805 | |||
806 | /* Build the common part of the request */ | ||
807 | scic_sds_general_request_construct( | ||
808 | (struct scic_sds_controller *)scic_controller, | ||
809 | (struct scic_sds_remote_device *)scic_remote_device, | ||
810 | io_tag, | ||
811 | user_io_request_object, | ||
812 | this_request | ||
813 | ); | ||
814 | |||
815 | if ( | ||
816 | scic_sds_remote_device_get_index((struct scic_sds_remote_device *)scic_remote_device) | ||
817 | == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX | ||
818 | ) { | ||
819 | return SCI_FAILURE_INVALID_REMOTE_DEVICE; | ||
820 | } | ||
821 | |||
822 | scic_remote_device_get_protocols(scic_remote_device, &device_protocol); | ||
823 | |||
824 | if (device_protocol.u.bits.attached_ssp_target) { | ||
825 | scic_sds_ssp_io_request_assign_buffers(this_request); | ||
826 | } else if (device_protocol.u.bits.attached_stp_target) { | ||
827 | scic_sds_stp_request_assign_buffers(this_request); | ||
828 | memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); | ||
829 | } else if (device_protocol.u.bits.attached_smp_target) { | ||
830 | scic_sds_smp_request_assign_buffers(this_request); | ||
831 | memset(this_request->command_buffer, 0, sizeof(struct smp_request)); | ||
832 | } else { | ||
833 | status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | ||
834 | } | ||
835 | |||
836 | if (status == SCI_SUCCESS) { | ||
837 | memset( | ||
838 | this_request->task_context_buffer, | ||
839 | 0, | ||
840 | SCI_FIELD_OFFSET(struct scu_task_context, sgl_pair_ab) | ||
841 | ); | ||
842 | *new_scic_io_request_handle = scic_io_request_memory; | ||
843 | } | ||
844 | |||
845 | return status; | ||
846 | } | ||
847 | |||
848 | /* --------------------------------------------------------------------------- */ | ||
849 | |||
850 | |||
851 | enum sci_status scic_task_request_construct( | ||
852 | struct scic_sds_controller *controller, | ||
853 | struct scic_sds_remote_device *remote_device, | ||
854 | u16 io_tag, | ||
855 | void *user_io_request_object, | ||
856 | void *scic_task_request_memory, | ||
857 | struct scic_sds_request **new_scic_task_request_handle) | ||
858 | { | ||
859 | enum sci_status status = SCI_SUCCESS; | ||
860 | struct scic_sds_request *this_request = (struct scic_sds_request *) | ||
861 | scic_task_request_memory; | ||
862 | struct smp_discover_response_protocols device_protocol; | ||
863 | |||
864 | /* Build the common part of the request */ | ||
865 | scic_sds_general_request_construct( | ||
866 | (struct scic_sds_controller *)controller, | ||
867 | (struct scic_sds_remote_device *)remote_device, | ||
868 | io_tag, | ||
869 | user_io_request_object, | ||
870 | this_request | ||
871 | ); | ||
872 | |||
873 | scic_remote_device_get_protocols(remote_device, &device_protocol); | ||
874 | |||
875 | if (device_protocol.u.bits.attached_ssp_target) { | ||
876 | scic_sds_ssp_task_request_assign_buffers(this_request); | ||
877 | |||
878 | this_request->has_started_substate_machine = true; | ||
879 | |||
880 | /* Construct the started sub-state machine. */ | ||
881 | sci_base_state_machine_construct( | ||
882 | &this_request->started_substate_machine, | ||
883 | &this_request->parent.parent, | ||
884 | scic_sds_io_request_started_task_mgmt_substate_table, | ||
885 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION | ||
886 | ); | ||
887 | } else if (device_protocol.u.bits.attached_stp_target) { | ||
888 | scic_sds_stp_request_assign_buffers(this_request); | ||
889 | } else { | ||
890 | status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | ||
891 | } | ||
892 | |||
893 | if (status == SCI_SUCCESS) { | ||
894 | this_request->is_task_management_request = true; | ||
895 | memset(this_request->task_context_buffer, 0x00, sizeof(struct scu_task_context)); | ||
896 | *new_scic_task_request_handle = scic_task_request_memory; | ||
897 | } | ||
898 | |||
899 | return status; | ||
900 | } | ||
901 | |||
902 | |||
903 | enum sci_status scic_io_request_construct_basic_ssp( | ||
904 | struct scic_sds_request *sci_req) | ||
905 | { | ||
906 | void *os_handle; | ||
907 | |||
908 | sci_req->protocol = SCIC_SSP_PROTOCOL; | ||
909 | |||
910 | os_handle = scic_sds_request_get_user_request(sci_req); | ||
911 | |||
912 | scu_ssp_io_request_construct_task_context( | ||
913 | sci_req, | ||
914 | scic_cb_io_request_get_data_direction(os_handle), | ||
915 | scic_cb_io_request_get_transfer_length(os_handle) | ||
916 | ); | ||
917 | |||
918 | |||
919 | scic_sds_io_request_build_ssp_command_iu(sci_req); | ||
920 | |||
921 | sci_base_state_machine_change_state( | ||
922 | &sci_req->parent.state_machine, | ||
923 | SCI_BASE_REQUEST_STATE_CONSTRUCTED | ||
924 | ); | ||
925 | |||
926 | return SCI_SUCCESS; | ||
927 | } | ||
928 | |||
929 | |||
930 | enum sci_status scic_task_request_construct_ssp( | ||
931 | struct scic_sds_request *sci_req) | ||
932 | { | ||
933 | /* Construct the SSP Task SCU Task Context */ | ||
934 | scu_ssp_task_request_construct_task_context(sci_req); | ||
935 | |||
936 | /* Fill in the SSP Task IU */ | ||
937 | scic_sds_task_request_build_ssp_task_iu(sci_req); | ||
938 | |||
939 | sci_base_state_machine_change_state( | ||
940 | &sci_req->parent.state_machine, | ||
941 | SCI_BASE_REQUEST_STATE_CONSTRUCTED | ||
942 | ); | ||
943 | |||
944 | return SCI_SUCCESS; | ||
945 | } | ||
946 | |||
947 | |||
948 | enum sci_status scic_io_request_construct_basic_sata( | ||
949 | struct scic_sds_request *sci_req) | ||
950 | { | ||
951 | enum sci_status status; | ||
952 | struct scic_sds_stp_request *this_stp_request; | ||
953 | u8 sat_protocol; | ||
954 | u32 transfer_length; | ||
955 | SCI_IO_REQUEST_DATA_DIRECTION data_direction; | ||
956 | bool copy_rx_frame = false; | ||
957 | |||
958 | this_stp_request = (struct scic_sds_stp_request *)sci_req; | ||
959 | |||
960 | sci_req->protocol = SCIC_STP_PROTOCOL; | ||
961 | |||
962 | transfer_length = | ||
963 | scic_cb_io_request_get_transfer_length(sci_req->user_request); | ||
964 | data_direction = | ||
965 | scic_cb_io_request_get_data_direction(sci_req->user_request); | ||
966 | |||
967 | sat_protocol = scic_cb_request_get_sat_protocol(sci_req->user_request); | ||
968 | copy_rx_frame = scic_cb_io_request_do_copy_rx_frames(this_stp_request->parent.user_request); | ||
969 | |||
970 | status = scic_io_request_construct_sata( | ||
971 | sci_req, | ||
972 | sat_protocol, | ||
973 | transfer_length, | ||
974 | data_direction, | ||
975 | copy_rx_frame | ||
976 | ); | ||
977 | |||
978 | if (status == SCI_SUCCESS) | ||
979 | sci_base_state_machine_change_state( | ||
980 | &sci_req->parent.state_machine, | ||
981 | SCI_BASE_REQUEST_STATE_CONSTRUCTED | ||
982 | ); | ||
983 | |||
984 | return status; | ||
985 | } | ||
986 | |||
987 | |||
988 | enum sci_status scic_task_request_construct_sata( | ||
989 | struct scic_sds_request *sci_req) | ||
990 | { | ||
991 | enum sci_status status; | ||
992 | u8 sat_protocol = scic_cb_request_get_sat_protocol(sci_req->user_request); | ||
993 | |||
994 | switch (sat_protocol) { | ||
995 | case SAT_PROTOCOL_ATA_HARD_RESET: | ||
996 | case SAT_PROTOCOL_SOFT_RESET: | ||
997 | status = scic_sds_stp_soft_reset_request_construct(sci_req); | ||
998 | break; | ||
999 | |||
1000 | default: | ||
1001 | dev_err(scic_to_dev(sci_req->owning_controller), | ||
1002 | "%s: SCIC IO Request 0x%p received un-handled SAT " | ||
1003 | "Protocl %d.\n", | ||
1004 | __func__, | ||
1005 | sci_req, | ||
1006 | sat_protocol); | ||
1007 | |||
1008 | status = SCI_FAILURE; | ||
1009 | break; | ||
1010 | } | ||
1011 | |||
1012 | if (status == SCI_SUCCESS) | ||
1013 | sci_base_state_machine_change_state( | ||
1014 | &sci_req->parent.state_machine, | ||
1015 | SCI_BASE_REQUEST_STATE_CONSTRUCTED | ||
1016 | ); | ||
1017 | |||
1018 | return status; | ||
1019 | } | ||
1020 | |||
1021 | |||
1022 | u16 scic_io_request_get_io_tag( | ||
1023 | struct scic_sds_request *sci_req) | ||
1024 | { | ||
1025 | return sci_req->io_tag; | ||
1026 | } | ||
1027 | |||
1028 | |||
1029 | u32 scic_request_get_controller_status( | ||
1030 | struct scic_sds_request *sci_req) | ||
1031 | { | ||
1032 | return sci_req->scu_status; | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | void *scic_io_request_get_command_iu_address( | ||
1037 | struct scic_sds_request *sci_req) | ||
1038 | { | ||
1039 | return sci_req->command_buffer; | ||
1040 | } | ||
1041 | |||
1042 | |||
1043 | void *scic_io_request_get_response_iu_address( | ||
1044 | struct scic_sds_request *sci_req) | ||
1045 | { | ||
1046 | return sci_req->response_buffer; | ||
1047 | } | ||
1048 | |||
1049 | |||
1050 | #define SCU_TASK_CONTEXT_SRAM 0x200000 | ||
1051 | u32 scic_io_request_get_number_of_bytes_transferred( | ||
1052 | struct scic_sds_request *scic_sds_request) | ||
1053 | { | ||
1054 | u32 ret_val = 0; | ||
1055 | |||
1056 | if (SMU_AMR_READ(scic_sds_request->owning_controller) == 0) { | ||
1057 | /* | ||
1058 | * get the bytes of data from the Address == BAR1 + 20002Ch + (256*TCi) where | ||
1059 | * BAR1 is the scu_registers | ||
1060 | * 0x20002C = 0x200000 + 0x2c | ||
1061 | * = start of task context SRAM + offset of (type.ssp.data_offset) | ||
1062 | * TCi is the io_tag of struct scic_sds_request */ | ||
1063 | ret_val = scic_sds_pci_read_scu_dword( | ||
1064 | scic_sds_request->owning_controller, | ||
1065 | ( | ||
1066 | (u8 *)scic_sds_request->owning_controller->scu_registers + | ||
1067 | (SCU_TASK_CONTEXT_SRAM + SCI_FIELD_OFFSET(struct scu_task_context, type.ssp.data_offset)) + | ||
1068 | ((sizeof(struct scu_task_context)) * scic_sds_io_tag_get_index(scic_sds_request->io_tag)) | ||
1069 | ) | ||
1070 | ); | ||
1071 | } | ||
1072 | |||
1073 | return ret_val; | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /* | ||
1078 | * **************************************************************************** | ||
1079 | * * SCIC SDS Interface Implementation | ||
1080 | * **************************************************************************** */ | ||
1081 | |||
1082 | /** | ||
1083 | * | ||
1084 | * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start | ||
1085 | * operation is to be executed. | ||
1086 | * | ||
1087 | * This method invokes the base state start request handler for the | ||
1088 | * SCIC_SDS_IO_REQUEST_T object. enum sci_status | ||
1089 | */ | ||
1090 | enum sci_status scic_sds_request_start( | ||
1091 | struct scic_sds_request *this_request) | ||
1092 | { | ||
1093 | if ( | ||
1094 | this_request->device_sequence | ||
1095 | == scic_sds_remote_device_get_sequence(this_request->target_device) | ||
1096 | ) { | ||
1097 | return this_request->state_handlers->parent.start_handler( | ||
1098 | &this_request->parent | ||
1099 | ); | ||
1100 | } | ||
1101 | |||
1102 | return SCI_FAILURE; | ||
1103 | } | ||
1104 | |||
1105 | /** | ||
1106 | * | ||
1107 | * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start | ||
1108 | * operation is to be executed. | ||
1109 | * | ||
1110 | * This method invokes the base state terminate request handber for the | ||
1111 | * SCIC_SDS_IO_REQUEST_T object. enum sci_status | ||
1112 | */ | ||
1113 | enum sci_status scic_sds_io_request_terminate( | ||
1114 | struct scic_sds_request *this_request) | ||
1115 | { | ||
1116 | return this_request->state_handlers->parent.abort_handler( | ||
1117 | &this_request->parent); | ||
1118 | } | ||
1119 | |||
1120 | /** | ||
1121 | * | ||
1122 | * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start | ||
1123 | * operation is to be executed. | ||
1124 | * | ||
1125 | * This method invokes the base state request completion handler for the | ||
1126 | * SCIC_SDS_IO_REQUEST_T object. enum sci_status | ||
1127 | */ | ||
1128 | enum sci_status scic_sds_io_request_complete( | ||
1129 | struct scic_sds_request *this_request) | ||
1130 | { | ||
1131 | return this_request->state_handlers->parent.complete_handler( | ||
1132 | &this_request->parent); | ||
1133 | } | ||
1134 | |||
1135 | /** | ||
1136 | * | ||
1137 | * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start | ||
1138 | * operation is to be executed. | ||
1139 | * @event_code: The event code returned by the hardware for the task reqeust. | ||
1140 | * | ||
1141 | * This method invokes the core state handler for the SCIC_SDS_IO_REQUEST_T | ||
1142 | * object. enum sci_status | ||
1143 | */ | ||
1144 | enum sci_status scic_sds_io_request_event_handler( | ||
1145 | struct scic_sds_request *this_request, | ||
1146 | u32 event_code) | ||
1147 | { | ||
1148 | return this_request->state_handlers->event_handler(this_request, event_code); | ||
1149 | } | ||
1150 | |||
1151 | /** | ||
1152 | * | ||
1153 | * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the start | ||
1154 | * operation is to be executed. | ||
1155 | * @frame_index: The frame index returned by the hardware for the reqeust | ||
1156 | * object. | ||
1157 | * | ||
1158 | * This method invokes the core state frame handler for the | ||
1159 | * SCIC_SDS_IO_REQUEST_T object. enum sci_status | ||
1160 | */ | ||
1161 | enum sci_status scic_sds_io_request_frame_handler( | ||
1162 | struct scic_sds_request *this_request, | ||
1163 | u32 frame_index) | ||
1164 | { | ||
1165 | return this_request->state_handlers->frame_handler(this_request, frame_index); | ||
1166 | } | ||
1167 | |||
1168 | /** | ||
1169 | * | ||
1170 | * @this_request: The SCIC_SDS_IO_REQUEST_T object for which the task start | ||
1171 | * operation is to be executed. | ||
1172 | * | ||
1173 | * This method invokes the core state task complete handler for the | ||
1174 | * SCIC_SDS_IO_REQUEST_T object. enum sci_status | ||
1175 | */ | ||
1176 | |||
1177 | /* | ||
1178 | * **************************************************************************** | ||
1179 | * * SCIC SDS PROTECTED METHODS | ||
1180 | * **************************************************************************** */ | ||
1181 | |||
1182 | /** | ||
1183 | * This method copies response data for requests returning response data | ||
1184 | * instead of sense data. | ||
1185 | * @this_request: This parameter specifies the request object for which to copy | ||
1186 | * the response data. | ||
1187 | * | ||
1188 | */ | ||
1189 | void scic_sds_io_request_copy_response( | ||
1190 | struct scic_sds_request *this_request) | ||
1191 | { | ||
1192 | void *response_buffer; | ||
1193 | u32 user_response_length; | ||
1194 | u32 core_response_length; | ||
1195 | struct sci_ssp_response_iu *ssp_response; | ||
1196 | |||
1197 | ssp_response = (struct sci_ssp_response_iu *)this_request->response_buffer; | ||
1198 | |||
1199 | response_buffer = scic_cb_ssp_task_request_get_response_data_address( | ||
1200 | this_request->user_request | ||
1201 | ); | ||
1202 | |||
1203 | user_response_length = scic_cb_ssp_task_request_get_response_data_length( | ||
1204 | this_request->user_request | ||
1205 | ); | ||
1206 | |||
1207 | core_response_length = sci_ssp_get_response_data_length( | ||
1208 | ssp_response->response_data_length | ||
1209 | ); | ||
1210 | |||
1211 | user_response_length = min(user_response_length, core_response_length); | ||
1212 | |||
1213 | memcpy(response_buffer, ssp_response->data, user_response_length); | ||
1214 | } | ||
1215 | |||
1216 | /* | ||
1217 | * ***************************************************************************** | ||
1218 | * * DEFAULT STATE HANDLERS | ||
1219 | * ***************************************************************************** */ | ||
1220 | |||
1221 | /** | ||
1222 | * scic_sds_request_default_start_handler() - | ||
1223 | * @request: This is the struct sci_base_request object that is cast to the | ||
1224 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1225 | * | ||
1226 | * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T | ||
1227 | * object receives a scic_sds_request_start() request. The default action is | ||
1228 | * to log a warning and return a failure status. enum sci_status | ||
1229 | * SCI_FAILURE_INVALID_STATE | ||
1230 | */ | ||
1231 | enum sci_status scic_sds_request_default_start_handler( | ||
1232 | struct sci_base_request *request) | ||
1233 | { | ||
1234 | struct scic_sds_request *scic_request = | ||
1235 | (struct scic_sds_request *)request; | ||
1236 | |||
1237 | dev_warn(scic_to_dev(scic_request->owning_controller), | ||
1238 | "%s: SCIC IO Request requested to start while in wrong " | ||
1239 | "state %d\n", | ||
1240 | __func__, | ||
1241 | sci_base_state_machine_get_state( | ||
1242 | &((struct scic_sds_request *)request)->parent.state_machine)); | ||
1243 | |||
1244 | return SCI_FAILURE_INVALID_STATE; | ||
1245 | } | ||
1246 | |||
1247 | static enum sci_status scic_sds_request_default_abort_handler( | ||
1248 | struct sci_base_request *request) | ||
1249 | { | ||
1250 | struct scic_sds_request *scic_request = | ||
1251 | (struct scic_sds_request *)request; | ||
1252 | |||
1253 | dev_warn(scic_to_dev(scic_request->owning_controller), | ||
1254 | "%s: SCIC IO Request requested to abort while in wrong " | ||
1255 | "state %d\n", | ||
1256 | __func__, | ||
1257 | sci_base_state_machine_get_state( | ||
1258 | &((struct scic_sds_request *)request)->parent.state_machine)); | ||
1259 | |||
1260 | return SCI_FAILURE_INVALID_STATE; | ||
1261 | } | ||
1262 | |||
1263 | /** | ||
1264 | * scic_sds_request_default_complete_handler() - | ||
1265 | * @request: This is the struct sci_base_request object that is cast to the | ||
1266 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1267 | * | ||
1268 | * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T | ||
1269 | * object receives a scic_sds_request_complete() request. The default action | ||
1270 | * is to log a warning and return a failure status. enum sci_status | ||
1271 | * SCI_FAILURE_INVALID_STATE | ||
1272 | */ | ||
1273 | enum sci_status scic_sds_request_default_complete_handler( | ||
1274 | struct sci_base_request *request) | ||
1275 | { | ||
1276 | struct scic_sds_request *scic_request = | ||
1277 | (struct scic_sds_request *)request; | ||
1278 | |||
1279 | dev_warn(scic_to_dev(scic_request->owning_controller), | ||
1280 | "%s: SCIC IO Request requested to complete while in wrong " | ||
1281 | "state %d\n", | ||
1282 | __func__, | ||
1283 | sci_base_state_machine_get_state( | ||
1284 | &((struct scic_sds_request *)request)->parent.state_machine)); | ||
1285 | |||
1286 | return SCI_FAILURE_INVALID_STATE; | ||
1287 | } | ||
1288 | |||
1289 | /** | ||
1290 | * scic_sds_request_default_destruct_handler() - | ||
1291 | * @request: This is the struct sci_base_request object that is cast to the | ||
1292 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1293 | * | ||
1294 | * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T | ||
1295 | * object receives a scic_sds_request_complete() request. The default action | ||
1296 | * is to log a warning and return a failure status. enum sci_status | ||
1297 | * SCI_FAILURE_INVALID_STATE | ||
1298 | */ | ||
1299 | enum sci_status scic_sds_request_default_destruct_handler( | ||
1300 | struct sci_base_request *request) | ||
1301 | { | ||
1302 | struct scic_sds_request *scic_request = | ||
1303 | (struct scic_sds_request *)request; | ||
1304 | |||
1305 | dev_warn(scic_to_dev(scic_request->owning_controller), | ||
1306 | "%s: SCIC IO Request requested to destroy while in wrong " | ||
1307 | "state %d\n", | ||
1308 | __func__, | ||
1309 | sci_base_state_machine_get_state( | ||
1310 | &((struct scic_sds_request *)request)->parent.state_machine)); | ||
1311 | |||
1312 | return SCI_FAILURE_INVALID_STATE; | ||
1313 | } | ||
1314 | |||
1315 | /** | ||
1316 | * scic_sds_request_default_tc_completion_handler() - | ||
1317 | * @request: This is the struct sci_base_request object that is cast to the | ||
1318 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1319 | * | ||
1320 | * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T | ||
1321 | * object receives a scic_sds_task_request_complete() request. The default | ||
1322 | * action is to log a warning and return a failure status. enum sci_status | ||
1323 | * SCI_FAILURE_INVALID_STATE | ||
1324 | */ | ||
1325 | enum sci_status scic_sds_request_default_tc_completion_handler( | ||
1326 | struct scic_sds_request *this_request, | ||
1327 | u32 completion_code) | ||
1328 | { | ||
1329 | dev_warn(scic_to_dev(this_request->owning_controller), | ||
1330 | "%s: SCIC IO Request given task completion notification %x " | ||
1331 | "while in wrong state %d\n", | ||
1332 | __func__, | ||
1333 | completion_code, | ||
1334 | sci_base_state_machine_get_state( | ||
1335 | &this_request->parent.state_machine)); | ||
1336 | |||
1337 | return SCI_FAILURE_INVALID_STATE; | ||
1338 | |||
1339 | } | ||
1340 | |||
1341 | /** | ||
1342 | * scic_sds_request_default_event_handler() - | ||
1343 | * @request: This is the struct sci_base_request object that is cast to the | ||
1344 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1345 | * | ||
1346 | * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T | ||
1347 | * object receives a scic_sds_request_event_handler() request. The default | ||
1348 | * action is to log a warning and return a failure status. enum sci_status | ||
1349 | * SCI_FAILURE_INVALID_STATE | ||
1350 | */ | ||
1351 | enum sci_status scic_sds_request_default_event_handler( | ||
1352 | struct scic_sds_request *this_request, | ||
1353 | u32 event_code) | ||
1354 | { | ||
1355 | dev_warn(scic_to_dev(this_request->owning_controller), | ||
1356 | "%s: SCIC IO Request given event code notification %x while " | ||
1357 | "in wrong state %d\n", | ||
1358 | __func__, | ||
1359 | event_code, | ||
1360 | sci_base_state_machine_get_state( | ||
1361 | &this_request->parent.state_machine)); | ||
1362 | |||
1363 | return SCI_FAILURE_INVALID_STATE; | ||
1364 | } | ||
1365 | |||
1366 | /** | ||
1367 | * scic_sds_request_default_frame_handler() - | ||
1368 | * @request: This is the struct sci_base_request object that is cast to the | ||
1369 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1370 | * | ||
1371 | * This method is the default action to take when an SCIC_SDS_IO_REQUEST_T | ||
1372 | * object receives a scic_sds_request_event_handler() request. The default | ||
1373 | * action is to log a warning and return a failure status. enum sci_status | ||
1374 | * SCI_FAILURE_INVALID_STATE | ||
1375 | */ | ||
1376 | enum sci_status scic_sds_request_default_frame_handler( | ||
1377 | struct scic_sds_request *this_request, | ||
1378 | u32 frame_index) | ||
1379 | { | ||
1380 | dev_warn(scic_to_dev(this_request->owning_controller), | ||
1381 | "%s: SCIC IO Request given unexpected frame %x while in " | ||
1382 | "state %d\n", | ||
1383 | __func__, | ||
1384 | frame_index, | ||
1385 | sci_base_state_machine_get_state( | ||
1386 | &this_request->parent.state_machine)); | ||
1387 | |||
1388 | scic_sds_controller_release_frame( | ||
1389 | this_request->owning_controller, frame_index); | ||
1390 | |||
1391 | return SCI_FAILURE_INVALID_STATE; | ||
1392 | } | ||
1393 | |||
1394 | /* | ||
1395 | * ***************************************************************************** | ||
1396 | * * CONSTRUCTED STATE HANDLERS | ||
1397 | * ***************************************************************************** */ | ||
1398 | |||
1399 | /** | ||
1400 | * scic_sds_request_constructed_state_start_handler() - | ||
1401 | * @request: This is the struct sci_base_request object that is cast to the | ||
1402 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1403 | * | ||
1404 | * This method implements the action taken when a constructed | ||
1405 | * SCIC_SDS_IO_REQUEST_T object receives a scic_sds_request_start() request. | ||
1406 | * This method will, if necessary, allocate a TCi for the io request object and | ||
1407 | * then will, if necessary, copy the constructed TC data into the actual TC | ||
1408 | * buffer. If everything is successful the post context field is updated with | ||
1409 | * the TCi so the controller can post the request to the hardware. enum sci_status | ||
1410 | * SCI_SUCCESS SCI_FAILURE_INSUFFICIENT_RESOURCES | ||
1411 | */ | ||
1412 | static enum sci_status scic_sds_request_constructed_state_start_handler( | ||
1413 | struct sci_base_request *request) | ||
1414 | { | ||
1415 | struct scu_task_context *task_context; | ||
1416 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
1417 | |||
1418 | if (this_request->io_tag == SCI_CONTROLLER_INVALID_IO_TAG) { | ||
1419 | this_request->io_tag = | ||
1420 | scic_controller_allocate_io_tag(this_request->owning_controller); | ||
1421 | } | ||
1422 | |||
1423 | /* Record the IO Tag in the request */ | ||
1424 | if (this_request->io_tag != SCI_CONTROLLER_INVALID_IO_TAG) { | ||
1425 | task_context = this_request->task_context_buffer; | ||
1426 | |||
1427 | task_context->task_index = scic_sds_io_tag_get_index(this_request->io_tag); | ||
1428 | |||
1429 | switch (task_context->protocol_type) { | ||
1430 | case SCU_TASK_CONTEXT_PROTOCOL_SMP: | ||
1431 | case SCU_TASK_CONTEXT_PROTOCOL_SSP: | ||
1432 | /* SSP/SMP Frame */ | ||
1433 | task_context->type.ssp.tag = this_request->io_tag; | ||
1434 | task_context->type.ssp.target_port_transfer_tag = 0xFFFF; | ||
1435 | break; | ||
1436 | |||
1437 | case SCU_TASK_CONTEXT_PROTOCOL_STP: | ||
1438 | /* | ||
1439 | * STP/SATA Frame | ||
1440 | * task_context->type.stp.ncq_tag = this_request->ncq_tag; */ | ||
1441 | break; | ||
1442 | |||
1443 | case SCU_TASK_CONTEXT_PROTOCOL_NONE: | ||
1444 | /* / @todo When do we set no protocol type? */ | ||
1445 | break; | ||
1446 | |||
1447 | default: | ||
1448 | /* This should never happen since we build the IO requests */ | ||
1449 | break; | ||
1450 | } | ||
1451 | |||
1452 | /* | ||
1453 | * Check to see if we need to copy the task context buffer | ||
1454 | * or have been building into the task context buffer */ | ||
1455 | if (this_request->was_tag_assigned_by_user == false) { | ||
1456 | scic_sds_controller_copy_task_context( | ||
1457 | this_request->owning_controller, this_request | ||
1458 | ); | ||
1459 | } | ||
1460 | |||
1461 | /* Add to the post_context the io tag value */ | ||
1462 | this_request->post_context |= scic_sds_io_tag_get_index(this_request->io_tag); | ||
1463 | |||
1464 | /* Everything is good go ahead and change state */ | ||
1465 | sci_base_state_machine_change_state( | ||
1466 | &this_request->parent.state_machine, | ||
1467 | SCI_BASE_REQUEST_STATE_STARTED | ||
1468 | ); | ||
1469 | |||
1470 | return SCI_SUCCESS; | ||
1471 | } | ||
1472 | |||
1473 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; | ||
1474 | } | ||
1475 | |||
1476 | /** | ||
1477 | * scic_sds_request_constructed_state_abort_handler() - | ||
1478 | * @request: This is the struct sci_base_request object that is cast to the | ||
1479 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1480 | * | ||
1481 | * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T | ||
1482 | * object receives a scic_sds_request_terminate() request. Since the request | ||
1483 | * has not yet been posted to the hardware the request transitions to the | ||
1484 | * completed state. enum sci_status SCI_SUCCESS | ||
1485 | */ | ||
1486 | static enum sci_status scic_sds_request_constructed_state_abort_handler( | ||
1487 | struct sci_base_request *request) | ||
1488 | { | ||
1489 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
1490 | |||
1491 | /* | ||
1492 | * This request has been terminated by the user make sure that the correct | ||
1493 | * status code is returned */ | ||
1494 | scic_sds_request_set_status( | ||
1495 | this_request, | ||
1496 | SCU_TASK_DONE_TASK_ABORT, | ||
1497 | SCI_FAILURE_IO_TERMINATED | ||
1498 | ); | ||
1499 | |||
1500 | sci_base_state_machine_change_state( | ||
1501 | &this_request->parent.state_machine, | ||
1502 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1503 | ); | ||
1504 | |||
1505 | return SCI_SUCCESS; | ||
1506 | } | ||
1507 | |||
1508 | /* | ||
1509 | * ***************************************************************************** | ||
1510 | * * STARTED STATE HANDLERS | ||
1511 | * ***************************************************************************** */ | ||
1512 | |||
1513 | /** | ||
1514 | * scic_sds_request_started_state_abort_handler() - | ||
1515 | * @request: This is the struct sci_base_request object that is cast to the | ||
1516 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1517 | * | ||
1518 | * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T | ||
1519 | * object receives a scic_sds_request_terminate() request. Since the request | ||
1520 | * has been posted to the hardware the io request state is changed to the | ||
1521 | * aborting state. enum sci_status SCI_SUCCESS | ||
1522 | */ | ||
1523 | enum sci_status scic_sds_request_started_state_abort_handler( | ||
1524 | struct sci_base_request *request) | ||
1525 | { | ||
1526 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
1527 | |||
1528 | if (this_request->has_started_substate_machine) { | ||
1529 | sci_base_state_machine_stop(&this_request->started_substate_machine); | ||
1530 | } | ||
1531 | |||
1532 | sci_base_state_machine_change_state( | ||
1533 | &this_request->parent.state_machine, | ||
1534 | SCI_BASE_REQUEST_STATE_ABORTING | ||
1535 | ); | ||
1536 | |||
1537 | return SCI_SUCCESS; | ||
1538 | } | ||
1539 | |||
1540 | /** | ||
1541 | * scic_sds_request_started_state_tc_completion_handler() - This method process | ||
1542 | * TC (task context) completions for normal IO request (i.e. Task/Abort | ||
1543 | * Completions of type 0). This method will update the | ||
1544 | * SCIC_SDS_IO_REQUEST_T::status field. | ||
1545 | * @this_request: This parameter specifies the request for which a completion | ||
1546 | * occurred. | ||
1547 | * @completion_code: This parameter specifies the completion code received from | ||
1548 | * the SCU. | ||
1549 | * | ||
1550 | */ | ||
1551 | enum sci_status scic_sds_request_started_state_tc_completion_handler( | ||
1552 | struct scic_sds_request *this_request, | ||
1553 | u32 completion_code) | ||
1554 | { | ||
1555 | u8 data_present; | ||
1556 | struct sci_ssp_response_iu *response_buffer; | ||
1557 | |||
1558 | /** | ||
1559 | * @todo Any SDMA return code of other than 0 is bad | ||
1560 | * decode 0x003C0000 to determine SDMA status | ||
1561 | */ | ||
1562 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1563 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1564 | scic_sds_request_set_status( | ||
1565 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1566 | ); | ||
1567 | break; | ||
1568 | |||
1569 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EARLY_RESP): | ||
1570 | { | ||
1571 | /* | ||
1572 | * There are times when the SCU hardware will return an early response | ||
1573 | * because the io request specified more data than is returned by the | ||
1574 | * target device (mode pages, inquiry data, etc.). We must check the | ||
1575 | * response stats to see if this is truly a failed request or a good | ||
1576 | * request that just got completed early. */ | ||
1577 | struct sci_ssp_response_iu *response = (struct sci_ssp_response_iu *) | ||
1578 | this_request->response_buffer; | ||
1579 | scic_word_copy_with_swap( | ||
1580 | this_request->response_buffer, | ||
1581 | this_request->response_buffer, | ||
1582 | sizeof(struct sci_ssp_response_iu) / sizeof(u32) | ||
1583 | ); | ||
1584 | |||
1585 | if (response->status == 0) { | ||
1586 | scic_sds_request_set_status( | ||
1587 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY | ||
1588 | ); | ||
1589 | } else { | ||
1590 | scic_sds_request_set_status( | ||
1591 | this_request, | ||
1592 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1593 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1594 | ); | ||
1595 | } | ||
1596 | } | ||
1597 | break; | ||
1598 | |||
1599 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CHECK_RESPONSE): | ||
1600 | scic_word_copy_with_swap( | ||
1601 | this_request->response_buffer, | ||
1602 | this_request->response_buffer, | ||
1603 | sizeof(struct sci_ssp_response_iu) / sizeof(u32) | ||
1604 | ); | ||
1605 | |||
1606 | scic_sds_request_set_status( | ||
1607 | this_request, | ||
1608 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1609 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1610 | ); | ||
1611 | break; | ||
1612 | |||
1613 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RESP_LEN_ERR): | ||
1614 | /* | ||
1615 | * / @todo With TASK_DONE_RESP_LEN_ERR is the response frame guaranteed | ||
1616 | * / to be received before this completion status is posted? */ | ||
1617 | response_buffer = | ||
1618 | (struct sci_ssp_response_iu *)this_request->response_buffer; | ||
1619 | data_present = | ||
1620 | response_buffer->data_present & SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK; | ||
1621 | |||
1622 | if ((data_present == 0x01) || (data_present == 0x02)) { | ||
1623 | scic_sds_request_set_status( | ||
1624 | this_request, | ||
1625 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1626 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1627 | ); | ||
1628 | } else { | ||
1629 | scic_sds_request_set_status( | ||
1630 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1631 | ); | ||
1632 | } | ||
1633 | break; | ||
1634 | |||
1635 | /* only stp device gets suspended. */ | ||
1636 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): | ||
1637 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_PERR): | ||
1638 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_ERR): | ||
1639 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_DATA_LEN_ERR): | ||
1640 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_ABORT_ERR): | ||
1641 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_WD_LEN): | ||
1642 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): | ||
1643 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_RESP): | ||
1644 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_SDBFIS): | ||
1645 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): | ||
1646 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDB_ERR): | ||
1647 | if (this_request->protocol == SCIC_STP_PROTOCOL) { | ||
1648 | scic_sds_request_set_status( | ||
1649 | this_request, | ||
1650 | SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, | ||
1651 | SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED | ||
1652 | ); | ||
1653 | } else { | ||
1654 | scic_sds_request_set_status( | ||
1655 | this_request, | ||
1656 | SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, | ||
1657 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1658 | ); | ||
1659 | } | ||
1660 | break; | ||
1661 | |||
1662 | /* both stp/ssp device gets suspended */ | ||
1663 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LF_ERR): | ||
1664 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_WRONG_DESTINATION): | ||
1665 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1): | ||
1666 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2): | ||
1667 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3): | ||
1668 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_BAD_DESTINATION): | ||
1669 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_ZONE_VIOLATION): | ||
1670 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY): | ||
1671 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED): | ||
1672 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED): | ||
1673 | scic_sds_request_set_status( | ||
1674 | this_request, | ||
1675 | SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, | ||
1676 | SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED | ||
1677 | ); | ||
1678 | break; | ||
1679 | |||
1680 | /* neither ssp nor stp gets suspended. */ | ||
1681 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_NAK_CMD_ERR): | ||
1682 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_XR): | ||
1683 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_XR_IU_LEN_ERR): | ||
1684 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SDMA_ERR): | ||
1685 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OFFSET_ERR): | ||
1686 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_EXCESS_DATA): | ||
1687 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): | ||
1688 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): | ||
1689 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): | ||
1690 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): | ||
1691 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_DATA): | ||
1692 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_OPEN_FAIL): | ||
1693 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_VIIT_ENTRY_NV): | ||
1694 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_IIT_ENTRY_NV): | ||
1695 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_RNCNV_OUTBOUND): | ||
1696 | default: | ||
1697 | scic_sds_request_set_status( | ||
1698 | this_request, | ||
1699 | SCU_GET_COMPLETION_TL_STATUS(completion_code) >> SCU_COMPLETION_TL_STATUS_SHIFT, | ||
1700 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1701 | ); | ||
1702 | break; | ||
1703 | } | ||
1704 | |||
1705 | /** | ||
1706 | * @todo This is probably wrong for ACK/NAK timeout conditions | ||
1707 | */ | ||
1708 | |||
1709 | /* In all cases we will treat this as the completion of the IO request. */ | ||
1710 | sci_base_state_machine_change_state( | ||
1711 | &this_request->parent.state_machine, | ||
1712 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1713 | ); | ||
1714 | |||
1715 | return SCI_SUCCESS; | ||
1716 | } | ||
1717 | |||
1718 | /** | ||
1719 | * scic_sds_request_started_state_frame_handler() - | ||
1720 | * @request: This is the struct sci_base_request object that is cast to the | ||
1721 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1722 | * @frame_index: This is the index of the unsolicited frame to be processed. | ||
1723 | * | ||
1724 | * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T | ||
1725 | * object receives a scic_sds_request_frame_handler() request. This method | ||
1726 | * first determines the frame type received. If this is a response frame then | ||
1727 | * the response data is copied to the io request response buffer for processing | ||
1728 | * at completion time. If the frame type is not a response buffer an error is | ||
1729 | * logged. enum sci_status SCI_SUCCESS SCI_FAILURE_INVALID_PARAMETER_VALUE | ||
1730 | */ | ||
1731 | static enum sci_status scic_sds_request_started_state_frame_handler( | ||
1732 | struct scic_sds_request *this_request, | ||
1733 | u32 frame_index) | ||
1734 | { | ||
1735 | enum sci_status status; | ||
1736 | struct sci_ssp_frame_header *frame_header; | ||
1737 | |||
1738 | /* / @todo If this is a response frame we must record that we received it */ | ||
1739 | status = scic_sds_unsolicited_frame_control_get_header( | ||
1740 | &(scic_sds_request_get_controller(this_request)->uf_control), | ||
1741 | frame_index, | ||
1742 | (void **)&frame_header | ||
1743 | ); | ||
1744 | |||
1745 | if (frame_header->frame_type == SCI_SAS_RESPONSE_FRAME) { | ||
1746 | struct sci_ssp_response_iu *response_buffer; | ||
1747 | |||
1748 | status = scic_sds_unsolicited_frame_control_get_buffer( | ||
1749 | &(scic_sds_request_get_controller(this_request)->uf_control), | ||
1750 | frame_index, | ||
1751 | (void **)&response_buffer | ||
1752 | ); | ||
1753 | |||
1754 | scic_word_copy_with_swap( | ||
1755 | this_request->response_buffer, | ||
1756 | (u32 *)response_buffer, | ||
1757 | sizeof(struct sci_ssp_response_iu) | ||
1758 | ); | ||
1759 | |||
1760 | response_buffer = (struct sci_ssp_response_iu *)this_request->response_buffer; | ||
1761 | |||
1762 | if ((response_buffer->data_present == 0x01) || | ||
1763 | (response_buffer->data_present == 0x02)) { | ||
1764 | scic_sds_request_set_status( | ||
1765 | this_request, | ||
1766 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1767 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1768 | ); | ||
1769 | } else | ||
1770 | scic_sds_request_set_status( | ||
1771 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1772 | ); | ||
1773 | } else | ||
1774 | /* This was not a response frame why did it get forwarded? */ | ||
1775 | dev_err(scic_to_dev(this_request->owning_controller), | ||
1776 | "%s: SCIC IO Request 0x%p received unexpected " | ||
1777 | "frame %d type 0x%02x\n", | ||
1778 | __func__, | ||
1779 | this_request, | ||
1780 | frame_index, | ||
1781 | frame_header->frame_type); | ||
1782 | |||
1783 | /* | ||
1784 | * In any case we are done with this frame buffer return it to the | ||
1785 | * controller */ | ||
1786 | scic_sds_controller_release_frame( | ||
1787 | this_request->owning_controller, frame_index | ||
1788 | ); | ||
1789 | |||
1790 | return SCI_SUCCESS; | ||
1791 | } | ||
1792 | |||
1793 | /* | ||
1794 | * ***************************************************************************** | ||
1795 | * * COMPLETED STATE HANDLERS | ||
1796 | * ***************************************************************************** */ | ||
1797 | |||
1798 | |||
1799 | /** | ||
1800 | * scic_sds_request_completed_state_complete_handler() - | ||
1801 | * @request: This is the struct sci_base_request object that is cast to the | ||
1802 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1803 | * | ||
1804 | * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T | ||
1805 | * object receives a scic_sds_request_complete() request. This method frees up | ||
1806 | * any io request resources that have been allocated and transitions the | ||
1807 | * request to its final state. Consider stopping the state machine instead of | ||
1808 | * transitioning to the final state? enum sci_status SCI_SUCCESS | ||
1809 | */ | ||
1810 | static enum sci_status scic_sds_request_completed_state_complete_handler( | ||
1811 | struct sci_base_request *request) | ||
1812 | { | ||
1813 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
1814 | |||
1815 | if (this_request->was_tag_assigned_by_user != true) { | ||
1816 | scic_controller_free_io_tag( | ||
1817 | this_request->owning_controller, this_request->io_tag | ||
1818 | ); | ||
1819 | } | ||
1820 | |||
1821 | if (this_request->saved_rx_frame_index != SCU_INVALID_FRAME_INDEX) { | ||
1822 | scic_sds_controller_release_frame( | ||
1823 | this_request->owning_controller, this_request->saved_rx_frame_index); | ||
1824 | } | ||
1825 | |||
1826 | sci_base_state_machine_change_state( | ||
1827 | &this_request->parent.state_machine, | ||
1828 | SCI_BASE_REQUEST_STATE_FINAL | ||
1829 | ); | ||
1830 | |||
1831 | return SCI_SUCCESS; | ||
1832 | } | ||
1833 | |||
1834 | /* | ||
1835 | * ***************************************************************************** | ||
1836 | * * ABORTING STATE HANDLERS | ||
1837 | * ***************************************************************************** */ | ||
1838 | |||
1839 | /** | ||
1840 | * scic_sds_request_aborting_state_abort_handler() - | ||
1841 | * @request: This is the struct sci_base_request object that is cast to the | ||
1842 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1843 | * | ||
1844 | * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T | ||
1845 | * object receives a scic_sds_request_terminate() request. This method is the | ||
1846 | * io request aborting state abort handlers. On receipt of a multiple | ||
1847 | * terminate requests the io request will transition to the completed state. | ||
1848 | * This should not happen in normal operation. enum sci_status SCI_SUCCESS | ||
1849 | */ | ||
1850 | static enum sci_status scic_sds_request_aborting_state_abort_handler( | ||
1851 | struct sci_base_request *request) | ||
1852 | { | ||
1853 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
1854 | |||
1855 | sci_base_state_machine_change_state( | ||
1856 | &this_request->parent.state_machine, | ||
1857 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1858 | ); | ||
1859 | |||
1860 | return SCI_SUCCESS; | ||
1861 | } | ||
1862 | |||
1863 | /** | ||
1864 | * scic_sds_request_aborting_state_tc_completion_handler() - | ||
1865 | * @request: This is the struct sci_base_request object that is cast to the | ||
1866 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1867 | * | ||
1868 | * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T | ||
1869 | * object receives a scic_sds_request_task_completion() request. This method | ||
1870 | * decodes the completion type waiting for the abort task complete | ||
1871 | * notification. When the abort task complete is received the io request | ||
1872 | * transitions to the completed state. enum sci_status SCI_SUCCESS | ||
1873 | */ | ||
1874 | static enum sci_status scic_sds_request_aborting_state_tc_completion_handler( | ||
1875 | struct scic_sds_request *this_request, | ||
1876 | u32 completion_code) | ||
1877 | { | ||
1878 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1879 | case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): | ||
1880 | case (SCU_TASK_DONE_TASK_ABORT << SCU_COMPLETION_TL_STATUS_SHIFT): | ||
1881 | scic_sds_request_set_status( | ||
1882 | this_request, SCU_TASK_DONE_TASK_ABORT, SCI_FAILURE_IO_TERMINATED | ||
1883 | ); | ||
1884 | |||
1885 | sci_base_state_machine_change_state( | ||
1886 | &this_request->parent.state_machine, | ||
1887 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1888 | ); | ||
1889 | break; | ||
1890 | |||
1891 | default: | ||
1892 | /* | ||
1893 | * Unless we get some strange error wait for the task abort to complete | ||
1894 | * TODO: Should there be a state change for this completion? */ | ||
1895 | break; | ||
1896 | } | ||
1897 | |||
1898 | return SCI_SUCCESS; | ||
1899 | } | ||
1900 | |||
1901 | /** | ||
1902 | * scic_sds_request_aborting_state_frame_handler() - | ||
1903 | * @request: This is the struct sci_base_request object that is cast to the | ||
1904 | * SCIC_SDS_IO_REQUEST_T object for which the start operation is requested. | ||
1905 | * | ||
1906 | * This method implements the action to be taken when an SCIC_SDS_IO_REQUEST_T | ||
1907 | * object receives a scic_sds_request_frame_handler() request. This method | ||
1908 | * discards the unsolicited frame since we are waiting for the abort task | ||
1909 | * completion. enum sci_status SCI_SUCCESS | ||
1910 | */ | ||
1911 | static enum sci_status scic_sds_request_aborting_state_frame_handler( | ||
1912 | struct scic_sds_request *this_request, | ||
1913 | u32 frame_index) | ||
1914 | { | ||
1915 | /* TODO: Is it even possible to get an unsolicited frame in the aborting state? */ | ||
1916 | |||
1917 | scic_sds_controller_release_frame( | ||
1918 | this_request->owning_controller, frame_index); | ||
1919 | |||
1920 | return SCI_SUCCESS; | ||
1921 | } | ||
1922 | |||
1923 | /* --------------------------------------------------------------------------- */ | ||
1924 | |||
1925 | const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[] = { | ||
1926 | [SCI_BASE_REQUEST_STATE_INITIAL] = { | ||
1927 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1928 | .parent.abort_handler = scic_sds_request_default_abort_handler, | ||
1929 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1930 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1931 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1932 | .event_handler = scic_sds_request_default_event_handler, | ||
1933 | .frame_handler = scic_sds_request_default_frame_handler, | ||
1934 | }, | ||
1935 | [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { | ||
1936 | .parent.start_handler = scic_sds_request_constructed_state_start_handler, | ||
1937 | .parent.abort_handler = scic_sds_request_constructed_state_abort_handler, | ||
1938 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1939 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1940 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1941 | .event_handler = scic_sds_request_default_event_handler, | ||
1942 | .frame_handler = scic_sds_request_default_frame_handler, | ||
1943 | }, | ||
1944 | [SCI_BASE_REQUEST_STATE_STARTED] = { | ||
1945 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1946 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1947 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1948 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1949 | .tc_completion_handler = scic_sds_request_started_state_tc_completion_handler, | ||
1950 | .event_handler = scic_sds_request_default_event_handler, | ||
1951 | .frame_handler = scic_sds_request_started_state_frame_handler, | ||
1952 | }, | ||
1953 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { | ||
1954 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1955 | .parent.abort_handler = scic_sds_request_default_abort_handler, | ||
1956 | .parent.complete_handler = scic_sds_request_completed_state_complete_handler, | ||
1957 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1958 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1959 | .event_handler = scic_sds_request_default_event_handler, | ||
1960 | .frame_handler = scic_sds_request_default_frame_handler, | ||
1961 | }, | ||
1962 | [SCI_BASE_REQUEST_STATE_ABORTING] = { | ||
1963 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1964 | .parent.abort_handler = scic_sds_request_aborting_state_abort_handler, | ||
1965 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1966 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1967 | .tc_completion_handler = scic_sds_request_aborting_state_tc_completion_handler, | ||
1968 | .event_handler = scic_sds_request_default_event_handler, | ||
1969 | .frame_handler = scic_sds_request_aborting_state_frame_handler, | ||
1970 | }, | ||
1971 | [SCI_BASE_REQUEST_STATE_FINAL] = { | ||
1972 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1973 | .parent.abort_handler = scic_sds_request_default_abort_handler, | ||
1974 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1975 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1976 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1977 | .event_handler = scic_sds_request_default_event_handler, | ||
1978 | .frame_handler = scic_sds_request_default_frame_handler, | ||
1979 | }, | ||
1980 | }; | ||
1981 | |||
1982 | /** | ||
1983 | * scic_sds_request_initial_state_enter() - | ||
1984 | * @object: This parameter specifies the base object for which the state | ||
1985 | * transition is occurring. | ||
1986 | * | ||
1987 | * This method implements the actions taken when entering the | ||
1988 | * SCI_BASE_REQUEST_STATE_INITIAL state. This state is entered when the initial | ||
1989 | * base request is constructed. Entry into the initial state sets all handlers | ||
1990 | * for the io request object to their default handlers. none | ||
1991 | */ | ||
1992 | static void scic_sds_request_initial_state_enter( | ||
1993 | struct sci_base_object *object) | ||
1994 | { | ||
1995 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1996 | |||
1997 | SET_STATE_HANDLER( | ||
1998 | this_request, | ||
1999 | scic_sds_request_state_handler_table, | ||
2000 | SCI_BASE_REQUEST_STATE_INITIAL | ||
2001 | ); | ||
2002 | } | ||
2003 | |||
2004 | /** | ||
2005 | * scic_sds_request_constructed_state_enter() - | ||
2006 | * @object: The io request object that is to enter the constructed state. | ||
2007 | * | ||
2008 | * This method implements the actions taken when entering the | ||
2009 | * SCI_BASE_REQUEST_STATE_CONSTRUCTED state. The method sets the state handlers | ||
2010 | * for the the constructed state. none | ||
2011 | */ | ||
2012 | static void scic_sds_request_constructed_state_enter( | ||
2013 | struct sci_base_object *object) | ||
2014 | { | ||
2015 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
2016 | |||
2017 | SET_STATE_HANDLER( | ||
2018 | this_request, | ||
2019 | scic_sds_request_state_handler_table, | ||
2020 | SCI_BASE_REQUEST_STATE_CONSTRUCTED | ||
2021 | ); | ||
2022 | } | ||
2023 | |||
2024 | /** | ||
2025 | * scic_sds_request_started_state_enter() - | ||
2026 | * @object: This parameter specifies the base object for which the state | ||
2027 | * transition is occuring. This is cast into a SCIC_SDS_IO_REQUEST object. | ||
2028 | * | ||
2029 | * This method implements the actions taken when entering the | ||
2030 | * SCI_BASE_REQUEST_STATE_STARTED state. If the io request object type is a | ||
2031 | * SCSI Task request we must enter the started substate machine. none | ||
2032 | */ | ||
2033 | static void scic_sds_request_started_state_enter( | ||
2034 | struct sci_base_object *object) | ||
2035 | { | ||
2036 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
2037 | |||
2038 | SET_STATE_HANDLER( | ||
2039 | this_request, | ||
2040 | scic_sds_request_state_handler_table, | ||
2041 | SCI_BASE_REQUEST_STATE_STARTED | ||
2042 | ); | ||
2043 | |||
2044 | /* | ||
2045 | * Most of the request state machines have a started substate machine so | ||
2046 | * start its execution on the entry to the started state. */ | ||
2047 | if (this_request->has_started_substate_machine == true) | ||
2048 | sci_base_state_machine_start(&this_request->started_substate_machine); | ||
2049 | } | ||
2050 | |||
2051 | /** | ||
2052 | * scic_sds_request_started_state_exit() - | ||
2053 | * @object: This parameter specifies the base object for which the state | ||
2054 | * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST | ||
2055 | * object. | ||
2056 | * | ||
2057 | * This method implements the actions taken when exiting the | ||
2058 | * SCI_BASE_REQUEST_STATE_STARTED state. For task requests the action will be | ||
2059 | * to stop the started substate machine. none | ||
2060 | */ | ||
2061 | static void scic_sds_request_started_state_exit( | ||
2062 | struct sci_base_object *object) | ||
2063 | { | ||
2064 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
2065 | |||
2066 | if (this_request->has_started_substate_machine == true) | ||
2067 | sci_base_state_machine_stop(&this_request->started_substate_machine); | ||
2068 | } | ||
2069 | |||
2070 | /** | ||
2071 | * scic_sds_request_completed_state_enter() - | ||
2072 | * @object: This parameter specifies the base object for which the state | ||
2073 | * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST | ||
2074 | * object. | ||
2075 | * | ||
2076 | * This method implements the actions taken when entering the | ||
2077 | * SCI_BASE_REQUEST_STATE_COMPLETED state. This state is entered when the | ||
2078 | * SCIC_SDS_IO_REQUEST has completed. The method will decode the request | ||
2079 | * completion status and convert it to an enum sci_status to return in the | ||
2080 | * completion callback function. none | ||
2081 | */ | ||
2082 | static void scic_sds_request_completed_state_enter( | ||
2083 | struct sci_base_object *object) | ||
2084 | { | ||
2085 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
2086 | |||
2087 | SET_STATE_HANDLER( | ||
2088 | this_request, | ||
2089 | scic_sds_request_state_handler_table, | ||
2090 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
2091 | ); | ||
2092 | |||
2093 | /* Tell the SCI_USER that the IO request is complete */ | ||
2094 | if (this_request->is_task_management_request == false) { | ||
2095 | scic_cb_io_request_complete( | ||
2096 | scic_sds_request_get_controller(this_request), | ||
2097 | scic_sds_request_get_device(this_request), | ||
2098 | this_request, | ||
2099 | this_request->sci_status | ||
2100 | ); | ||
2101 | } else { | ||
2102 | scic_cb_task_request_complete( | ||
2103 | scic_sds_request_get_controller(this_request), | ||
2104 | scic_sds_request_get_device(this_request), | ||
2105 | this_request, | ||
2106 | this_request->sci_status | ||
2107 | ); | ||
2108 | } | ||
2109 | } | ||
2110 | |||
2111 | /** | ||
2112 | * scic_sds_request_aborting_state_enter() - | ||
2113 | * @object: This parameter specifies the base object for which the state | ||
2114 | * transition is occuring. This object is cast into a SCIC_SDS_IO_REQUEST | ||
2115 | * object. | ||
2116 | * | ||
2117 | * This method implements the actions taken when entering the | ||
2118 | * SCI_BASE_REQUEST_STATE_ABORTING state. none | ||
2119 | */ | ||
2120 | static void scic_sds_request_aborting_state_enter( | ||
2121 | struct sci_base_object *object) | ||
2122 | { | ||
2123 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
2124 | |||
2125 | /* Setting the abort bit in the Task Context is required by the silicon. */ | ||
2126 | this_request->task_context_buffer->abort = 1; | ||
2127 | |||
2128 | SET_STATE_HANDLER( | ||
2129 | this_request, | ||
2130 | scic_sds_request_state_handler_table, | ||
2131 | SCI_BASE_REQUEST_STATE_ABORTING | ||
2132 | ); | ||
2133 | } | ||
2134 | |||
2135 | /** | ||
2136 | * scic_sds_request_final_state_enter() - | ||
2137 | * @object: This parameter specifies the base object for which the state | ||
2138 | * transition is occuring. This is cast into a SCIC_SDS_IO_REQUEST object. | ||
2139 | * | ||
2140 | * This method implements the actions taken when entering the | ||
2141 | * SCI_BASE_REQUEST_STATE_FINAL state. The only action required is to put the | ||
2142 | * state handlers in place. none | ||
2143 | */ | ||
2144 | static void scic_sds_request_final_state_enter( | ||
2145 | struct sci_base_object *object) | ||
2146 | { | ||
2147 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
2148 | |||
2149 | SET_STATE_HANDLER( | ||
2150 | this_request, | ||
2151 | scic_sds_request_state_handler_table, | ||
2152 | SCI_BASE_REQUEST_STATE_FINAL | ||
2153 | ); | ||
2154 | } | ||
2155 | |||
2156 | /* --------------------------------------------------------------------------- */ | ||
2157 | |||
2158 | const struct sci_base_state scic_sds_request_state_table[] = { | ||
2159 | [SCI_BASE_REQUEST_STATE_INITIAL] = { | ||
2160 | .enter_state = scic_sds_request_initial_state_enter, | ||
2161 | }, | ||
2162 | [SCI_BASE_REQUEST_STATE_CONSTRUCTED] = { | ||
2163 | .enter_state = scic_sds_request_constructed_state_enter, | ||
2164 | }, | ||
2165 | [SCI_BASE_REQUEST_STATE_STARTED] = { | ||
2166 | .enter_state = scic_sds_request_started_state_enter, | ||
2167 | .exit_state = scic_sds_request_started_state_exit | ||
2168 | }, | ||
2169 | [SCI_BASE_REQUEST_STATE_COMPLETED] = { | ||
2170 | .enter_state = scic_sds_request_completed_state_enter, | ||
2171 | }, | ||
2172 | [SCI_BASE_REQUEST_STATE_ABORTING] = { | ||
2173 | .enter_state = scic_sds_request_aborting_state_enter, | ||
2174 | }, | ||
2175 | [SCI_BASE_REQUEST_STATE_FINAL] = { | ||
2176 | .enter_state = scic_sds_request_final_state_enter, | ||
2177 | }, | ||
2178 | }; | ||
2179 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_request.h b/drivers/scsi/isci/core/scic_sds_request.h new file mode 100644 index 000000000000..0691a7552a2a --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_request.h | |||
@@ -0,0 +1,484 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_IO_REQUEST_H_ | ||
57 | #define _SCIC_SDS_IO_REQUEST_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures, constants and prototypes for the | ||
61 | * SCIC_SDS_IO_REQUEST object. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "scic_io_request.h" | ||
67 | |||
68 | #include "sci_base_request.h" | ||
69 | #include "scu_task_context.h" | ||
70 | #include "intel_sas.h" | ||
71 | |||
72 | struct scic_sds_controller; | ||
73 | struct scic_sds_remote_device; | ||
74 | struct scic_sds_io_request_state_handler; | ||
75 | |||
76 | /** | ||
77 | * enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES - This enumeration | ||
78 | * depicts all of the substates for a task management request to be | ||
79 | * performed in the STARTED super-state. | ||
80 | * | ||
81 | * | ||
82 | */ | ||
83 | enum scic_sds_raw_request_started_task_mgmt_substates { | ||
84 | /** | ||
85 | * The AWAIT_TC_COMPLETION sub-state indicates that the started raw | ||
86 | * task management request is waiting for the transmission of the | ||
87 | * initial frame (i.e. command, task, etc.). | ||
88 | */ | ||
89 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION, | ||
90 | |||
91 | /** | ||
92 | * This sub-state indicates that the started task management request | ||
93 | * is waiting for the reception of an unsolicited frame | ||
94 | * (i.e. response IU). | ||
95 | */ | ||
96 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE, | ||
97 | }; | ||
98 | |||
99 | |||
100 | /** | ||
101 | * enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES - This enumeration depicts all | ||
102 | * of the substates for a SMP request to be performed in the STARTED | ||
103 | * super-state. | ||
104 | * | ||
105 | * | ||
106 | */ | ||
107 | enum scic_sds_smp_request_started_substates { | ||
108 | /** | ||
109 | * This sub-state indicates that the started task management request | ||
110 | * is waiting for the reception of an unsolicited frame | ||
111 | * (i.e. response IU). | ||
112 | */ | ||
113 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE, | ||
114 | |||
115 | /** | ||
116 | * The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is | ||
117 | * waiting for the transmission of the initial frame (i.e. command, task, etc.). | ||
118 | */ | ||
119 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION, | ||
120 | }; | ||
121 | |||
122 | /** | ||
123 | * struct SCIC_SDS_IO_REQUEST - This structure contains or references all of | ||
124 | * the data necessary to process a task management or normal IO request. | ||
125 | * | ||
126 | * | ||
127 | */ | ||
128 | struct scic_sds_request { | ||
129 | /** | ||
130 | * This field indictes the parent object of the request. | ||
131 | */ | ||
132 | struct sci_base_request parent; | ||
133 | |||
134 | void *user_request; | ||
135 | |||
136 | /** | ||
137 | * This field simply points to the controller to which this IO request | ||
138 | * is associated. | ||
139 | */ | ||
140 | struct scic_sds_controller *owning_controller; | ||
141 | |||
142 | /** | ||
143 | * This field simply points to the remote device to which this IO request | ||
144 | * is associated. | ||
145 | */ | ||
146 | struct scic_sds_remote_device *target_device; | ||
147 | |||
148 | /** | ||
149 | * This field is utilized to determine if the SCI user is managing | ||
150 | * the IO tag for this request or if the core is managing it. | ||
151 | */ | ||
152 | bool was_tag_assigned_by_user; | ||
153 | |||
154 | /** | ||
155 | * This field indicates the IO tag for this request. The IO tag is | ||
156 | * comprised of the task_index and a sequence count. The sequence count | ||
157 | * is utilized to help identify tasks from one life to another. | ||
158 | */ | ||
159 | u16 io_tag; | ||
160 | |||
161 | /** | ||
162 | * This field specifies the protocol being utilized for this | ||
163 | * IO request. | ||
164 | */ | ||
165 | SCIC_TRANSPORT_PROTOCOL protocol; | ||
166 | |||
167 | /** | ||
168 | * This field indicates the completion status taken from the SCUs | ||
169 | * completion code. It indicates the completion result for the SCU hardware. | ||
170 | */ | ||
171 | u32 scu_status; | ||
172 | |||
173 | /** | ||
174 | * This field indicates the completion status returned to the SCI user. It | ||
175 | * indicates the users view of the io request completion. | ||
176 | */ | ||
177 | u32 sci_status; | ||
178 | |||
179 | /** | ||
180 | * This field contains the value to be utilized when posting (e.g. Post_TC, | ||
181 | * Post_TC_Abort) this request to the silicon. | ||
182 | */ | ||
183 | u32 post_context; | ||
184 | |||
185 | void *command_buffer; | ||
186 | void *response_buffer; | ||
187 | struct scu_task_context *task_context_buffer; | ||
188 | struct scu_sgl_element_pair *sgl_element_pair_buffer; | ||
189 | |||
190 | /** | ||
191 | * This field indicates if this request is a task management request or | ||
192 | * normal IO request. | ||
193 | */ | ||
194 | bool is_task_management_request; | ||
195 | |||
196 | /** | ||
197 | * This field indicates that this request contains an initialized started | ||
198 | * substate machine. | ||
199 | */ | ||
200 | bool has_started_substate_machine; | ||
201 | |||
202 | /** | ||
203 | * This field is a pointer to the stored rx frame data. It is used in STP | ||
204 | * internal requests and SMP response frames. If this field is non-NULL the | ||
205 | * saved frame must be released on IO request completion. | ||
206 | * | ||
207 | * @todo In the future do we want to keep a list of RX frame buffers? | ||
208 | */ | ||
209 | u32 saved_rx_frame_index; | ||
210 | |||
211 | /** | ||
212 | * This field specifies the data necessary to manage the sub-state | ||
213 | * machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state. | ||
214 | */ | ||
215 | struct sci_base_state_machine started_substate_machine; | ||
216 | |||
217 | /** | ||
218 | * This field specifies the current state handlers in place for this | ||
219 | * IO Request object. This field is updated each time the request | ||
220 | * changes state. | ||
221 | */ | ||
222 | const struct scic_sds_io_request_state_handler *state_handlers; | ||
223 | |||
224 | /** | ||
225 | * This field in the recorded device sequence for the io request. This is | ||
226 | * recorded during the build operation and is compared in the start | ||
227 | * operation. If the sequence is different then there was a change of | ||
228 | * devices from the build to start operations. | ||
229 | */ | ||
230 | u8 device_sequence; | ||
231 | |||
232 | }; | ||
233 | |||
234 | |||
235 | typedef enum sci_status | ||
236 | (*scic_sds_io_request_frame_handler_t)(struct scic_sds_request *req, u32 frame); | ||
237 | |||
238 | typedef enum sci_status | ||
239 | (*scic_sds_io_request_event_handler_t)(struct scic_sds_request *req, u32 event); | ||
240 | |||
241 | typedef enum sci_status | ||
242 | (*scic_sds_io_request_task_completion_handler_t)(struct scic_sds_request *req, u32 completion_code); | ||
243 | |||
244 | /** | ||
245 | * struct scic_sds_io_request_state_handler - This is the SDS core definition | ||
246 | * of the state handlers. | ||
247 | * | ||
248 | * | ||
249 | */ | ||
250 | struct scic_sds_io_request_state_handler { | ||
251 | struct sci_base_request_state_handler parent; | ||
252 | |||
253 | scic_sds_io_request_task_completion_handler_t tc_completion_handler; | ||
254 | scic_sds_io_request_event_handler_t event_handler; | ||
255 | scic_sds_io_request_frame_handler_t frame_handler; | ||
256 | |||
257 | }; | ||
258 | |||
259 | extern const struct sci_base_state scic_sds_request_state_table[]; | ||
260 | extern const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[]; | ||
261 | |||
262 | extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[]; | ||
263 | extern const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[]; | ||
264 | |||
265 | extern const struct sci_base_state scic_sds_smp_request_started_substate_table[]; | ||
266 | extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[]; | ||
267 | |||
268 | /** | ||
269 | * | ||
270 | * | ||
271 | * This macro returns the maximum number of SGL element paris that we will | ||
272 | * support in a single IO request. | ||
273 | */ | ||
274 | #define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2) | ||
275 | |||
276 | /** | ||
277 | * scic_sds_request_get_controller() - | ||
278 | * | ||
279 | * This macro will return the controller for this io request object | ||
280 | */ | ||
281 | #define scic_sds_request_get_controller(this_request) \ | ||
282 | ((this_request)->owning_controller) | ||
283 | |||
284 | /** | ||
285 | * scic_sds_request_get_device() - | ||
286 | * | ||
287 | * This macro will return the device for this io request object | ||
288 | */ | ||
289 | #define scic_sds_request_get_device(this_request) \ | ||
290 | ((this_request)->target_device) | ||
291 | |||
292 | /** | ||
293 | * scic_sds_request_get_port() - | ||
294 | * | ||
295 | * This macro will return the port for this io request object | ||
296 | */ | ||
297 | #define scic_sds_request_get_port(this_request) \ | ||
298 | scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request)) | ||
299 | |||
300 | /** | ||
301 | * scic_sds_request_get_post_context() - | ||
302 | * | ||
303 | * This macro returns the constructed post context result for the io request. | ||
304 | */ | ||
305 | #define scic_sds_request_get_post_context(this_request) \ | ||
306 | ((this_request)->post_context) | ||
307 | |||
308 | /** | ||
309 | * scic_sds_request_get_task_context() - | ||
310 | * | ||
311 | * This is a helper macro to return the os handle for this request object. | ||
312 | */ | ||
313 | #define scic_sds_request_get_task_context(request) \ | ||
314 | ((request)->task_context_buffer) | ||
315 | |||
316 | #define CACHE_LINE_SIZE (64) | ||
317 | #define scic_sds_request_align_task_context_buffer(address) \ | ||
318 | ((struct scu_task_context *)(\ | ||
319 | (((unsigned long)(address)) + (CACHE_LINE_SIZE - 1)) \ | ||
320 | & ~(CACHE_LINE_SIZE - 1) \ | ||
321 | )) | ||
322 | |||
323 | /** | ||
324 | * scic_sds_request_align_sgl_element_buffer() - | ||
325 | * | ||
326 | * This macro will align the memory address so that it is correct for the SCU | ||
327 | * hardware to DMA the SGL element pairs. | ||
328 | */ | ||
329 | #define scic_sds_request_align_sgl_element_buffer(address) \ | ||
330 | ((struct scu_sgl_element_pair *)(\ | ||
331 | ((char *)(address)) \ | ||
332 | + (\ | ||
333 | ((~(unsigned long)(address)) + 1) \ | ||
334 | & (sizeof(struct scu_sgl_element_pair) - 1) \ | ||
335 | ) \ | ||
336 | )) | ||
337 | |||
338 | /** | ||
339 | * scic_sds_request_set_status() - | ||
340 | * | ||
341 | * This macro will set the scu hardware status and sci request completion | ||
342 | * status for an io request. | ||
343 | */ | ||
344 | #define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \ | ||
345 | { \ | ||
346 | (request)->scu_status = (scu_status_code); \ | ||
347 | (request)->sci_status = (sci_status_code); \ | ||
348 | } | ||
349 | |||
350 | #define scic_sds_request_complete(a_request) \ | ||
351 | ((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent)) | ||
352 | |||
353 | |||
354 | |||
355 | |||
356 | /** | ||
357 | * scic_sds_io_request_tc_completion() - | ||
358 | * | ||
359 | * This macro invokes the core state task completion handler for the | ||
360 | * SCIC_SDS_IO_REQUEST_T object. | ||
361 | */ | ||
362 | #define scic_sds_io_request_tc_completion(this_request, completion_code) \ | ||
363 | { \ | ||
364 | if (this_request->parent.state_machine.current_state_id \ | ||
365 | == SCI_BASE_REQUEST_STATE_STARTED \ | ||
366 | && this_request->has_started_substate_machine \ | ||
367 | == false) \ | ||
368 | scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \ | ||
369 | else \ | ||
370 | this_request->state_handlers->tc_completion_handler(this_request, completion_code); \ | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * SCU_SGL_ZERO() - | ||
375 | * | ||
376 | * This macro zeros the hardware SGL element data | ||
377 | */ | ||
378 | #define SCU_SGL_ZERO(scu_sge) \ | ||
379 | { \ | ||
380 | (scu_sge).length = 0; \ | ||
381 | (scu_sge).address_lower = 0; \ | ||
382 | (scu_sge).address_upper = 0; \ | ||
383 | (scu_sge).address_modifier = 0; \ | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * SCU_SGL_COPY() - | ||
388 | * | ||
389 | * This macro copys the SGL Element data from the host os to the hardware SGL | ||
390 | * elment data | ||
391 | */ | ||
392 | #define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \ | ||
393 | { \ | ||
394 | (scu_sge).length = \ | ||
395 | scic_cb_sge_get_length_field(os_handle, os_sge); \ | ||
396 | (scu_sge).address_upper = \ | ||
397 | upper_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \ | ||
398 | (scu_sge).address_lower = \ | ||
399 | lower_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \ | ||
400 | (scu_sge).address_modifier = 0; \ | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * ***************************************************************************** | ||
405 | * * CORE REQUEST PROTOTYPES | ||
406 | * ***************************************************************************** */ | ||
407 | |||
408 | void scic_sds_request_build_sgl( | ||
409 | struct scic_sds_request *this_request); | ||
410 | |||
411 | |||
412 | |||
413 | void scic_sds_stp_request_assign_buffers( | ||
414 | struct scic_sds_request *this_request); | ||
415 | |||
416 | void scic_sds_smp_request_assign_buffers( | ||
417 | struct scic_sds_request *this_request); | ||
418 | |||
419 | /* --------------------------------------------------------------------------- */ | ||
420 | |||
421 | enum sci_status scic_sds_request_start( | ||
422 | struct scic_sds_request *this_request); | ||
423 | |||
424 | enum sci_status scic_sds_io_request_terminate( | ||
425 | struct scic_sds_request *this_request); | ||
426 | |||
427 | enum sci_status scic_sds_io_request_complete( | ||
428 | struct scic_sds_request *this_request); | ||
429 | |||
430 | void scic_sds_io_request_copy_response( | ||
431 | struct scic_sds_request *this_request); | ||
432 | |||
433 | enum sci_status scic_sds_io_request_event_handler( | ||
434 | struct scic_sds_request *this_request, | ||
435 | u32 event_code); | ||
436 | |||
437 | enum sci_status scic_sds_io_request_frame_handler( | ||
438 | struct scic_sds_request *this_request, | ||
439 | u32 frame_index); | ||
440 | |||
441 | |||
442 | enum sci_status scic_sds_task_request_terminate( | ||
443 | struct scic_sds_request *this_request); | ||
444 | |||
445 | /* | ||
446 | * ***************************************************************************** | ||
447 | * * DEFAULT STATE HANDLERS | ||
448 | * ***************************************************************************** */ | ||
449 | |||
450 | enum sci_status scic_sds_request_default_start_handler( | ||
451 | struct sci_base_request *this_request); | ||
452 | |||
453 | |||
454 | enum sci_status scic_sds_request_default_complete_handler( | ||
455 | struct sci_base_request *this_request); | ||
456 | |||
457 | enum sci_status scic_sds_request_default_destruct_handler( | ||
458 | struct sci_base_request *this_request); | ||
459 | |||
460 | enum sci_status scic_sds_request_default_tc_completion_handler( | ||
461 | struct scic_sds_request *this_request, | ||
462 | u32 completion_code); | ||
463 | |||
464 | enum sci_status scic_sds_request_default_event_handler( | ||
465 | struct scic_sds_request *this_request, | ||
466 | u32 event_code); | ||
467 | |||
468 | enum sci_status scic_sds_request_default_frame_handler( | ||
469 | struct scic_sds_request *this_request, | ||
470 | u32 frame_index); | ||
471 | |||
472 | /* | ||
473 | * ***************************************************************************** | ||
474 | * * STARTED STATE HANDLERS | ||
475 | * ***************************************************************************** */ | ||
476 | |||
477 | enum sci_status scic_sds_request_started_state_abort_handler( | ||
478 | struct sci_base_request *this_request); | ||
479 | |||
480 | enum sci_status scic_sds_request_started_state_tc_completion_handler( | ||
481 | struct scic_sds_request *this_request, | ||
482 | u32 completion_code); | ||
483 | |||
484 | #endif /* _SCIC_SDS_IO_REQUEST_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_smp_remote_device.c b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c new file mode 100644 index 000000000000..7cf78d3212cc --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_smp_remote_device.c | |||
@@ -0,0 +1,410 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains This file contains the ready substate handlers for a SMP | ||
58 | * device. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #include "sci_environment.h" | ||
64 | #include "scic_user_callback.h" | ||
65 | #include "scic_sds_remote_device.h" | ||
66 | #include "scic_sds_controller.h" | ||
67 | #include "scic_sds_port.h" | ||
68 | #include "scic_sds_request.h" | ||
69 | #include "scu_event_codes.h" | ||
70 | #include "scu_task_context.h" | ||
71 | |||
72 | |||
73 | /* | ||
74 | * ***************************************************************************** | ||
75 | * * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS | ||
76 | * ***************************************************************************** */ | ||
77 | |||
78 | /** | ||
79 | * | ||
80 | * @[in]: device The device the io is sent to. | ||
81 | * @[in]: request The io to start. | ||
82 | * | ||
83 | * This method will handle the start io operation for a SMP device that is in | ||
84 | * the idle state. enum sci_status | ||
85 | */ | ||
86 | static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler( | ||
87 | struct sci_base_remote_device *device, | ||
88 | struct sci_base_request *request) | ||
89 | { | ||
90 | enum sci_status status; | ||
91 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
92 | struct scic_sds_request *io_request = (struct scic_sds_request *)request; | ||
93 | |||
94 | /* Will the port allow the io request to start? */ | ||
95 | status = this_device->owning_port->state_handlers->start_io_handler( | ||
96 | this_device->owning_port, | ||
97 | this_device, | ||
98 | io_request | ||
99 | ); | ||
100 | |||
101 | if (status == SCI_SUCCESS) { | ||
102 | status = | ||
103 | scic_sds_remote_node_context_start_io(this_device->rnc, io_request); | ||
104 | |||
105 | if (status == SCI_SUCCESS) { | ||
106 | status = scic_sds_request_start(io_request); | ||
107 | } | ||
108 | |||
109 | if (status == SCI_SUCCESS) { | ||
110 | this_device->working_request = io_request; | ||
111 | |||
112 | sci_base_state_machine_change_state( | ||
113 | &this_device->ready_substate_machine, | ||
114 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD | ||
115 | ); | ||
116 | } | ||
117 | |||
118 | scic_sds_remote_device_start_request(this_device, io_request, status); | ||
119 | } | ||
120 | |||
121 | return status; | ||
122 | } | ||
123 | |||
124 | |||
125 | /* | ||
126 | * ****************************************************************************** | ||
127 | * * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS | ||
128 | * ****************************************************************************** */ | ||
129 | /** | ||
130 | * | ||
131 | * @device: This is the device object that is receiving the IO. | ||
132 | * @request: The io to start. | ||
133 | * | ||
134 | * This device is already handling a command it can not accept new commands | ||
135 | * until this one is complete. enum sci_status | ||
136 | */ | ||
137 | static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler( | ||
138 | struct sci_base_remote_device *device, | ||
139 | struct sci_base_request *request) | ||
140 | { | ||
141 | return SCI_FAILURE_INVALID_STATE; | ||
142 | } | ||
143 | |||
144 | |||
145 | /** | ||
146 | * this is the complete_io_handler for smp device at ready cmd substate. | ||
147 | * @device: This is the device object that is receiving the IO. | ||
148 | * @request: The io to start. | ||
149 | * | ||
150 | * enum sci_status | ||
151 | */ | ||
152 | static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler( | ||
153 | struct sci_base_remote_device *device, | ||
154 | struct sci_base_request *request) | ||
155 | { | ||
156 | enum sci_status status; | ||
157 | struct scic_sds_remote_device *this_device; | ||
158 | struct scic_sds_request *the_request; | ||
159 | |||
160 | this_device = (struct scic_sds_remote_device *)device; | ||
161 | the_request = (struct scic_sds_request *)request; | ||
162 | |||
163 | status = scic_sds_io_request_complete(the_request); | ||
164 | |||
165 | if (status == SCI_SUCCESS) { | ||
166 | status = scic_sds_port_complete_io( | ||
167 | this_device->owning_port, this_device, the_request); | ||
168 | |||
169 | if (status == SCI_SUCCESS) { | ||
170 | scic_sds_remote_device_decrement_request_count(this_device); | ||
171 | sci_base_state_machine_change_state( | ||
172 | &this_device->ready_substate_machine, | ||
173 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | ||
174 | ); | ||
175 | } else | ||
176 | dev_err(scirdev_to_dev(this_device), | ||
177 | "%s: SCIC SDS Remote Device 0x%p io request " | ||
178 | "0x%p could not be completd on the port 0x%p " | ||
179 | "failed with status %d.\n", | ||
180 | __func__, | ||
181 | this_device, | ||
182 | the_request, | ||
183 | this_device->owning_port, | ||
184 | status); | ||
185 | } | ||
186 | |||
187 | return status; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * This is frame handler for smp device ready cmd substate. | ||
192 | * @this_device: This is the device object that is receiving the frame. | ||
193 | * @frame_index: The index for the frame received. | ||
194 | * | ||
195 | * enum sci_status | ||
196 | */ | ||
197 | static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler( | ||
198 | struct scic_sds_remote_device *this_device, | ||
199 | u32 frame_index) | ||
200 | { | ||
201 | enum sci_status status; | ||
202 | |||
203 | /* | ||
204 | * / The device does not process any UF received from the hardware while | ||
205 | * / in this state. All unsolicited frames are forwarded to the io request | ||
206 | * / object. */ | ||
207 | status = scic_sds_io_request_frame_handler( | ||
208 | this_device->working_request, | ||
209 | frame_index | ||
210 | ); | ||
211 | |||
212 | return status; | ||
213 | } | ||
214 | |||
215 | /* --------------------------------------------------------------------------- */ | ||
216 | |||
217 | struct scic_sds_remote_device_state_handler | ||
218 | scic_sds_smp_remote_device_ready_substate_handler_table[ | ||
219 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = | ||
220 | { | ||
221 | /* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */ | ||
222 | { | ||
223 | { | ||
224 | scic_sds_remote_device_default_start_handler, | ||
225 | scic_sds_remote_device_ready_state_stop_handler, | ||
226 | scic_sds_remote_device_default_fail_handler, | ||
227 | scic_sds_remote_device_default_destruct_handler, | ||
228 | scic_sds_remote_device_default_reset_handler, | ||
229 | scic_sds_remote_device_default_reset_complete_handler, | ||
230 | scic_sds_smp_remote_device_ready_idle_substate_start_io_handler, | ||
231 | scic_sds_remote_device_default_complete_request_handler, | ||
232 | scic_sds_remote_device_default_continue_request_handler, | ||
233 | scic_sds_remote_device_default_start_request_handler, | ||
234 | scic_sds_remote_device_default_complete_request_handler | ||
235 | }, | ||
236 | scic_sds_remote_device_default_suspend_handler, | ||
237 | scic_sds_remote_device_default_resume_handler, | ||
238 | scic_sds_remote_device_general_event_handler, | ||
239 | scic_sds_remote_device_default_frame_handler | ||
240 | }, | ||
241 | /* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD */ | ||
242 | { | ||
243 | { | ||
244 | scic_sds_remote_device_default_start_handler, | ||
245 | scic_sds_remote_device_ready_state_stop_handler, | ||
246 | scic_sds_remote_device_default_fail_handler, | ||
247 | scic_sds_remote_device_default_destruct_handler, | ||
248 | scic_sds_remote_device_default_reset_handler, | ||
249 | scic_sds_remote_device_default_reset_complete_handler, | ||
250 | scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler, | ||
251 | scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler, | ||
252 | scic_sds_remote_device_default_continue_request_handler, | ||
253 | scic_sds_remote_device_default_start_request_handler, | ||
254 | scic_sds_remote_device_default_complete_request_handler | ||
255 | }, | ||
256 | scic_sds_remote_device_default_suspend_handler, | ||
257 | scic_sds_remote_device_default_resume_handler, | ||
258 | scic_sds_remote_device_general_event_handler, | ||
259 | scic_sds_smp_remote_device_ready_cmd_substate_frame_handler | ||
260 | } | ||
261 | }; | ||
262 | /* | ||
263 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
264 | * redistributing this file, you may do so under either license. | ||
265 | * | ||
266 | * GPL LICENSE SUMMARY | ||
267 | * | ||
268 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
269 | * | ||
270 | * This program is free software; you can redistribute it and/or modify | ||
271 | * it under the terms of version 2 of the GNU General Public License as | ||
272 | * published by the Free Software Foundation. | ||
273 | * | ||
274 | * This program is distributed in the hope that it will be useful, but | ||
275 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
276 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
277 | * General Public License for more details. | ||
278 | * | ||
279 | * You should have received a copy of the GNU General Public License | ||
280 | * along with this program; if not, write to the Free Software | ||
281 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
282 | * The full GNU General Public License is included in this distribution | ||
283 | * in the file called LICENSE.GPL. | ||
284 | * | ||
285 | * BSD LICENSE | ||
286 | * | ||
287 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
288 | * All rights reserved. | ||
289 | * | ||
290 | * Redistribution and use in source and binary forms, with or without | ||
291 | * modification, are permitted provided that the following conditions | ||
292 | * are met: | ||
293 | * | ||
294 | * * Redistributions of source code must retain the above copyright | ||
295 | * notice, this list of conditions and the following disclaimer. | ||
296 | * * Redistributions in binary form must reproduce the above copyright | ||
297 | * notice, this list of conditions and the following disclaimer in | ||
298 | * the documentation and/or other materials provided with the | ||
299 | * distribution. | ||
300 | * * Neither the name of Intel Corporation nor the names of its | ||
301 | * contributors may be used to endorse or promote products derived | ||
302 | * from this software without specific prior written permission. | ||
303 | * | ||
304 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
305 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
306 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
307 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
308 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
309 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
310 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
311 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
312 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
313 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
314 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
315 | */ | ||
316 | |||
317 | /** | ||
318 | * This file contains the enter and exit functions for the | ||
319 | * struct scic_sds_remote_device ready substate machine. | ||
320 | * | ||
321 | * | ||
322 | */ | ||
323 | |||
324 | #include "scic_remote_device.h" | ||
325 | #include "scic_user_callback.h" | ||
326 | #include "scic_sds_remote_device.h" | ||
327 | #include "scic_sds_controller.h" | ||
328 | #include "scic_sds_port.h" | ||
329 | #include "sci_util.h" | ||
330 | #include "sci_environment.h" | ||
331 | |||
332 | /** | ||
333 | * | ||
334 | * @object: This is the struct sci_base_object which is cast into a | ||
335 | * struct scic_sds_remote_device. | ||
336 | * | ||
337 | * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method. | ||
338 | * This method sets the ready cmd substate handlers and reports the device as | ||
339 | * ready. none | ||
340 | */ | ||
341 | static void scic_sds_smp_remote_device_ready_idle_substate_enter( | ||
342 | struct sci_base_object *object) | ||
343 | { | ||
344 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
345 | |||
346 | SET_STATE_HANDLER( | ||
347 | this_device, | ||
348 | scic_sds_smp_remote_device_ready_substate_handler_table, | ||
349 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | ||
350 | ); | ||
351 | |||
352 | scic_cb_remote_device_ready( | ||
353 | scic_sds_remote_device_get_controller(this_device), this_device); | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * | ||
358 | * @object: This is the struct sci_base_object which is cast into a | ||
359 | * struct scic_sds_remote_device. | ||
360 | * | ||
361 | * This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This | ||
362 | * method sets the remote device objects ready cmd substate handlers, and | ||
363 | * notify core user that the device is not ready. none | ||
364 | */ | ||
365 | static void scic_sds_smp_remote_device_ready_cmd_substate_enter( | ||
366 | struct sci_base_object *object) | ||
367 | { | ||
368 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
369 | |||
370 | BUG_ON(this_device->working_request == NULL); | ||
371 | |||
372 | SET_STATE_HANDLER( | ||
373 | this_device, | ||
374 | scic_sds_smp_remote_device_ready_substate_handler_table, | ||
375 | SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD | ||
376 | ); | ||
377 | |||
378 | scic_cb_remote_device_not_ready( | ||
379 | scic_sds_remote_device_get_controller(this_device), | ||
380 | this_device, | ||
381 | SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED | ||
382 | ); | ||
383 | } | ||
384 | |||
385 | /** | ||
386 | * | ||
387 | * @object: This is the struct sci_base_object which is cast into a | ||
388 | * struct scic_sds_remote_device. | ||
389 | * | ||
390 | * This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none | ||
391 | */ | ||
392 | static void scic_sds_smp_remote_device_ready_cmd_substate_exit( | ||
393 | struct sci_base_object *object) | ||
394 | { | ||
395 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object; | ||
396 | |||
397 | this_device->working_request = NULL; | ||
398 | } | ||
399 | |||
400 | /* --------------------------------------------------------------------------- */ | ||
401 | |||
402 | const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = { | ||
403 | [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { | ||
404 | .enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter, | ||
405 | }, | ||
406 | [SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { | ||
407 | .enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter, | ||
408 | .exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit, | ||
409 | }, | ||
410 | }; | ||
diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.c b/drivers/scsi/isci/core/scic_sds_smp_request.c new file mode 100644 index 000000000000..949d23e7452a --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_smp_request.c | |||
@@ -0,0 +1,669 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "intel_sas.h" | ||
57 | #include "sci_base_state_machine.h" | ||
58 | #include "scic_controller.h" | ||
59 | #include "scic_remote_device.h" | ||
60 | #include "scic_sds_controller.h" | ||
61 | #include "scic_sds_remote_device.h" | ||
62 | #include "scic_sds_request.h" | ||
63 | #include "scic_sds_smp_request.h" | ||
64 | #include "sci_environment.h" | ||
65 | #include "sci_util.h" | ||
66 | #include "scu_completion_codes.h" | ||
67 | #include "scu_task_context.h" | ||
68 | |||
69 | static void scu_smp_request_construct_task_context( | ||
70 | struct scic_sds_request *this_request, | ||
71 | struct smp_request *smp_request); | ||
72 | |||
73 | /** | ||
74 | * | ||
75 | * | ||
76 | * This method return the memory space required for STP PIO requests. u32 | ||
77 | */ | ||
78 | u32 scic_sds_smp_request_get_object_size(void) | ||
79 | { | ||
80 | return sizeof(struct scic_sds_request) | ||
81 | + sizeof(struct smp_request) | ||
82 | + sizeof(struct smp_response) | ||
83 | + sizeof(struct scu_task_context); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * scic_sds_smp_request_get_command_buffer() - | ||
88 | * | ||
89 | * This macro returns the address of the smp command buffer in the smp request | ||
90 | * memory. No need to cast to SMP request type. | ||
91 | */ | ||
92 | #define scic_sds_smp_request_get_command_buffer(memory) \ | ||
93 | (((char *)(memory)) + sizeof(struct scic_sds_request)) | ||
94 | |||
95 | /** | ||
96 | * scic_sds_smp_request_get_response_buffer() - | ||
97 | * | ||
98 | * This macro returns the address of the smp response buffer in the smp request | ||
99 | * memory. | ||
100 | */ | ||
101 | #define scic_sds_smp_request_get_response_buffer(memory) \ | ||
102 | (((char *)(scic_sds_smp_request_get_command_buffer(memory))) \ | ||
103 | + sizeof(struct smp_request)) | ||
104 | |||
105 | /** | ||
106 | * scic_sds_smp_request_get_task_context_buffer() - | ||
107 | * | ||
108 | * This macro returs the task context buffer for the SMP request. | ||
109 | */ | ||
110 | #define scic_sds_smp_request_get_task_context_buffer(memory) \ | ||
111 | ((struct scu_task_context *)(\ | ||
112 | ((char *)(scic_sds_smp_request_get_response_buffer(memory))) \ | ||
113 | + sizeof(struct smp_response) \ | ||
114 | )) | ||
115 | |||
116 | |||
117 | |||
118 | /** | ||
119 | * This method build the remainder of the IO request object. | ||
120 | * @this_request: This parameter specifies the request object being constructed. | ||
121 | * | ||
122 | * The scic_sds_general_request_construct() must be called before this call is | ||
123 | * valid. none | ||
124 | */ | ||
125 | |||
126 | void scic_sds_smp_request_assign_buffers( | ||
127 | struct scic_sds_request *this_request) | ||
128 | { | ||
129 | /* Assign all of the buffer pointers */ | ||
130 | this_request->command_buffer = | ||
131 | scic_sds_smp_request_get_command_buffer(this_request); | ||
132 | this_request->response_buffer = | ||
133 | scic_sds_smp_request_get_response_buffer(this_request); | ||
134 | this_request->sgl_element_pair_buffer = NULL; | ||
135 | |||
136 | if (this_request->was_tag_assigned_by_user == false) { | ||
137 | this_request->task_context_buffer = | ||
138 | scic_sds_smp_request_get_task_context_buffer(this_request); | ||
139 | this_request->task_context_buffer = | ||
140 | scic_sds_request_align_task_context_buffer(this_request->task_context_buffer); | ||
141 | } | ||
142 | |||
143 | } | ||
144 | /** | ||
145 | * This method is called by the SCI user to build an SMP IO request. | ||
146 | * | ||
147 | * - The user must have previously called scic_io_request_construct() on the | ||
148 | * supplied IO request. Indicate if the controller successfully built the IO | ||
149 | * request. SCI_SUCCESS This value is returned if the IO request was | ||
150 | * successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned | ||
151 | * if the remote_device does not support the SMP protocol. | ||
152 | * SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not | ||
153 | * properly set the association between the SCIC IO request and the user's IO | ||
154 | * request. Please refer to the sci_object_set_association() routine for more | ||
155 | * information. | ||
156 | */ | ||
157 | enum sci_status scic_io_request_construct_smp( | ||
158 | struct scic_sds_request *sci_req) | ||
159 | { | ||
160 | struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL); | ||
161 | |||
162 | if (!smp_req) | ||
163 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; | ||
164 | |||
165 | sci_req->protocol = SCIC_SMP_PROTOCOL; | ||
166 | sci_req->has_started_substate_machine = true; | ||
167 | |||
168 | /* Construct the started sub-state machine. */ | ||
169 | sci_base_state_machine_construct( | ||
170 | &sci_req->started_substate_machine, | ||
171 | &sci_req->parent.parent, | ||
172 | scic_sds_smp_request_started_substate_table, | ||
173 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE | ||
174 | ); | ||
175 | |||
176 | /* Construct the SMP SCU Task Context */ | ||
177 | memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req)); | ||
178 | |||
179 | /* | ||
180 | * Look at the SMP requests' header fields; for certain SAS 1.x SMP | ||
181 | * functions under SAS 2.0, a zero request length really indicates | ||
182 | * a non-zero default length. */ | ||
183 | if (smp_req->header.request_length == 0) { | ||
184 | switch (smp_req->header.function) { | ||
185 | case SMP_FUNCTION_DISCOVER: | ||
186 | case SMP_FUNCTION_REPORT_PHY_ERROR_LOG: | ||
187 | case SMP_FUNCTION_REPORT_PHY_SATA: | ||
188 | case SMP_FUNCTION_REPORT_ROUTE_INFORMATION: | ||
189 | smp_req->header.request_length = 2; | ||
190 | break; | ||
191 | case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION: | ||
192 | case SMP_FUNCTION_PHY_CONTROL: | ||
193 | case SMP_FUNCTION_PHY_TEST: | ||
194 | smp_req->header.request_length = 9; | ||
195 | break; | ||
196 | /* Default - zero is a valid default for 2.0. */ | ||
197 | } | ||
198 | } | ||
199 | |||
200 | scu_smp_request_construct_task_context(sci_req, smp_req); | ||
201 | |||
202 | sci_base_state_machine_change_state( | ||
203 | &sci_req->parent.state_machine, | ||
204 | SCI_BASE_REQUEST_STATE_CONSTRUCTED | ||
205 | ); | ||
206 | |||
207 | kfree(smp_req); | ||
208 | |||
209 | return SCI_SUCCESS; | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * This method is called by the SCI user to build an SMP pass-through IO | ||
214 | * request. | ||
215 | * @scic_smp_request: This parameter specifies the handle to the io request | ||
216 | * object to be built. | ||
217 | * @passthru_cb: This parameter specifies the pointer to the callback structure | ||
218 | * that contains the function pointers | ||
219 | * | ||
220 | * - The user must have previously called scic_io_request_construct() on the | ||
221 | * supplied IO request. Indicate if the controller successfully built the IO | ||
222 | * request. | ||
223 | */ | ||
224 | |||
225 | /** | ||
226 | * This method will fill in the SCU Task Context for a SMP request. The | ||
227 | * following important settings are utilized: -# task_type == | ||
228 | * SCU_TASK_TYPE_SMP. This simply indicates that a normal request type | ||
229 | * (i.e. non-raw frame) is being utilized to perform task management. -# | ||
230 | * control_frame == 1. This ensures that the proper endianess is set so | ||
231 | * that the bytes are transmitted in the right order for a smp request frame. | ||
232 | * @this_request: This parameter specifies the smp request object being | ||
233 | * constructed. | ||
234 | * | ||
235 | */ | ||
236 | static void scu_smp_request_construct_task_context( | ||
237 | struct scic_sds_request *this_request, | ||
238 | struct smp_request *smp_request) | ||
239 | { | ||
240 | dma_addr_t physical_address; | ||
241 | struct scic_sds_controller *owning_controller; | ||
242 | struct scic_sds_remote_device *target_device; | ||
243 | struct scic_sds_port *target_port; | ||
244 | struct scu_task_context *task_context; | ||
245 | |||
246 | /* byte swap the smp request. */ | ||
247 | scic_word_copy_with_swap( | ||
248 | this_request->command_buffer, | ||
249 | (u32 *)smp_request, | ||
250 | sizeof(struct smp_request) / sizeof(u32) | ||
251 | ); | ||
252 | |||
253 | task_context = scic_sds_request_get_task_context(this_request); | ||
254 | |||
255 | owning_controller = scic_sds_request_get_controller(this_request); | ||
256 | target_device = scic_sds_request_get_device(this_request); | ||
257 | target_port = scic_sds_request_get_port(this_request); | ||
258 | |||
259 | /* | ||
260 | * Fill in the TC with the its required data | ||
261 | * 00h */ | ||
262 | task_context->priority = 0; | ||
263 | task_context->initiator_request = 1; | ||
264 | task_context->connection_rate = | ||
265 | scic_remote_device_get_connection_rate(target_device); | ||
266 | task_context->protocol_engine_index = | ||
267 | scic_sds_controller_get_protocol_engine_group(owning_controller); | ||
268 | task_context->logical_port_index = | ||
269 | scic_sds_port_get_index(target_port); | ||
270 | task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP; | ||
271 | task_context->abort = 0; | ||
272 | task_context->valid = SCU_TASK_CONTEXT_VALID; | ||
273 | task_context->context_type = SCU_TASK_CONTEXT_TYPE; | ||
274 | |||
275 | /* 04h */ | ||
276 | task_context->remote_node_index = this_request->target_device->rnc->remote_node_index; | ||
277 | task_context->command_code = 0; | ||
278 | task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST; | ||
279 | |||
280 | /* 08h */ | ||
281 | task_context->link_layer_control = 0; | ||
282 | task_context->do_not_dma_ssp_good_response = 1; | ||
283 | task_context->strict_ordering = 0; | ||
284 | task_context->control_frame = 1; | ||
285 | task_context->timeout_enable = 0; | ||
286 | task_context->block_guard_enable = 0; | ||
287 | |||
288 | /* 0ch */ | ||
289 | task_context->address_modifier = 0; | ||
290 | |||
291 | /* 10h */ | ||
292 | task_context->ssp_command_iu_length = smp_request->header.request_length; | ||
293 | |||
294 | /* 14h */ | ||
295 | task_context->transfer_length_bytes = 0; | ||
296 | |||
297 | /* | ||
298 | * 18h ~ 30h, protocol specific | ||
299 | * since commandIU has been build by framework at this point, we just | ||
300 | * copy the frist DWord from command IU to this location. */ | ||
301 | memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(u32)); | ||
302 | |||
303 | /* | ||
304 | * 40h | ||
305 | * "For SMP you could program it to zero. We would prefer that way so that | ||
306 | * done code will be consistent." - Venki */ | ||
307 | task_context->task_phase = 0; | ||
308 | |||
309 | if (this_request->was_tag_assigned_by_user) { | ||
310 | /* Build the task context now since we have already read the data */ | ||
311 | this_request->post_context = ( | ||
312 | SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ||
313 | | ( | ||
314 | scic_sds_controller_get_protocol_engine_group(owning_controller) | ||
315 | << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT | ||
316 | ) | ||
317 | | ( | ||
318 | scic_sds_port_get_index(target_port) | ||
319 | << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ||
320 | ) | ||
321 | | scic_sds_io_tag_get_index(this_request->io_tag) | ||
322 | ); | ||
323 | } else { | ||
324 | /* Build the task context now since we have already read the data */ | ||
325 | this_request->post_context = ( | ||
326 | SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ||
327 | | ( | ||
328 | scic_sds_controller_get_protocol_engine_group(owning_controller) | ||
329 | << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT | ||
330 | ) | ||
331 | | ( | ||
332 | scic_sds_port_get_index(target_port) | ||
333 | << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ||
334 | ) | ||
335 | /* This is not assigned because we have to wait until we get a TCi */ | ||
336 | ); | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Copy the physical address for the command buffer to the SCU Task Context | ||
341 | * command buffer should not contain command header. */ | ||
342 | scic_cb_io_request_get_physical_address( | ||
343 | scic_sds_request_get_controller(this_request), | ||
344 | this_request, | ||
345 | ((char *)(this_request->command_buffer) + sizeof(u32)), | ||
346 | &physical_address | ||
347 | ); | ||
348 | |||
349 | task_context->command_iu_upper = | ||
350 | upper_32_bits(physical_address); | ||
351 | task_context->command_iu_lower = | ||
352 | lower_32_bits(physical_address); | ||
353 | |||
354 | |||
355 | /* SMP response comes as UF, so no need to set response IU address. */ | ||
356 | task_context->response_iu_upper = 0; | ||
357 | task_context->response_iu_lower = 0; | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * This method processes an unsolicited frame while the SMP request is waiting | ||
362 | * for a response frame. It will copy the response data, release the | ||
363 | * unsolicited frame, and transition the request to the | ||
364 | * SCI_BASE_REQUEST_STATE_COMPLETED state. | ||
365 | * @this_request: This parameter specifies the request for which the | ||
366 | * unsolicited frame was received. | ||
367 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
368 | * should contain the response. | ||
369 | * | ||
370 | * This method returns an indication of whether the response frame was handled | ||
371 | * successfully or not. SCI_SUCCESS Currently this value is always returned and | ||
372 | * indicates successful processing of the TC response. | ||
373 | */ | ||
374 | static enum sci_status scic_sds_smp_request_await_response_frame_handler( | ||
375 | struct scic_sds_request *this_request, | ||
376 | u32 frame_index) | ||
377 | { | ||
378 | enum sci_status status; | ||
379 | void *frame_header; | ||
380 | struct smp_response_header *this_frame_header; | ||
381 | u8 *user_smp_buffer = this_request->response_buffer; | ||
382 | |||
383 | status = scic_sds_unsolicited_frame_control_get_header( | ||
384 | &(scic_sds_request_get_controller(this_request)->uf_control), | ||
385 | frame_index, | ||
386 | &frame_header | ||
387 | ); | ||
388 | |||
389 | /* byte swap the header. */ | ||
390 | scic_word_copy_with_swap( | ||
391 | (u32 *)user_smp_buffer, | ||
392 | frame_header, | ||
393 | sizeof(struct smp_response_header) / sizeof(u32) | ||
394 | ); | ||
395 | this_frame_header = (struct smp_response_header *)user_smp_buffer; | ||
396 | |||
397 | if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) { | ||
398 | void *smp_response_buffer; | ||
399 | |||
400 | status = scic_sds_unsolicited_frame_control_get_buffer( | ||
401 | &(scic_sds_request_get_controller(this_request)->uf_control), | ||
402 | frame_index, | ||
403 | &smp_response_buffer | ||
404 | ); | ||
405 | |||
406 | scic_word_copy_with_swap( | ||
407 | (u32 *)(user_smp_buffer + sizeof(struct smp_response_header)), | ||
408 | smp_response_buffer, | ||
409 | sizeof(union smp_response_body) / sizeof(u32) | ||
410 | ); | ||
411 | if (this_frame_header->function == SMP_FUNCTION_DISCOVER) { | ||
412 | struct smp_response *this_smp_response; | ||
413 | |||
414 | this_smp_response = (struct smp_response *)user_smp_buffer; | ||
415 | |||
416 | /* | ||
417 | * Some expanders only report an attached SATA device, and | ||
418 | * not an STP target. Since the core depends on the STP | ||
419 | * target attribute to correctly build I/O, set the bit now | ||
420 | * if necessary. */ | ||
421 | if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device | ||
422 | && !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) { | ||
423 | this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1; | ||
424 | |||
425 | dev_dbg(scic_to_dev(this_request->owning_controller), | ||
426 | "%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n", | ||
427 | __func__, this_request); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * Don't need to copy to user space. User instead will refer to | ||
433 | * core request's response buffer. */ | ||
434 | |||
435 | /* | ||
436 | * copy the smp response to framework smp request's response buffer. | ||
437 | * scic_sds_smp_request_copy_response(this_request); */ | ||
438 | |||
439 | scic_sds_request_set_status( | ||
440 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
441 | ); | ||
442 | |||
443 | sci_base_state_machine_change_state( | ||
444 | &this_request->started_substate_machine, | ||
445 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION | ||
446 | ); | ||
447 | } else { | ||
448 | /* This was not a response frame why did it get forwarded? */ | ||
449 | dev_err(scic_to_dev(this_request->owning_controller), | ||
450 | "%s: SCIC SMP Request 0x%p received unexpected frame " | ||
451 | "%d type 0x%02x\n", | ||
452 | __func__, | ||
453 | this_request, | ||
454 | frame_index, | ||
455 | this_frame_header->smp_frame_type); | ||
456 | |||
457 | scic_sds_request_set_status( | ||
458 | this_request, | ||
459 | SCU_TASK_DONE_SMP_FRM_TYPE_ERR, | ||
460 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
461 | ); | ||
462 | |||
463 | sci_base_state_machine_change_state( | ||
464 | &this_request->parent.state_machine, | ||
465 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
466 | ); | ||
467 | } | ||
468 | |||
469 | scic_sds_controller_release_frame( | ||
470 | this_request->owning_controller, frame_index | ||
471 | ); | ||
472 | |||
473 | return SCI_SUCCESS; | ||
474 | } | ||
475 | |||
476 | |||
477 | /** | ||
478 | * This method processes an abnormal TC completion while the SMP request is | ||
479 | * waiting for a response frame. It decides what happened to the IO based | ||
480 | * on TC completion status. | ||
481 | * @this_request: This parameter specifies the request for which the TC | ||
482 | * completion was received. | ||
483 | * @completion_code: This parameter indicates the completion status information | ||
484 | * for the TC. | ||
485 | * | ||
486 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
487 | * this method always returns success. | ||
488 | */ | ||
489 | static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler( | ||
490 | struct scic_sds_request *this_request, | ||
491 | u32 completion_code) | ||
492 | { | ||
493 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
494 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
495 | /* | ||
496 | * In the AWAIT RESPONSE state, any TC completion is unexpected. | ||
497 | * but if the TC has success status, we complete the IO anyway. */ | ||
498 | scic_sds_request_set_status( | ||
499 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
500 | ); | ||
501 | |||
502 | sci_base_state_machine_change_state( | ||
503 | &this_request->parent.state_machine, | ||
504 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
505 | ); | ||
506 | break; | ||
507 | |||
508 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR): | ||
509 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR): | ||
510 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR): | ||
511 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR): | ||
512 | /* | ||
513 | * These status has been seen in a specific LSI expander, which sometimes | ||
514 | * is not able to send smp response within 2 ms. This causes our hardware | ||
515 | * break the connection and set TC completion with one of these SMP_XXX_XX_ERR | ||
516 | * status. For these type of error, we ask scic user to retry the request. */ | ||
517 | scic_sds_request_set_status( | ||
518 | this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED | ||
519 | ); | ||
520 | |||
521 | sci_base_state_machine_change_state( | ||
522 | &this_request->parent.state_machine, | ||
523 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
524 | ); | ||
525 | break; | ||
526 | |||
527 | default: | ||
528 | /* | ||
529 | * All other completion status cause the IO to be complete. If a NAK | ||
530 | * was received, then it is up to the user to retry the request. */ | ||
531 | scic_sds_request_set_status( | ||
532 | this_request, | ||
533 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
534 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
535 | ); | ||
536 | |||
537 | sci_base_state_machine_change_state( | ||
538 | &this_request->parent.state_machine, | ||
539 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
540 | ); | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | return SCI_SUCCESS; | ||
545 | } | ||
546 | |||
547 | |||
548 | /** | ||
549 | * This method processes the completions transport layer (TL) status to | ||
550 | * determine if the SMP request was sent successfully. If the SMP request | ||
551 | * was sent successfully, then the state for the SMP request transits to | ||
552 | * waiting for a response frame. | ||
553 | * @this_request: This parameter specifies the request for which the TC | ||
554 | * completion was received. | ||
555 | * @completion_code: This parameter indicates the completion status information | ||
556 | * for the TC. | ||
557 | * | ||
558 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
559 | * this method always returns success. | ||
560 | */ | ||
561 | static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler( | ||
562 | struct scic_sds_request *this_request, | ||
563 | u32 completion_code) | ||
564 | { | ||
565 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
566 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
567 | scic_sds_request_set_status( | ||
568 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
569 | ); | ||
570 | |||
571 | sci_base_state_machine_change_state( | ||
572 | &this_request->parent.state_machine, | ||
573 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
574 | ); | ||
575 | break; | ||
576 | |||
577 | default: | ||
578 | /* | ||
579 | * All other completion status cause the IO to be complete. If a NAK | ||
580 | * was received, then it is up to the user to retry the request. */ | ||
581 | scic_sds_request_set_status( | ||
582 | this_request, | ||
583 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
584 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
585 | ); | ||
586 | |||
587 | sci_base_state_machine_change_state( | ||
588 | &this_request->parent.state_machine, | ||
589 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
590 | ); | ||
591 | break; | ||
592 | } | ||
593 | |||
594 | return SCI_SUCCESS; | ||
595 | } | ||
596 | |||
597 | |||
598 | const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = { | ||
599 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { | ||
600 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
601 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
602 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
603 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
604 | .tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler, | ||
605 | .event_handler = scic_sds_request_default_event_handler, | ||
606 | .frame_handler = scic_sds_smp_request_await_response_frame_handler, | ||
607 | }, | ||
608 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
609 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
610 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
611 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
612 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
613 | .tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler, | ||
614 | .event_handler = scic_sds_request_default_event_handler, | ||
615 | .frame_handler = scic_sds_request_default_frame_handler, | ||
616 | } | ||
617 | }; | ||
618 | |||
619 | /** | ||
620 | * This method performs the actions required when entering the | ||
621 | * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This | ||
622 | * includes setting the IO request state handlers for this sub-state. | ||
623 | * @object: This parameter specifies the request object for which the sub-state | ||
624 | * change is occuring. | ||
625 | * | ||
626 | * none. | ||
627 | */ | ||
628 | static void scic_sds_smp_request_started_await_response_substate_enter( | ||
629 | struct sci_base_object *object) | ||
630 | { | ||
631 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
632 | |||
633 | SET_STATE_HANDLER( | ||
634 | this_request, | ||
635 | scic_sds_smp_request_started_substate_handler_table, | ||
636 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE | ||
637 | ); | ||
638 | } | ||
639 | |||
640 | /** | ||
641 | * This method performs the actions required when entering the | ||
642 | * SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state. | ||
643 | * This includes setting the SMP request state handlers for this sub-state. | ||
644 | * @object: This parameter specifies the request object for which the sub-state | ||
645 | * change is occuring. | ||
646 | * | ||
647 | * none. | ||
648 | */ | ||
649 | static void scic_sds_smp_request_started_await_tc_completion_substate_enter( | ||
650 | struct sci_base_object *object) | ||
651 | { | ||
652 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
653 | |||
654 | SET_STATE_HANDLER( | ||
655 | this_request, | ||
656 | scic_sds_smp_request_started_substate_handler_table, | ||
657 | SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION | ||
658 | ); | ||
659 | } | ||
660 | |||
661 | const struct sci_base_state scic_sds_smp_request_started_substate_table[] = { | ||
662 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = { | ||
663 | .enter_state = scic_sds_smp_request_started_await_response_substate_enter, | ||
664 | }, | ||
665 | [SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
666 | .enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter, | ||
667 | }, | ||
668 | }; | ||
669 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_smp_request.h b/drivers/scsi/isci/core/scic_sds_smp_request.h new file mode 100644 index 000000000000..b7c5b83b1989 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_smp_request.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | #ifndef _SCIC_SDS_SMP_REQUEST_T_ | ||
56 | #define _SCIC_SDS_SMP_REQUEST_T_ | ||
57 | |||
58 | #include "intel_sas.h" | ||
59 | #include "sci_types.h" | ||
60 | #include "scic_sds_request.h" | ||
61 | |||
62 | |||
63 | u32 scic_sds_smp_request_get_object_size(void); | ||
64 | |||
65 | |||
66 | void scic_sds_smp_request_copy_response( | ||
67 | struct scic_sds_request *this_request); | ||
68 | |||
69 | #endif /* _SCIC_SDS_SMP_REQUEST_T_ */ | ||
70 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_ssp_request.c b/drivers/scsi/isci/core/scic_sds_ssp_request.c new file mode 100644 index 000000000000..0d6441c5ce00 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_ssp_request.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the task management substate handlers for the | ||
58 | * SCIC_SDS_IO_REQUEST object. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #include "intel_sas.h" | ||
64 | #include "sci_environment.h" | ||
65 | #include "scic_sds_request.h" | ||
66 | #include "scic_controller.h" | ||
67 | #include "scic_sds_controller.h" | ||
68 | #include "scu_completion_codes.h" | ||
69 | #include "scu_task_context.h" | ||
70 | |||
71 | /** | ||
72 | * This method processes the completions transport layer (TL) status to | ||
73 | * determine if the RAW task management frame was sent successfully. If the | ||
74 | * raw frame was sent successfully, then the state for the task request | ||
75 | * transitions to waiting for a response frame. | ||
76 | * @this_request: This parameter specifies the request for which the TC | ||
77 | * completion was received. | ||
78 | * @completion_code: This parameter indicates the completion status information | ||
79 | * for the TC. | ||
80 | * | ||
81 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
82 | * this method always returns success. | ||
83 | */ | ||
84 | static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler( | ||
85 | struct scic_sds_request *this_request, | ||
86 | u32 completion_code) | ||
87 | { | ||
88 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
89 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
90 | scic_sds_request_set_status( | ||
91 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
92 | ); | ||
93 | |||
94 | sci_base_state_machine_change_state( | ||
95 | &this_request->started_substate_machine, | ||
96 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE | ||
97 | ); | ||
98 | break; | ||
99 | |||
100 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO): | ||
101 | /* | ||
102 | * Currently, the decision is to simply allow the task request to | ||
103 | * timeout if the task IU wasn't received successfully. | ||
104 | * There is a potential for receiving multiple task responses if we | ||
105 | * decide to send the task IU again. */ | ||
106 | dev_warn(scic_to_dev(this_request->owning_controller), | ||
107 | "%s: TaskRequest:0x%p CompletionCode:%x - " | ||
108 | "ACK/NAK timeout\n", | ||
109 | __func__, | ||
110 | this_request, | ||
111 | completion_code); | ||
112 | |||
113 | sci_base_state_machine_change_state( | ||
114 | &this_request->started_substate_machine, | ||
115 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE | ||
116 | ); | ||
117 | break; | ||
118 | |||
119 | default: | ||
120 | /* | ||
121 | * All other completion status cause the IO to be complete. If a NAK | ||
122 | * was received, then it is up to the user to retry the request. */ | ||
123 | scic_sds_request_set_status( | ||
124 | this_request, | ||
125 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
126 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
127 | ); | ||
128 | |||
129 | sci_base_state_machine_change_state( | ||
130 | &this_request->parent.state_machine, | ||
131 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
132 | ); | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | return SCI_SUCCESS; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * This method is responsible for processing a terminate/abort request for this | ||
141 | * TC while the request is waiting for the task management response | ||
142 | * unsolicited frame. | ||
143 | * @this_request: This parameter specifies the request for which the | ||
144 | * termination was requested. | ||
145 | * | ||
146 | * This method returns an indication as to whether the abort request was | ||
147 | * successfully handled. need to update to ensure the received UF doesn't cause | ||
148 | * damage to subsequent requests (i.e. put the extended tag in a holding | ||
149 | * pattern for this particular device). | ||
150 | */ | ||
151 | static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler( | ||
152 | struct sci_base_request *request) | ||
153 | { | ||
154 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
155 | |||
156 | sci_base_state_machine_change_state( | ||
157 | &this_request->parent.state_machine, | ||
158 | SCI_BASE_REQUEST_STATE_ABORTING | ||
159 | ); | ||
160 | |||
161 | sci_base_state_machine_change_state( | ||
162 | &this_request->parent.state_machine, | ||
163 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
164 | ); | ||
165 | |||
166 | return SCI_SUCCESS; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * This method processes an unsolicited frame while the task mgmt request is | ||
171 | * waiting for a response frame. It will copy the response data, release | ||
172 | * the unsolicited frame, and transition the request to the | ||
173 | * SCI_BASE_REQUEST_STATE_COMPLETED state. | ||
174 | * @this_request: This parameter specifies the request for which the | ||
175 | * unsolicited frame was received. | ||
176 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
177 | * should contain the response. | ||
178 | * | ||
179 | * This method returns an indication of whether the TC response frame was | ||
180 | * handled successfully or not. SCI_SUCCESS Currently this value is always | ||
181 | * returned and indicates successful processing of the TC response. Should | ||
182 | * probably update to check frame type and make sure it is a response frame. | ||
183 | */ | ||
184 | static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler( | ||
185 | struct scic_sds_request *this_request, | ||
186 | u32 frame_index) | ||
187 | { | ||
188 | scic_sds_io_request_copy_response(this_request); | ||
189 | |||
190 | sci_base_state_machine_change_state( | ||
191 | &this_request->parent.state_machine, | ||
192 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
193 | ); | ||
194 | |||
195 | scic_sds_controller_release_frame( | ||
196 | this_request->owning_controller, frame_index | ||
197 | ); | ||
198 | |||
199 | return SCI_SUCCESS; | ||
200 | } | ||
201 | |||
202 | const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = { | ||
203 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
204 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
205 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
206 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
207 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
208 | .tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler, | ||
209 | .event_handler = scic_sds_request_default_event_handler, | ||
210 | .frame_handler = scic_sds_request_default_frame_handler, | ||
211 | }, | ||
212 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { | ||
213 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
214 | .parent.abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler, | ||
215 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
216 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
217 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
218 | .event_handler = scic_sds_request_default_event_handler, | ||
219 | .frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler, | ||
220 | } | ||
221 | }; | ||
222 | |||
223 | /* | ||
224 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
225 | * redistributing this file, you may do so under either license. | ||
226 | * | ||
227 | * GPL LICENSE SUMMARY | ||
228 | * | ||
229 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
230 | * | ||
231 | * This program is free software; you can redistribute it and/or modify | ||
232 | * it under the terms of version 2 of the GNU General Public License as | ||
233 | * published by the Free Software Foundation. | ||
234 | * | ||
235 | * This program is distributed in the hope that it will be useful, but | ||
236 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
237 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
238 | * General Public License for more details. | ||
239 | * | ||
240 | * You should have received a copy of the GNU General Public License | ||
241 | * along with this program; if not, write to the Free Software | ||
242 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
243 | * The full GNU General Public License is included in this distribution | ||
244 | * in the file called LICENSE.GPL. | ||
245 | * | ||
246 | * BSD LICENSE | ||
247 | * | ||
248 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
249 | * All rights reserved. | ||
250 | * | ||
251 | * Redistribution and use in source and binary forms, with or without | ||
252 | * modification, are permitted provided that the following conditions | ||
253 | * are met: | ||
254 | * | ||
255 | * * Redistributions of source code must retain the above copyright | ||
256 | * notice, this list of conditions and the following disclaimer. | ||
257 | * * Redistributions in binary form must reproduce the above copyright | ||
258 | * notice, this list of conditions and the following disclaimer in | ||
259 | * the documentation and/or other materials provided with the | ||
260 | * distribution. | ||
261 | * * Neither the name of Intel Corporation nor the names of its | ||
262 | * contributors may be used to endorse or promote products derived | ||
263 | * from this software without specific prior written permission. | ||
264 | * | ||
265 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
266 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
267 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
268 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
269 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
270 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
271 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
272 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
273 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
274 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
275 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
276 | */ | ||
277 | |||
278 | /** | ||
279 | * This file contains the enter/exit methods associated with each of the task | ||
280 | * management raw request states. For more information on the task | ||
281 | * management request state machine please refer to scic_sds_io_request.h | ||
282 | * | ||
283 | * | ||
284 | */ | ||
285 | |||
286 | #include "scic_sds_request.h" | ||
287 | #include "sci_base_state_machine.h" | ||
288 | |||
289 | /** | ||
290 | * This method performs the actions required when entering the | ||
291 | * SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION | ||
292 | * sub-state. This includes setting the IO request state handlers for this | ||
293 | * sub-state. | ||
294 | * @object: This parameter specifies the request object for which the sub-state | ||
295 | * change is occuring. | ||
296 | * | ||
297 | * none. | ||
298 | */ | ||
299 | static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter( | ||
300 | struct sci_base_object *object) | ||
301 | { | ||
302 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
303 | |||
304 | SET_STATE_HANDLER( | ||
305 | this_request, | ||
306 | scic_sds_ssp_task_request_started_substate_handler_table, | ||
307 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION | ||
308 | ); | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * This method performs the actions required when entering the | ||
313 | * SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This | ||
314 | * includes setting the IO request state handlers for this sub-state. | ||
315 | * @object: This parameter specifies the request object for which the sub-state | ||
316 | * change is occuring. | ||
317 | * | ||
318 | * none. | ||
319 | */ | ||
320 | static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter( | ||
321 | struct sci_base_object *object) | ||
322 | { | ||
323 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
324 | |||
325 | SET_STATE_HANDLER( | ||
326 | this_request, | ||
327 | scic_sds_ssp_task_request_started_substate_handler_table, | ||
328 | SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE | ||
329 | ); | ||
330 | } | ||
331 | |||
332 | const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = { | ||
333 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = { | ||
334 | .enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter, | ||
335 | }, | ||
336 | [SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = { | ||
337 | .enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter, | ||
338 | }, | ||
339 | }; | ||
340 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.c b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c new file mode 100644 index 000000000000..f52a8e32b48f --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.c | |||
@@ -0,0 +1,838 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | #if !defined(DISABLE_ATAPI) | ||
56 | |||
57 | #include "intel_ata.h" | ||
58 | #include "intel_sas.h" | ||
59 | #include "intel_sata.h" | ||
60 | #include "intel_sat.h" | ||
61 | #include "sati_translator_sequence.h" | ||
62 | #include "sci_base_state.h" | ||
63 | #include "scic_controller.h" | ||
64 | #include "scic_remote_device.h" | ||
65 | #include "scic_sds_controller.h" | ||
66 | #include "scic_sds_remote_device.h" | ||
67 | #include "scic_sds_request.h" | ||
68 | #include "scic_sds_stp_packet_request.h" | ||
69 | #include "scic_user_callback.h" | ||
70 | #include "sci_util.h" | ||
71 | #include "scu_completion_codes.h" | ||
72 | #include "scu_task_context.h" | ||
73 | |||
74 | |||
75 | /** | ||
76 | * This method will fill in the SCU Task Context for a PACKET fis. And | ||
77 | * construct the request STARTED sub-state machine for Packet Protocol IO. | ||
78 | * @this_request: This parameter specifies the stp packet request object being | ||
79 | * constructed. | ||
80 | * | ||
81 | */ | ||
82 | enum sci_status scic_sds_stp_packet_request_construct( | ||
83 | struct scic_sds_request *this_request) | ||
84 | { | ||
85 | struct sata_fis_reg_h2d *h2d_fis = | ||
86 | scic_stp_io_request_get_h2d_reg_address( | ||
87 | this_request | ||
88 | ); | ||
89 | |||
90 | /* | ||
91 | * Work around, we currently only support PACKET DMA protocol, so we | ||
92 | * need to make change to Packet Fis features field. */ | ||
93 | h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA; | ||
94 | |||
95 | scic_sds_stp_non_ncq_request_construct(this_request); | ||
96 | |||
97 | /* Build the Packet Fis task context structure */ | ||
98 | scu_stp_raw_request_construct_task_context( | ||
99 | (struct scic_sds_stp_request *)this_request, | ||
100 | this_request->task_context_buffer | ||
101 | ); | ||
102 | |||
103 | sci_base_state_machine_construct( | ||
104 | &this_request->started_substate_machine, | ||
105 | &this_request->parent.parent, | ||
106 | scic_sds_stp_packet_request_started_substate_table, | ||
107 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE | ||
108 | ); | ||
109 | |||
110 | return SCI_SUCCESS; | ||
111 | } | ||
112 | |||
113 | |||
114 | /** | ||
115 | * This method will fill in the SCU Task Context for a Packet request command | ||
116 | * phase in PACKET DMA DATA (IN/OUT) type. The following important settings | ||
117 | * are utilized: -# task_type == SCU_TASK_TYPE_PACKET_DMA. This simply | ||
118 | * indicates that a normal request type (i.e. non-raw frame) is being | ||
119 | * utilized to perform task management. -# control_frame == 1. This ensures | ||
120 | * that the proper endianess is set so that the bytes are transmitted in the | ||
121 | * right order for a smp request frame. | ||
122 | * @this_request: This parameter specifies the smp request object being | ||
123 | * constructed. | ||
124 | * @task_context: The task_context to be reconstruct for packet request command | ||
125 | * phase. | ||
126 | * | ||
127 | */ | ||
128 | void scu_stp_packet_request_command_phase_construct_task_context( | ||
129 | struct scic_sds_request *this_request, | ||
130 | struct scu_task_context *task_context) | ||
131 | { | ||
132 | void *atapi_cdb; | ||
133 | u32 atapi_cdb_length; | ||
134 | struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)this_request; | ||
135 | |||
136 | /* | ||
137 | * reference: SSTL 1.13.4.2 | ||
138 | * task_type, sata_direction */ | ||
139 | if (scic_cb_io_request_get_data_direction(this_request->user_request) | ||
140 | == SCI_IO_REQUEST_DATA_OUT) { | ||
141 | task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT; | ||
142 | task_context->sata_direction = 0; | ||
143 | } else { /* todo: for NO_DATA command, we need to send out raw frame. */ | ||
144 | task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN; | ||
145 | task_context->sata_direction = 1; | ||
146 | } | ||
147 | |||
148 | /* sata header */ | ||
149 | memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); | ||
150 | task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; | ||
151 | |||
152 | /* | ||
153 | * Copy in the command IU with CDB so that the commandIU address doesn't | ||
154 | * change. */ | ||
155 | memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); | ||
156 | |||
157 | atapi_cdb = | ||
158 | scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); | ||
159 | |||
160 | atapi_cdb_length = | ||
161 | scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); | ||
162 | |||
163 | memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); | ||
164 | |||
165 | atapi_cdb_length = | ||
166 | max(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length); | ||
167 | |||
168 | task_context->ssp_command_iu_length = | ||
169 | ((atapi_cdb_length % 4) == 0) ? | ||
170 | (atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1); | ||
171 | |||
172 | /* task phase is set to TX_CMD */ | ||
173 | task_context->task_phase = 0x1; | ||
174 | |||
175 | /* retry counter */ | ||
176 | task_context->stp_retry_count = 0; | ||
177 | |||
178 | if (scic_cb_request_is_initial_construction(this_request->user_request)) { | ||
179 | /* data transfer size. */ | ||
180 | task_context->transfer_length_bytes = | ||
181 | scic_cb_io_request_get_transfer_length(this_request->user_request); | ||
182 | |||
183 | /* setup sgl */ | ||
184 | scic_sds_request_build_sgl(this_request); | ||
185 | } else { | ||
186 | /* data transfer size, need to be 4 bytes aligned. */ | ||
187 | task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2); | ||
188 | |||
189 | scic_sds_stp_packet_internal_request_sense_build_sgl(this_request); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * This method will fill in the SCU Task Context for a DATA fis containing CDB | ||
195 | * in Raw Frame type. The TC for previous Packet fis was already there, we | ||
196 | * only need to change the H2D fis content. | ||
197 | * @this_request: This parameter specifies the smp request object being | ||
198 | * constructed. | ||
199 | * @task_context: The task_context to be reconstruct for packet request command | ||
200 | * phase. | ||
201 | * | ||
202 | */ | ||
203 | void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( | ||
204 | struct scic_sds_request *this_request, | ||
205 | struct scu_task_context *task_context) | ||
206 | { | ||
207 | void *atapi_cdb = | ||
208 | scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request); | ||
209 | |||
210 | u32 atapi_cdb_length = | ||
211 | scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request); | ||
212 | |||
213 | memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d)); | ||
214 | memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length); | ||
215 | |||
216 | memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT)); | ||
217 | task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; | ||
218 | |||
219 | /* | ||
220 | * Note the data send out has to be 4 bytes aligned. Or else out hardware will | ||
221 | * patch non-zero bytes and cause the target device unhappy. */ | ||
222 | task_context->transfer_length_bytes = 12; | ||
223 | } | ||
224 | |||
225 | |||
226 | /* | ||
227 | * *@brief This methods decode the D2H status FIS and retrieve the sense data, | ||
228 | * then pass the sense data to user request. | ||
229 | * | ||
230 | ***@param[in] this_request The request receive D2H status FIS. | ||
231 | ***@param[in] status_fis The D2H status fis to be processed. | ||
232 | * | ||
233 | */ | ||
234 | enum sci_status scic_sds_stp_packet_request_process_status_fis( | ||
235 | struct scic_sds_request *this_request, | ||
236 | struct sata_fis_reg_d2h *status_fis) | ||
237 | { | ||
238 | enum sci_status status = SCI_SUCCESS; | ||
239 | |||
240 | /* TODO: Process the error status fis, retrieve sense data. */ | ||
241 | if (status_fis->status & ATA_STATUS_REG_ERROR_BIT) | ||
242 | status = SCI_FAILURE_IO_RESPONSE_VALID; | ||
243 | |||
244 | return status; | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * *@brief This methods builds sgl for internal REQUEST SENSE stp packet | ||
249 | * command using this request response buffer, only one sge is | ||
250 | * needed. | ||
251 | * | ||
252 | ***@param[in] this_request The request receive request sense data. | ||
253 | * | ||
254 | */ | ||
255 | void scic_sds_stp_packet_internal_request_sense_build_sgl( | ||
256 | struct scic_sds_request *this_request) | ||
257 | { | ||
258 | void *sge; | ||
259 | struct scu_sgl_element_pair *scu_sgl_list = NULL; | ||
260 | struct scu_task_context *task_context; | ||
261 | dma_addr_t physical_address; | ||
262 | |||
263 | struct sci_ssp_response_iu *rsp_iu = | ||
264 | (struct sci_ssp_response_iu *)this_request->response_buffer; | ||
265 | |||
266 | sge = (void *)&rsp_iu->data[0]; | ||
267 | |||
268 | task_context = (struct scu_task_context *)this_request->task_context_buffer; | ||
269 | scu_sgl_list = &task_context->sgl_pair_ab; | ||
270 | |||
271 | scic_cb_io_request_get_physical_address( | ||
272 | scic_sds_request_get_controller(this_request), | ||
273 | this_request, | ||
274 | ((char *)sge), | ||
275 | &physical_address | ||
276 | ); | ||
277 | |||
278 | scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address); | ||
279 | scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address); | ||
280 | scu_sgl_list->A.length = task_context->transfer_length_bytes; | ||
281 | scu_sgl_list->A.address_modifier = 0; | ||
282 | |||
283 | SCU_SGL_ZERO(scu_sgl_list->B); | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * This method processes the completions transport layer (TL) status to | ||
288 | * determine if the Packet FIS was sent successfully. If the Packet FIS was | ||
289 | * sent successfully, then the state for the Packet request transits to | ||
290 | * waiting for a PIO SETUP frame. | ||
291 | * @this_request: This parameter specifies the request for which the TC | ||
292 | * completion was received. | ||
293 | * @completion_code: This parameter indicates the completion status information | ||
294 | * for the TC. | ||
295 | * | ||
296 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
297 | * this method always returns success. | ||
298 | */ | ||
299 | enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler( | ||
300 | struct scic_sds_request *this_request, | ||
301 | u32 completion_code) | ||
302 | { | ||
303 | enum sci_status status = SCI_SUCCESS; | ||
304 | |||
305 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
306 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
307 | scic_sds_request_set_status( | ||
308 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
309 | ); | ||
310 | |||
311 | sci_base_state_machine_change_state( | ||
312 | &this_request->started_substate_machine, | ||
313 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE | ||
314 | ); | ||
315 | break; | ||
316 | |||
317 | default: | ||
318 | /* | ||
319 | * All other completion status cause the IO to be complete. If a NAK | ||
320 | * was received, then it is up to the user to retry the request. */ | ||
321 | scic_sds_request_set_status( | ||
322 | this_request, | ||
323 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
324 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
325 | ); | ||
326 | |||
327 | sci_base_state_machine_change_state( | ||
328 | &this_request->parent.state_machine, | ||
329 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
330 | ); | ||
331 | break; | ||
332 | } | ||
333 | |||
334 | return status; | ||
335 | } | ||
336 | |||
337 | |||
338 | /** | ||
339 | * This method processes an unsolicited frame while the Packet request is | ||
340 | * waiting for a PIO SETUP FIS. It will release the unsolicited frame, and | ||
341 | * transition the request to the COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE | ||
342 | * state. | ||
343 | * @this_request: This parameter specifies the request for which the | ||
344 | * unsolicited frame was received. | ||
345 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
346 | * should contain the response. | ||
347 | * | ||
348 | * This method returns an indication of whether the pio setup frame was handled | ||
349 | * successfully or not. SCI_SUCCESS Currently this value is always returned and | ||
350 | * indicates successful processing of the TC response. | ||
351 | */ | ||
352 | enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler( | ||
353 | struct scic_sds_request *request, | ||
354 | u32 frame_index) | ||
355 | { | ||
356 | enum sci_status status; | ||
357 | struct sata_fis_header *frame_header; | ||
358 | u32 *frame_buffer; | ||
359 | struct scic_sds_stp_request *this_request; | ||
360 | |||
361 | this_request = (struct scic_sds_stp_request *)request; | ||
362 | |||
363 | status = scic_sds_unsolicited_frame_control_get_header( | ||
364 | &(this_request->parent.owning_controller->uf_control), | ||
365 | frame_index, | ||
366 | (void **)&frame_header | ||
367 | ); | ||
368 | |||
369 | if (status == SCI_SUCCESS) { | ||
370 | BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_PIO_SETUP); | ||
371 | |||
372 | /* | ||
373 | * Get from the frame buffer the PIO Setup Data, although we don't need | ||
374 | * any info from this pio setup fis. */ | ||
375 | scic_sds_unsolicited_frame_control_get_buffer( | ||
376 | &(this_request->parent.owning_controller->uf_control), | ||
377 | frame_index, | ||
378 | (void **)&frame_buffer | ||
379 | ); | ||
380 | |||
381 | /* | ||
382 | * Get the data from the PIO Setup | ||
383 | * The SCU Hardware returns first word in the frame_header and the rest | ||
384 | * of the data is in the frame buffer so we need to back up one dword */ | ||
385 | this_request->type.packet.device_preferred_cdb_length = | ||
386 | (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; | ||
387 | |||
388 | /* Frame has been decoded return it to the controller */ | ||
389 | scic_sds_controller_release_frame( | ||
390 | this_request->parent.owning_controller, frame_index | ||
391 | ); | ||
392 | |||
393 | sci_base_state_machine_change_state( | ||
394 | &this_request->parent.started_substate_machine, | ||
395 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE | ||
396 | ); | ||
397 | } else | ||
398 | dev_err(scic_to_dev(request->owning_controller), | ||
399 | "%s: SCIC IO Request 0x%p could not get frame header " | ||
400 | "for frame index %d, status %x\n", | ||
401 | __func__, this_request, frame_index, status); | ||
402 | |||
403 | return status; | ||
404 | } | ||
405 | |||
406 | |||
407 | /** | ||
408 | * This method processes the completions transport layer (TL) status to | ||
409 | * determine if the PACKET command data FIS was sent successfully. If | ||
410 | * successfully, then the state for the packet request transits to COMPLETE | ||
411 | * state. If not successfuly, the request transits to | ||
412 | * COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE. | ||
413 | * @this_request: This parameter specifies the request for which the TC | ||
414 | * completion was received. | ||
415 | * @completion_code: This parameter indicates the completion status information | ||
416 | * for the TC. | ||
417 | * | ||
418 | * Indicate if the tc completion handler was successful. SCI_SUCCESS currently | ||
419 | * this method always returns success. | ||
420 | */ | ||
421 | enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler( | ||
422 | struct scic_sds_request *this_request, | ||
423 | u32 completion_code) | ||
424 | { | ||
425 | enum sci_status status = SCI_SUCCESS; | ||
426 | u8 sat_packet_protocol = | ||
427 | scic_cb_request_get_sat_protocol(this_request->user_request); | ||
428 | |||
429 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
430 | case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT): | ||
431 | scic_sds_request_set_status( | ||
432 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
433 | ); | ||
434 | |||
435 | if (sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN | ||
436 | || sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT | ||
437 | ) | ||
438 | sci_base_state_machine_change_state( | ||
439 | &this_request->parent.state_machine, | ||
440 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
441 | ); | ||
442 | else | ||
443 | sci_base_state_machine_change_state( | ||
444 | &this_request->started_substate_machine, | ||
445 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE | ||
446 | ); | ||
447 | break; | ||
448 | |||
449 | case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT): | ||
450 | if (scic_io_request_get_number_of_bytes_transferred(this_request) < | ||
451 | scic_cb_io_request_get_transfer_length(this_request->user_request)) { | ||
452 | scic_sds_request_set_status( | ||
453 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY | ||
454 | ); | ||
455 | |||
456 | sci_base_state_machine_change_state( | ||
457 | &this_request->parent.state_machine, | ||
458 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
459 | ); | ||
460 | |||
461 | status = this_request->sci_status; | ||
462 | } | ||
463 | break; | ||
464 | |||
465 | case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT): | ||
466 | /* In this case, there is no UF coming after. compelte the IO now. */ | ||
467 | scic_sds_request_set_status( | ||
468 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
469 | ); | ||
470 | |||
471 | sci_base_state_machine_change_state( | ||
472 | &this_request->parent.state_machine, | ||
473 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
474 | ); | ||
475 | |||
476 | break; | ||
477 | |||
478 | default: | ||
479 | if (this_request->sci_status != SCI_SUCCESS) { /* The io status was set already. This means an UF for the status | ||
480 | * fis was received already. | ||
481 | */ | ||
482 | |||
483 | /* | ||
484 | * A device suspension event is expected, we need to have the device | ||
485 | * coming out of suspension, then complete the IO. */ | ||
486 | sci_base_state_machine_change_state( | ||
487 | &this_request->started_substate_machine, | ||
488 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE | ||
489 | ); | ||
490 | |||
491 | /* change the device state to ATAPI_ERROR. */ | ||
492 | sci_base_state_machine_change_state( | ||
493 | &this_request->target_device->ready_substate_machine, | ||
494 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR | ||
495 | ); | ||
496 | |||
497 | status = this_request->sci_status; | ||
498 | } else { /* If receiving any non-sucess TC status, no UF received yet, then an UF for | ||
499 | * the status fis is coming after. | ||
500 | */ | ||
501 | scic_sds_request_set_status( | ||
502 | this_request, | ||
503 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
504 | SCI_FAILURE_IO_RESPONSE_VALID | ||
505 | ); | ||
506 | |||
507 | sci_base_state_machine_change_state( | ||
508 | &this_request->started_substate_machine, | ||
509 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE | ||
510 | ); | ||
511 | } | ||
512 | break; | ||
513 | } | ||
514 | |||
515 | return status; | ||
516 | } | ||
517 | |||
518 | |||
519 | /** | ||
520 | * This method processes an unsolicited frame. | ||
521 | * @this_request: This parameter specifies the request for which the | ||
522 | * unsolicited frame was received. | ||
523 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
524 | * should contain the response. | ||
525 | * | ||
526 | * This method returns an indication of whether the UF frame was handled | ||
527 | * successfully or not. SCI_SUCCESS Currently this value is always returned and | ||
528 | * indicates successful processing of the TC response. | ||
529 | */ | ||
530 | enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler( | ||
531 | struct scic_sds_request *request, | ||
532 | u32 frame_index) | ||
533 | { | ||
534 | enum sci_status status; | ||
535 | struct sata_fis_header *frame_header; | ||
536 | u32 *frame_buffer; | ||
537 | struct scic_sds_stp_request *this_request; | ||
538 | |||
539 | this_request = (struct scic_sds_stp_request *)request; | ||
540 | |||
541 | status = scic_sds_unsolicited_frame_control_get_header( | ||
542 | &(this_request->parent.owning_controller->uf_control), | ||
543 | frame_index, | ||
544 | (void **)&frame_header | ||
545 | ); | ||
546 | |||
547 | if (status == SCI_SUCCESS) { | ||
548 | BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_REGD2H); | ||
549 | |||
550 | /* | ||
551 | * Get from the frame buffer the PIO Setup Data, although we don't need | ||
552 | * any info from this pio setup fis. */ | ||
553 | scic_sds_unsolicited_frame_control_get_buffer( | ||
554 | &(this_request->parent.owning_controller->uf_control), | ||
555 | frame_index, | ||
556 | (void **)&frame_buffer | ||
557 | ); | ||
558 | |||
559 | scic_sds_controller_copy_sata_response( | ||
560 | &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer | ||
561 | ); | ||
562 | |||
563 | /* Frame has been decoded return it to the controller */ | ||
564 | scic_sds_controller_release_frame( | ||
565 | this_request->parent.owning_controller, frame_index | ||
566 | ); | ||
567 | } | ||
568 | |||
569 | return status; | ||
570 | } | ||
571 | |||
572 | /** | ||
573 | * This method processes an unsolicited frame while the packet request is | ||
574 | * expecting TC completion. It will process the FIS and construct sense data. | ||
575 | * @this_request: This parameter specifies the request for which the | ||
576 | * unsolicited frame was received. | ||
577 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
578 | * should contain the response. | ||
579 | * | ||
580 | * This method returns an indication of whether the UF frame was handled | ||
581 | * successfully or not. SCI_SUCCESS Currently this value is always returned and | ||
582 | * indicates successful processing of the TC response. | ||
583 | */ | ||
584 | enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler( | ||
585 | struct scic_sds_request *request, | ||
586 | u32 frame_index) | ||
587 | { | ||
588 | struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; | ||
589 | |||
590 | enum sci_status status = | ||
591 | scic_sds_stp_packet_request_command_phase_common_frame_handler( | ||
592 | request, frame_index); | ||
593 | |||
594 | if (status == SCI_SUCCESS) { | ||
595 | /* The command has completed with error status from target device. */ | ||
596 | status = scic_sds_stp_packet_request_process_status_fis( | ||
597 | request, &this_request->d2h_reg_fis); | ||
598 | |||
599 | if (status != SCI_SUCCESS) { | ||
600 | scic_sds_request_set_status( | ||
601 | &this_request->parent, | ||
602 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
603 | status | ||
604 | ); | ||
605 | } else | ||
606 | scic_sds_request_set_status( | ||
607 | &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
608 | ); | ||
609 | } | ||
610 | |||
611 | return status; | ||
612 | } | ||
613 | |||
614 | |||
615 | /** | ||
616 | * This method processes an unsolicited frame while the packet request is | ||
617 | * expecting TC completion. It will process the FIS and construct sense data. | ||
618 | * @this_request: This parameter specifies the request for which the | ||
619 | * unsolicited frame was received. | ||
620 | * @frame_index: This parameter indicates the unsolicited frame index that | ||
621 | * should contain the response. | ||
622 | * | ||
623 | * This method returns an indication of whether the UF frame was handled | ||
624 | * successfully or not. SCI_SUCCESS Currently this value is always returned and | ||
625 | * indicates successful processing of the TC response. | ||
626 | */ | ||
627 | enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler( | ||
628 | struct scic_sds_request *request, | ||
629 | u32 frame_index) | ||
630 | { | ||
631 | enum sci_status status = | ||
632 | scic_sds_stp_packet_request_command_phase_common_frame_handler( | ||
633 | request, frame_index); | ||
634 | |||
635 | struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; | ||
636 | |||
637 | if (status == SCI_SUCCESS) { | ||
638 | /* The command has completed with error status from target device. */ | ||
639 | status = scic_sds_stp_packet_request_process_status_fis( | ||
640 | request, &this_request->d2h_reg_fis); | ||
641 | |||
642 | if (status != SCI_SUCCESS) { | ||
643 | scic_sds_request_set_status( | ||
644 | request, | ||
645 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
646 | status | ||
647 | ); | ||
648 | } else | ||
649 | scic_sds_request_set_status( | ||
650 | request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
651 | ); | ||
652 | |||
653 | /* | ||
654 | * Always complete the NON_DATA command right away, no need to delay completion | ||
655 | * even an error status fis came from target device. */ | ||
656 | sci_base_state_machine_change_state( | ||
657 | &request->parent.state_machine, | ||
658 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
659 | ); | ||
660 | } | ||
661 | |||
662 | return status; | ||
663 | } | ||
664 | |||
665 | enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_handler( | ||
666 | struct sci_base_request *request) | ||
667 | { | ||
668 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
669 | |||
670 | sci_base_state_machine_change_state( | ||
671 | &this_request->parent.state_machine, | ||
672 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
673 | ); | ||
674 | |||
675 | return this_request->sci_status; | ||
676 | } | ||
677 | |||
678 | /* --------------------------------------------------------------------------- */ | ||
679 | |||
680 | const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[] = { | ||
681 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { | ||
682 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
683 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
684 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
685 | .parent.destruct_handler = scic_sds_request_default_destruct_handler | ||
686 | .tc_completion_handler = scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler, | ||
687 | .event_handler = scic_sds_request_default_event_handler, | ||
688 | .frame_handler = scic_sds_request_default_frame_handler | ||
689 | }, | ||
690 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = { | ||
691 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
692 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
693 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
694 | .parent.destruct_handler = scic_sds_request_default_destruct_handler | ||
695 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
696 | .event_handler = scic_sds_request_default_event_handler, | ||
697 | .frame_handler = scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler | ||
698 | }, | ||
699 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { | ||
700 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
701 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
702 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
703 | .parent.destruct_handler = scic_sds_request_default_destruct_handler | ||
704 | .tc_completion_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler, | ||
705 | .event_handler = scic_sds_request_default_event_handler, | ||
706 | .frame_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler | ||
707 | }, | ||
708 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = { | ||
709 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
710 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
711 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
712 | .parent.destruct_handler = scic_sds_request_default_destruct_handler | ||
713 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
714 | .event_handler = scic_sds_request_default_event_handler, | ||
715 | .frame_handler = scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler | ||
716 | }, | ||
717 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = { | ||
718 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
719 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
720 | .parent.complete_handler = scic_sds_stp_packet_request_started_completion_delay_complete_handler, | ||
721 | .parent.destruct_handler = scic_sds_request_default_destruct_handler | ||
722 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
723 | .event_handler = scic_sds_request_default_event_handler, | ||
724 | .frame_handler = scic_sds_request_default_frame_handler | ||
725 | }, | ||
726 | }; | ||
727 | |||
728 | void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter( | ||
729 | struct sci_base_object *object) | ||
730 | { | ||
731 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
732 | |||
733 | SET_STATE_HANDLER( | ||
734 | this_request, | ||
735 | scic_sds_stp_packet_request_started_substate_handler_table, | ||
736 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE | ||
737 | ); | ||
738 | |||
739 | scic_sds_remote_device_set_working_request( | ||
740 | this_request->target_device, this_request | ||
741 | ); | ||
742 | } | ||
743 | |||
744 | void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter( | ||
745 | struct sci_base_object *object) | ||
746 | { | ||
747 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
748 | |||
749 | SET_STATE_HANDLER( | ||
750 | this_request, | ||
751 | scic_sds_stp_packet_request_started_substate_handler_table, | ||
752 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE | ||
753 | ); | ||
754 | } | ||
755 | |||
756 | void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter( | ||
757 | struct sci_base_object *object) | ||
758 | { | ||
759 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
760 | u8 sat_packet_protocol = | ||
761 | scic_cb_request_get_sat_protocol(this_request->user_request); | ||
762 | |||
763 | struct scu_task_context *task_context; | ||
764 | enum sci_status status; | ||
765 | |||
766 | /* | ||
767 | * Recycle the TC and reconstruct it for sending out data fis containing | ||
768 | * CDB. */ | ||
769 | task_context = scic_sds_controller_get_task_context_buffer( | ||
770 | this_request->owning_controller, this_request->io_tag); | ||
771 | |||
772 | if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA) | ||
773 | scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( | ||
774 | this_request, task_context); | ||
775 | else | ||
776 | scu_stp_packet_request_command_phase_construct_task_context( | ||
777 | this_request, task_context); | ||
778 | |||
779 | /* send the new TC out. */ | ||
780 | status = this_request->owning_controller->state_handlers->parent.continue_io_handler( | ||
781 | &this_request->owning_controller->parent, | ||
782 | &this_request->target_device->parent, | ||
783 | &this_request->parent | ||
784 | ); | ||
785 | |||
786 | if (status == SCI_SUCCESS) | ||
787 | SET_STATE_HANDLER( | ||
788 | this_request, | ||
789 | scic_sds_stp_packet_request_started_substate_handler_table, | ||
790 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE | ||
791 | ); | ||
792 | } | ||
793 | |||
794 | void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter( | ||
795 | struct sci_base_object *object) | ||
796 | { | ||
797 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
798 | |||
799 | SET_STATE_HANDLER( | ||
800 | this_request, | ||
801 | scic_sds_stp_packet_request_started_substate_handler_table, | ||
802 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE | ||
803 | ); | ||
804 | } | ||
805 | |||
806 | void scic_sds_stp_packet_request_started_completion_delay_enter( | ||
807 | struct sci_base_object *object) | ||
808 | { | ||
809 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
810 | |||
811 | SET_STATE_HANDLER( | ||
812 | this_request, | ||
813 | scic_sds_stp_packet_request_started_substate_handler_table, | ||
814 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE | ||
815 | ); | ||
816 | } | ||
817 | |||
818 | |||
819 | /* --------------------------------------------------------------------------- */ | ||
820 | const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[] = { | ||
821 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { | ||
822 | .enter_state = scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter, | ||
823 | }, | ||
824 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = { | ||
825 | .enter_state = scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter, | ||
826 | }, | ||
827 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = { | ||
828 | .enter_state = scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter, | ||
829 | }, | ||
830 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = { | ||
831 | .enter_state = scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter, | ||
832 | }, | ||
833 | [SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = { | ||
834 | .enter_state scic_sds_stp_packet_request_started_completion_delay_enter, | ||
835 | } | ||
836 | }; | ||
837 | |||
838 | #endif /* !defined(DISABLE_ATAPI) */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_stp_packet_request.h b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h new file mode 100644 index 000000000000..fc18b3f6a13f --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_packet_request.h | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | #ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_ | ||
56 | #define _SCIC_SDS_STP_PACKET_REQUEST_H_ | ||
57 | |||
58 | #include "intel_sas.h" | ||
59 | #include "sci_types.h" | ||
60 | #include "scic_sds_stp_request.h" | ||
61 | |||
62 | /** | ||
63 | * This file contains the structures and constants for PACKET protocol requests. | ||
64 | * | ||
65 | * | ||
66 | */ | ||
67 | |||
68 | |||
69 | /** | ||
70 | * | ||
71 | * | ||
72 | * This is the enumeration of the SATA PIO DATA IN started substate machine. | ||
73 | */ | ||
74 | enum _SCIC_SDS_STP_PACKET_REQUEST_STARTED_SUBSTATES { | ||
75 | /** | ||
76 | * While in this state the IO request object is waiting for the TC completion | ||
77 | * notification for the H2D Register FIS | ||
78 | */ | ||
79 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, | ||
80 | |||
81 | /** | ||
82 | * While in this state the IO request object is waiting for either a PIO Setup. | ||
83 | */ | ||
84 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE, | ||
85 | |||
86 | /** | ||
87 | * While in this state the IO request object is waiting for TC completion for | ||
88 | * the Packet DMA DATA fis or Raw Frame. | ||
89 | */ | ||
90 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE, | ||
91 | |||
92 | /** | ||
93 | * The non-data IO transit to this state in this state after receiving TC | ||
94 | * completion. While in this state IO request object is waiting for D2H status | ||
95 | * frame as UF. | ||
96 | */ | ||
97 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE, | ||
98 | |||
99 | /** | ||
100 | * The IO transit to this state in this state if the previous TC completion status | ||
101 | * is not success and the atapi device is suspended due to target device failed the IO. | ||
102 | * While in this state IO request object is waiting for device coming out of the | ||
103 | * suspension state then complete the IO. | ||
104 | */ | ||
105 | SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE, | ||
106 | }; | ||
107 | |||
108 | |||
109 | |||
110 | #if !defined(DISABLE_ATAPI) | ||
111 | extern const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[]; | ||
112 | extern const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[]; | ||
113 | #endif /* !defined(DISABLE_ATAPI) */ | ||
114 | |||
115 | #if !defined(DISABLE_ATAPI) | ||
116 | enum sci_status scic_sds_stp_packet_request_construct( | ||
117 | struct scic_sds_request *this_request); | ||
118 | #else /* !defined(DISABLE_ATAPI) */ | ||
119 | #define scic_sds_stp_packet_request_construct(request) SCI_FAILURE | ||
120 | #endif /* !defined(DISABLE_ATAPI) */ | ||
121 | |||
122 | #if !defined(DISABLE_ATAPI) | ||
123 | void scu_stp_packet_request_command_phase_construct_task_context( | ||
124 | struct scic_sds_request *this_request, | ||
125 | struct scu_task_context *task_context); | ||
126 | #else /* !defined(DISABLE_ATAPI) */ | ||
127 | #define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc) | ||
128 | #endif /* !defined(DISABLE_ATAPI) */ | ||
129 | |||
130 | #if !defined(DISABLE_ATAPI) | ||
131 | void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context( | ||
132 | struct scic_sds_request *this_request, | ||
133 | struct scu_task_context *task_context); | ||
134 | #else /* !defined(DISABLE_ATAPI) */ | ||
135 | #define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc) | ||
136 | #endif /* !defined(DISABLE_ATAPI) */ | ||
137 | |||
138 | #if !defined(DISABLE_ATAPI) | ||
139 | enum sci_status scic_sds_stp_packet_request_process_status_fis( | ||
140 | struct scic_sds_request *this_request, | ||
141 | struct sata_fis_reg_d2h *status_fis); | ||
142 | #else /* !defined(DISABLE_ATAPI) */ | ||
143 | #define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE | ||
144 | #endif /* !defined(DISABLE_ATAPI) */ | ||
145 | |||
146 | #if !defined(DISABLE_ATAPI) | ||
147 | void scic_sds_stp_packet_internal_request_sense_build_sgl( | ||
148 | struct scic_sds_request *this_request); | ||
149 | #else /* !defined(DISABLE_ATAPI) */ | ||
150 | #define scic_sds_stp_packet_internal_request_sense_build_sgl(request) | ||
151 | #endif /* !defined(DISABLE_ATAPI) */ | ||
152 | |||
153 | #endif /* _SCIC_SDS_STP_PACKET_REQUEST_H_ */ | ||
154 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_stp_pio_request.h b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h new file mode 100644 index 000000000000..64bf40a6e1d2 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_pio_request.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_ | ||
57 | #define _SCIC_SDS_SATA_PIO_REQUEST_H_ | ||
58 | |||
59 | #include "sci_base_state.h" | ||
60 | #include "scic_sds_request.h" | ||
61 | #include "scu_task_context.h" | ||
62 | |||
63 | /** | ||
64 | * This file contains the structures and constants for SATA PIO requests. | ||
65 | * | ||
66 | * | ||
67 | */ | ||
68 | |||
69 | |||
70 | /** | ||
71 | * | ||
72 | * | ||
73 | * This is the enumeration of the SATA PIO DATA IN started substate machine. | ||
74 | */ | ||
75 | enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES { | ||
76 | /** | ||
77 | * While in this state the IO request object is waiting for the TC completion | ||
78 | * notification for the H2D Register FIS | ||
79 | */ | ||
80 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE, | ||
81 | |||
82 | /** | ||
83 | * While in this state the IO request object is waiting for either a PIO Setup | ||
84 | * FIS or a D2H register FIS. The type of frame received is based on the | ||
85 | * result of the prior frame and line conditions. | ||
86 | */ | ||
87 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE, | ||
88 | |||
89 | /** | ||
90 | * While in this state the IO request object is waiting for a DATA frame from | ||
91 | * the device. | ||
92 | */ | ||
93 | SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE, | ||
94 | |||
95 | /** | ||
96 | * While in this state the IO request object is waiting to transmit the next data | ||
97 | * frame to the device. | ||
98 | */ | ||
99 | SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE, | ||
100 | }; | ||
101 | |||
102 | |||
103 | /* --------------------------------------------------------------------------- */ | ||
104 | |||
105 | extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[]; | ||
106 | |||
107 | extern const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[]; | ||
108 | |||
109 | /* --------------------------------------------------------------------------- */ | ||
110 | |||
111 | struct scic_sds_stp_request; | ||
112 | |||
113 | struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl( | ||
114 | struct scic_sds_stp_request *this_request); | ||
115 | |||
116 | #endif /* _SCIC_SDS_SATA_PIO_REQUEST_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_stp_remote_device.c b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c new file mode 100644 index 000000000000..abe8f331a15c --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_remote_device.c | |||
@@ -0,0 +1,975 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the ready substate handlers for an STP device. | ||
58 | * | ||
59 | * | ||
60 | */ | ||
61 | |||
62 | #include "intel_sat.h" | ||
63 | #include "intel_ata.h" | ||
64 | #include "intel_sata.h" | ||
65 | #include "sci_environment.h" | ||
66 | #include "scic_remote_device.h" | ||
67 | #include "scic_user_callback.h" | ||
68 | #include "scic_sds_controller.h" | ||
69 | #include "scic_sds_port.h" | ||
70 | #include "scic_sds_remote_device.h" | ||
71 | #include "scic_sds_request.h" | ||
72 | #include "scu_event_codes.h" | ||
73 | |||
74 | /** | ||
75 | * This method will perform the STP request completion processing common to IO | ||
76 | * requests and task requests of all types | ||
77 | * @device: This parameter specifies the device for which the request is being | ||
78 | * completed. | ||
79 | * @request: This parameter specifies the request being completed. | ||
80 | * | ||
81 | * This method returns an indication as to whether the request processing | ||
82 | * completed successfully. | ||
83 | */ | ||
84 | static enum sci_status scic_sds_stp_remote_device_complete_request( | ||
85 | struct sci_base_remote_device *device, | ||
86 | struct sci_base_request *request) | ||
87 | { | ||
88 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
89 | struct scic_sds_request *the_request = (struct scic_sds_request *)request; | ||
90 | enum sci_status status; | ||
91 | |||
92 | status = scic_sds_io_request_complete(the_request); | ||
93 | |||
94 | if (status == SCI_SUCCESS) { | ||
95 | status = scic_sds_port_complete_io( | ||
96 | this_device->owning_port, this_device, the_request | ||
97 | ); | ||
98 | |||
99 | if (status == SCI_SUCCESS) { | ||
100 | scic_sds_remote_device_decrement_request_count(this_device); | ||
101 | if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { | ||
102 | /* | ||
103 | * This request causes hardware error, device needs to be Lun Reset. | ||
104 | * So here we force the state machine to IDLE state so the rest IOs | ||
105 | * can reach RNC state handler, these IOs will be completed by RNC with | ||
106 | * status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */ | ||
107 | sci_base_state_machine_change_state( | ||
108 | &this_device->ready_substate_machine, | ||
109 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET | ||
110 | ); | ||
111 | } else if (scic_sds_remote_device_get_request_count(this_device) == 0) { | ||
112 | sci_base_state_machine_change_state( | ||
113 | &this_device->ready_substate_machine, | ||
114 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | ||
115 | ); | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | if (status != SCI_SUCCESS) | ||
121 | dev_err(scirdev_to_dev(this_device), | ||
122 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " | ||
123 | "could not complete\n", | ||
124 | __func__, | ||
125 | this_device->owning_port, | ||
126 | this_device, | ||
127 | the_request, | ||
128 | status); | ||
129 | |||
130 | return status; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * ***************************************************************************** | ||
135 | * * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS | ||
136 | * ***************************************************************************** */ | ||
137 | |||
138 | /** | ||
139 | * This is the READY NCQ substate handler to start task management request. In | ||
140 | * this routine, we suspend and resume the RNC. | ||
141 | * @device: The target device a task management request towards to. | ||
142 | * @request: The task request. | ||
143 | * | ||
144 | * enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to | ||
145 | * let controller_start_task_handler know that the controller can't post TC for | ||
146 | * task request yet, instead, when RNC gets resumed, a controller_continue_task | ||
147 | * callback will be called. | ||
148 | */ | ||
149 | static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler( | ||
150 | struct sci_base_remote_device *device, | ||
151 | struct sci_base_request *request) | ||
152 | { | ||
153 | enum sci_status status; | ||
154 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
155 | struct scic_sds_request *this_request = (struct scic_sds_request *)request; | ||
156 | |||
157 | /* Will the port allow the io request to start? */ | ||
158 | status = this_device->owning_port->state_handlers->start_io_handler( | ||
159 | this_device->owning_port, | ||
160 | this_device, | ||
161 | this_request | ||
162 | ); | ||
163 | |||
164 | if (SCI_SUCCESS == status) { | ||
165 | status = | ||
166 | scic_sds_remote_node_context_start_task(this_device->rnc, this_request); | ||
167 | |||
168 | if (SCI_SUCCESS == status) { | ||
169 | status = this_request->state_handlers->parent.start_handler(request); | ||
170 | } | ||
171 | |||
172 | if (status == SCI_SUCCESS) { | ||
173 | /* | ||
174 | * / @note If the remote device state is not IDLE this will replace | ||
175 | * / the request that probably resulted in the task management | ||
176 | * / request. */ | ||
177 | this_device->working_request = this_request; | ||
178 | |||
179 | sci_base_state_machine_change_state( | ||
180 | &this_device->ready_substate_machine, | ||
181 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD | ||
182 | ); | ||
183 | |||
184 | /* | ||
185 | * The remote node context must cleanup the TCi to NCQ mapping table. | ||
186 | * The only way to do this correctly is to either write to the TLCR | ||
187 | * register or to invalidate and repost the RNC. In either case the | ||
188 | * remote node context state machine will take the correct action when | ||
189 | * the remote node context is suspended and later resumed. */ | ||
190 | scic_sds_remote_node_context_suspend( | ||
191 | this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL); | ||
192 | |||
193 | scic_sds_remote_node_context_resume( | ||
194 | this_device->rnc, | ||
195 | (SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK) | ||
196 | scic_sds_remote_device_continue_request, | ||
197 | this_device); | ||
198 | } | ||
199 | |||
200 | scic_sds_remote_device_start_request(this_device, this_request, status); | ||
201 | |||
202 | /* | ||
203 | * We need to let the controller start request handler know that it can't | ||
204 | * post TC yet. We will provide a callback function to post TC when RNC gets | ||
205 | * resumed. */ | ||
206 | return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS; | ||
207 | } | ||
208 | |||
209 | return status; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * ***************************************************************************** | ||
214 | * * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS | ||
215 | * ***************************************************************************** */ | ||
216 | |||
217 | /** | ||
218 | * This method will handle the start io operation for a sata device that is in | ||
219 | * the command idle state. - Evalute the type of IO request to be started - | ||
220 | * If its an NCQ request change to NCQ substate - If its any other command | ||
221 | * change to the CMD substate | ||
222 | * @device: | ||
223 | * @request: | ||
224 | * | ||
225 | * If this is a softreset we may want to have a different substate. enum sci_status | ||
226 | */ | ||
227 | static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler( | ||
228 | struct sci_base_remote_device *device, | ||
229 | struct sci_base_request *request) | ||
230 | { | ||
231 | enum sci_status status; | ||
232 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
233 | struct scic_sds_request *io_request = (struct scic_sds_request *)request; | ||
234 | |||
235 | |||
236 | /* Will the port allow the io request to start? */ | ||
237 | status = this_device->owning_port->state_handlers->start_io_handler( | ||
238 | this_device->owning_port, | ||
239 | this_device, | ||
240 | io_request | ||
241 | ); | ||
242 | |||
243 | if (status == SCI_SUCCESS) { | ||
244 | status = | ||
245 | scic_sds_remote_node_context_start_io(this_device->rnc, io_request); | ||
246 | |||
247 | if (status == SCI_SUCCESS) { | ||
248 | status = io_request->state_handlers->parent.start_handler(request); | ||
249 | } | ||
250 | |||
251 | if (status == SCI_SUCCESS) { | ||
252 | if ( | ||
253 | scic_cb_request_get_sat_protocol(io_request->user_request) | ||
254 | == SAT_PROTOCOL_FPDMA | ||
255 | ) { | ||
256 | sci_base_state_machine_change_state( | ||
257 | &this_device->ready_substate_machine, | ||
258 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ | ||
259 | ); | ||
260 | } else { | ||
261 | this_device->working_request = io_request; | ||
262 | |||
263 | sci_base_state_machine_change_state( | ||
264 | &this_device->ready_substate_machine, | ||
265 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD | ||
266 | ); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | scic_sds_remote_device_start_request(this_device, io_request, status); | ||
271 | } | ||
272 | |||
273 | return status; | ||
274 | } | ||
275 | |||
276 | |||
277 | /** | ||
278 | * | ||
279 | * @[in]: device The device received event. | ||
280 | * @[in]: event_code The event code. | ||
281 | * | ||
282 | * This method will handle the event for a sata device that is in the idle | ||
283 | * state. We pick up suspension events to handle specifically to this state. We | ||
284 | * resume the RNC right away. enum sci_status | ||
285 | */ | ||
286 | static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler( | ||
287 | struct scic_sds_remote_device *this_device, | ||
288 | u32 event_code) | ||
289 | { | ||
290 | enum sci_status status; | ||
291 | |||
292 | status = scic_sds_remote_device_general_event_handler(this_device, event_code); | ||
293 | |||
294 | if (status == SCI_SUCCESS) { | ||
295 | if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX | ||
296 | || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { | ||
297 | status = scic_sds_remote_node_context_resume( | ||
298 | this_device->rnc, NULL, NULL); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | return status; | ||
303 | } | ||
304 | |||
305 | |||
306 | /* | ||
307 | * ***************************************************************************** | ||
308 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | ||
309 | * ***************************************************************************** */ | ||
310 | |||
311 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler( | ||
312 | struct sci_base_remote_device *device, | ||
313 | struct sci_base_request *request) | ||
314 | { | ||
315 | enum sci_status status; | ||
316 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
317 | struct scic_sds_request *io_request = (struct scic_sds_request *)request; | ||
318 | |||
319 | if ( | ||
320 | scic_cb_request_get_sat_protocol(io_request->user_request) | ||
321 | == SAT_PROTOCOL_FPDMA | ||
322 | ) { | ||
323 | status = this_device->owning_port->state_handlers->start_io_handler( | ||
324 | this_device->owning_port, | ||
325 | this_device, | ||
326 | io_request | ||
327 | ); | ||
328 | |||
329 | if (status == SCI_SUCCESS) { | ||
330 | status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request); | ||
331 | |||
332 | if (status == SCI_SUCCESS) { | ||
333 | status = io_request->state_handlers->parent.start_handler(request); | ||
334 | } | ||
335 | |||
336 | scic_sds_remote_device_start_request(this_device, io_request, status); | ||
337 | } | ||
338 | } else { | ||
339 | status = SCI_FAILURE_INVALID_STATE; | ||
340 | } | ||
341 | |||
342 | return status; | ||
343 | } | ||
344 | |||
345 | |||
346 | /** | ||
347 | * This method will handle events received while the STP device is in the ready | ||
348 | * command substate. | ||
349 | * @this_device: This is the device object that is receiving the event. | ||
350 | * @event_code: The event code to process. | ||
351 | * | ||
352 | * enum sci_status | ||
353 | */ | ||
354 | |||
355 | static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler( | ||
356 | struct scic_sds_remote_device *this_device, | ||
357 | u32 frame_index) | ||
358 | { | ||
359 | enum sci_status status; | ||
360 | struct sata_fis_header *frame_header; | ||
361 | |||
362 | status = scic_sds_unsolicited_frame_control_get_header( | ||
363 | &(scic_sds_remote_device_get_controller(this_device)->uf_control), | ||
364 | frame_index, | ||
365 | (void **)&frame_header | ||
366 | ); | ||
367 | |||
368 | if (status == SCI_SUCCESS) { | ||
369 | if ( | ||
370 | (frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS) | ||
371 | && (frame_header->status & ATA_STATUS_REG_ERROR_BIT) | ||
372 | ) { | ||
373 | this_device->not_ready_reason = | ||
374 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED; | ||
375 | |||
376 | sci_base_state_machine_change_state( | ||
377 | &this_device->ready_substate_machine, | ||
378 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR | ||
379 | ); | ||
380 | } else { | ||
381 | status = SCI_FAILURE; | ||
382 | } | ||
383 | |||
384 | scic_sds_controller_release_frame( | ||
385 | scic_sds_remote_device_get_controller(this_device), frame_index | ||
386 | ); | ||
387 | } | ||
388 | |||
389 | return status; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * ***************************************************************************** | ||
394 | * * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS | ||
395 | * ***************************************************************************** */ | ||
396 | |||
397 | /** | ||
398 | * This device is already handling a command it can not accept new commands | ||
399 | * until this one is complete. | ||
400 | * @device: | ||
401 | * @request: | ||
402 | * | ||
403 | * enum sci_status | ||
404 | */ | ||
405 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler( | ||
406 | struct sci_base_remote_device *device, | ||
407 | struct sci_base_request *request) | ||
408 | { | ||
409 | return SCI_FAILURE_INVALID_STATE; | ||
410 | } | ||
411 | |||
412 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler( | ||
413 | struct scic_sds_remote_device *this_device, | ||
414 | u32 suspend_type) | ||
415 | { | ||
416 | enum sci_status status; | ||
417 | |||
418 | status = scic_sds_remote_node_context_suspend( | ||
419 | this_device->rnc, suspend_type, NULL, NULL | ||
420 | ); | ||
421 | |||
422 | return status; | ||
423 | } | ||
424 | |||
425 | static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler( | ||
426 | struct scic_sds_remote_device *this_device, | ||
427 | u32 frame_index) | ||
428 | { | ||
429 | enum sci_status status; | ||
430 | |||
431 | /* | ||
432 | * / The device doe not process any UF received from the hardware while | ||
433 | * / in this state. All unsolicited frames are forwarded to the io request | ||
434 | * / object. */ | ||
435 | status = scic_sds_io_request_frame_handler( | ||
436 | this_device->working_request, | ||
437 | frame_index | ||
438 | ); | ||
439 | |||
440 | return status; | ||
441 | } | ||
442 | |||
443 | |||
444 | /* | ||
445 | * ***************************************************************************** | ||
446 | * * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS | ||
447 | * ***************************************************************************** */ | ||
448 | |||
449 | /* | ||
450 | * ***************************************************************************** | ||
451 | * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS | ||
452 | * ***************************************************************************** */ | ||
453 | |||
454 | /* | ||
455 | * ***************************************************************************** | ||
456 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS | ||
457 | * ***************************************************************************** */ | ||
458 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler( | ||
459 | struct sci_base_remote_device *device, | ||
460 | struct sci_base_request *request) | ||
461 | { | ||
462 | return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED; | ||
463 | } | ||
464 | |||
465 | |||
466 | |||
467 | /** | ||
468 | * This method will perform the STP request (both io or task) completion | ||
469 | * processing for await reset state. | ||
470 | * @device: This parameter specifies the device for which the request is being | ||
471 | * completed. | ||
472 | * @request: This parameter specifies the request being completed. | ||
473 | * | ||
474 | * This method returns an indication as to whether the request processing | ||
475 | * completed successfully. | ||
476 | */ | ||
477 | static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler( | ||
478 | struct sci_base_remote_device *device, | ||
479 | struct sci_base_request *request) | ||
480 | { | ||
481 | struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device; | ||
482 | struct scic_sds_request *the_request = (struct scic_sds_request *)request; | ||
483 | enum sci_status status; | ||
484 | |||
485 | status = scic_sds_io_request_complete(the_request); | ||
486 | |||
487 | if (status == SCI_SUCCESS) { | ||
488 | status = scic_sds_port_complete_io( | ||
489 | this_device->owning_port, this_device, the_request | ||
490 | ); | ||
491 | |||
492 | if (status == SCI_SUCCESS) | ||
493 | scic_sds_remote_device_decrement_request_count(this_device); | ||
494 | } | ||
495 | |||
496 | if (status != SCI_SUCCESS) | ||
497 | dev_err(scirdev_to_dev(this_device), | ||
498 | "%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x " | ||
499 | "could not complete\n", | ||
500 | __func__, | ||
501 | this_device->owning_port, | ||
502 | this_device, | ||
503 | the_request, | ||
504 | status); | ||
505 | |||
506 | return status; | ||
507 | } | ||
508 | |||
509 | #if !defined(DISABLE_ATAPI) | ||
510 | /* | ||
511 | * ***************************************************************************** | ||
512 | * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS | ||
513 | * ***************************************************************************** */ | ||
514 | |||
515 | /** | ||
516 | * | ||
517 | * @[in]: device The device received event. | ||
518 | * @[in]: event_code The event code. | ||
519 | * | ||
520 | * This method will handle the event for a ATAPI device that is in the ATAPI | ||
521 | * ERROR state. We pick up suspension events to handle specifically to this | ||
522 | * state. We resume the RNC right away. We then complete the outstanding IO to | ||
523 | * this device. enum sci_status | ||
524 | */ | ||
525 | enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler( | ||
526 | struct scic_sds_remote_device *this_device, | ||
527 | u32 event_code) | ||
528 | { | ||
529 | enum sci_status status; | ||
530 | |||
531 | status = scic_sds_remote_device_general_event_handler(this_device, event_code); | ||
532 | |||
533 | if (status == SCI_SUCCESS) { | ||
534 | if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX | ||
535 | || scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) { | ||
536 | status = scic_sds_remote_node_context_resume( | ||
537 | this_device->rnc, | ||
538 | this_device->working_request->state_handlers->parent.complete_handler, | ||
539 | (void *)this_device->working_request | ||
540 | ); | ||
541 | } | ||
542 | } | ||
543 | |||
544 | return status; | ||
545 | } | ||
546 | #endif /* !defined(DISABLE_ATAPI) */ | ||
547 | |||
548 | /* --------------------------------------------------------------------------- */ | ||
549 | |||
550 | struct scic_sds_remote_device_state_handler | ||
551 | scic_sds_stp_remote_device_ready_substate_handler_table[ | ||
552 | SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] = | ||
553 | { | ||
554 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */ | ||
555 | { | ||
556 | { | ||
557 | scic_sds_remote_device_default_start_handler, | ||
558 | scic_sds_remote_device_ready_state_stop_handler, | ||
559 | scic_sds_remote_device_default_fail_handler, | ||
560 | scic_sds_remote_device_default_destruct_handler, | ||
561 | scic_sds_remote_device_ready_state_reset_handler, | ||
562 | scic_sds_remote_device_default_reset_complete_handler, | ||
563 | scic_sds_stp_remote_device_ready_idle_substate_start_io_handler, | ||
564 | scic_sds_remote_device_default_complete_request_handler, | ||
565 | scic_sds_remote_device_default_continue_request_handler, | ||
566 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | ||
567 | scic_sds_remote_device_default_complete_request_handler | ||
568 | }, | ||
569 | scic_sds_remote_device_default_suspend_handler, | ||
570 | scic_sds_remote_device_default_resume_handler, | ||
571 | scic_sds_stp_remote_device_ready_idle_substate_event_handler, | ||
572 | scic_sds_remote_device_default_frame_handler | ||
573 | }, | ||
574 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD */ | ||
575 | { | ||
576 | { | ||
577 | scic_sds_remote_device_default_start_handler, | ||
578 | scic_sds_remote_device_ready_state_stop_handler, | ||
579 | scic_sds_remote_device_default_fail_handler, | ||
580 | scic_sds_remote_device_default_destruct_handler, | ||
581 | scic_sds_remote_device_ready_state_reset_handler, | ||
582 | scic_sds_remote_device_default_reset_complete_handler, | ||
583 | scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler, | ||
584 | scic_sds_stp_remote_device_complete_request, | ||
585 | scic_sds_remote_device_default_continue_request_handler, | ||
586 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | ||
587 | scic_sds_stp_remote_device_complete_request, | ||
588 | }, | ||
589 | scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler, | ||
590 | scic_sds_remote_device_default_resume_handler, | ||
591 | scic_sds_remote_device_general_event_handler, | ||
592 | scic_sds_stp_remote_device_ready_cmd_substate_frame_handler | ||
593 | }, | ||
594 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ */ | ||
595 | { | ||
596 | { | ||
597 | scic_sds_remote_device_default_start_handler, | ||
598 | scic_sds_remote_device_ready_state_stop_handler, | ||
599 | scic_sds_remote_device_default_fail_handler, | ||
600 | scic_sds_remote_device_default_destruct_handler, | ||
601 | scic_sds_remote_device_ready_state_reset_handler, | ||
602 | scic_sds_remote_device_default_reset_complete_handler, | ||
603 | scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler, | ||
604 | scic_sds_stp_remote_device_complete_request, | ||
605 | scic_sds_remote_device_default_continue_request_handler, | ||
606 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | ||
607 | scic_sds_stp_remote_device_complete_request | ||
608 | }, | ||
609 | scic_sds_remote_device_default_suspend_handler, | ||
610 | scic_sds_remote_device_default_resume_handler, | ||
611 | scic_sds_remote_device_general_event_handler, | ||
612 | scic_sds_stp_remote_device_ready_ncq_substate_frame_handler | ||
613 | }, | ||
614 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR */ | ||
615 | { | ||
616 | { | ||
617 | scic_sds_remote_device_default_start_handler, | ||
618 | scic_sds_remote_device_ready_state_stop_handler, | ||
619 | scic_sds_remote_device_default_fail_handler, | ||
620 | scic_sds_remote_device_default_destruct_handler, | ||
621 | scic_sds_remote_device_ready_state_reset_handler, | ||
622 | scic_sds_remote_device_default_reset_complete_handler, | ||
623 | scic_sds_remote_device_default_start_request_handler, | ||
624 | scic_sds_stp_remote_device_complete_request, | ||
625 | scic_sds_remote_device_default_continue_request_handler, | ||
626 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | ||
627 | scic_sds_stp_remote_device_complete_request | ||
628 | }, | ||
629 | scic_sds_remote_device_default_suspend_handler, | ||
630 | scic_sds_remote_device_default_resume_handler, | ||
631 | scic_sds_remote_device_general_event_handler, | ||
632 | scic_sds_remote_device_general_frame_handler | ||
633 | }, | ||
634 | #if !defined(DISABLE_ATAPI) | ||
635 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR */ | ||
636 | { | ||
637 | { | ||
638 | scic_sds_remote_device_default_start_handler, | ||
639 | scic_sds_remote_device_ready_state_stop_handler, | ||
640 | scic_sds_remote_device_default_fail_handler, | ||
641 | scic_sds_remote_device_default_destruct_handler, | ||
642 | scic_sds_remote_device_ready_state_reset_handler, | ||
643 | scic_sds_remote_device_default_reset_complete_handler, | ||
644 | scic_sds_remote_device_default_start_request_handler, | ||
645 | scic_sds_stp_remote_device_complete_request, | ||
646 | scic_sds_remote_device_default_continue_request_handler, | ||
647 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | ||
648 | scic_sds_stp_remote_device_complete_request | ||
649 | }, | ||
650 | scic_sds_remote_device_default_suspend_handler, | ||
651 | scic_sds_remote_device_default_resume_handler, | ||
652 | scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler, | ||
653 | scic_sds_remote_device_general_frame_handler | ||
654 | }, | ||
655 | #endif | ||
656 | /* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET */ | ||
657 | { | ||
658 | { | ||
659 | scic_sds_remote_device_default_start_handler, | ||
660 | scic_sds_remote_device_ready_state_stop_handler, | ||
661 | scic_sds_remote_device_default_fail_handler, | ||
662 | scic_sds_remote_device_default_destruct_handler, | ||
663 | scic_sds_remote_device_ready_state_reset_handler, | ||
664 | scic_sds_remote_device_default_reset_complete_handler, | ||
665 | scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler, | ||
666 | scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler, | ||
667 | scic_sds_remote_device_default_continue_request_handler, | ||
668 | scic_sds_stp_remote_device_ready_substate_start_request_handler, | ||
669 | scic_sds_stp_remote_device_complete_request | ||
670 | }, | ||
671 | scic_sds_remote_device_default_suspend_handler, | ||
672 | scic_sds_remote_device_default_resume_handler, | ||
673 | scic_sds_remote_device_general_event_handler, | ||
674 | scic_sds_remote_device_general_frame_handler | ||
675 | } | ||
676 | }; | ||
677 | |||
678 | /* | ||
679 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
680 | * redistributing this file, you may do so under either license. | ||
681 | * | ||
682 | * GPL LICENSE SUMMARY | ||
683 | * | ||
684 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
685 | * | ||
686 | * This program is free software; you can redistribute it and/or modify | ||
687 | * it under the terms of version 2 of the GNU General Public License as | ||
688 | * published by the Free Software Foundation. | ||
689 | * | ||
690 | * This program is distributed in the hope that it will be useful, but | ||
691 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
692 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
693 | * General Public License for more details. | ||
694 | * | ||
695 | * You should have received a copy of the GNU General Public License | ||
696 | * along with this program; if not, write to the Free Software | ||
697 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
698 | * The full GNU General Public License is included in this distribution | ||
699 | * in the file called LICENSE.GPL. | ||
700 | * | ||
701 | * BSD LICENSE | ||
702 | * | ||
703 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
704 | * All rights reserved. | ||
705 | * | ||
706 | * Redistribution and use in source and binary forms, with or without | ||
707 | * modification, are permitted provided that the following conditions | ||
708 | * are met: | ||
709 | * | ||
710 | * * Redistributions of source code must retain the above copyright | ||
711 | * notice, this list of conditions and the following disclaimer. | ||
712 | * * Redistributions in binary form must reproduce the above copyright | ||
713 | * notice, this list of conditions and the following disclaimer in | ||
714 | * the documentation and/or other materials provided with the | ||
715 | * distribution. | ||
716 | * * Neither the name of Intel Corporation nor the names of its | ||
717 | * contributors may be used to endorse or promote products derived | ||
718 | * from this software without specific prior written permission. | ||
719 | * | ||
720 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
721 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
722 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
723 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
724 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
725 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
726 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
727 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
728 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
729 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
730 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
731 | */ | ||
732 | |||
733 | #include "sci_base_state.h" | ||
734 | #include "scic_remote_device.h" | ||
735 | #include "scic_user_callback.h" | ||
736 | #include "scic_sds_controller.h" | ||
737 | #include "scic_sds_port.h" | ||
738 | #include "scic_sds_remote_device.h" | ||
739 | #include "sci_util.h" | ||
740 | #include "sci_environment.h" | ||
741 | |||
742 | /* | ||
743 | * ***************************************************************************** | ||
744 | * * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS | ||
745 | * ***************************************************************************** */ | ||
746 | |||
747 | static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( | ||
748 | void *user_cookie) | ||
749 | { | ||
750 | struct scic_sds_remote_device *this_device; | ||
751 | |||
752 | this_device = (struct scic_sds_remote_device *)user_cookie; | ||
753 | |||
754 | /* | ||
755 | * For NCQ operation we do not issue a | ||
756 | * scic_cb_remote_device_not_ready(). As a result, avoid sending | ||
757 | * the ready notification. */ | ||
758 | if (this_device->ready_substate_machine.previous_state_id | ||
759 | != SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) { | ||
760 | scic_cb_remote_device_ready( | ||
761 | scic_sds_remote_device_get_controller(this_device), this_device | ||
762 | ); | ||
763 | } | ||
764 | } | ||
765 | |||
766 | /* | ||
767 | * ***************************************************************************** | ||
768 | * * STP REMOTE DEVICE READY IDLE SUBSTATE | ||
769 | * ***************************************************************************** */ | ||
770 | |||
771 | /** | ||
772 | * | ||
773 | * @device: This is the SCI base object which is cast into a | ||
774 | * struct scic_sds_remote_device object. | ||
775 | * | ||
776 | */ | ||
777 | static void scic_sds_stp_remote_device_ready_idle_substate_enter( | ||
778 | struct sci_base_object *device) | ||
779 | { | ||
780 | struct scic_sds_remote_device *this_device; | ||
781 | |||
782 | this_device = (struct scic_sds_remote_device *)device; | ||
783 | |||
784 | SET_STATE_HANDLER( | ||
785 | this_device, | ||
786 | scic_sds_stp_remote_device_ready_substate_handler_table, | ||
787 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE | ||
788 | ); | ||
789 | |||
790 | this_device->working_request = NULL; | ||
791 | |||
792 | if (scic_sds_remote_node_context_is_ready(this_device->rnc)) { | ||
793 | /* | ||
794 | * Since the RNC is ready, it's alright to finish completion | ||
795 | * processing (e.g. signal the remote device is ready). */ | ||
796 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler( | ||
797 | this_device | ||
798 | ); | ||
799 | } else { | ||
800 | scic_sds_remote_node_context_resume( | ||
801 | this_device->rnc, | ||
802 | scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler, | ||
803 | this_device | ||
804 | ); | ||
805 | } | ||
806 | } | ||
807 | |||
808 | /* | ||
809 | * ***************************************************************************** | ||
810 | * * STP REMOTE DEVICE READY CMD SUBSTATE | ||
811 | * ***************************************************************************** */ | ||
812 | |||
813 | /** | ||
814 | * | ||
815 | * @device: This is the SCI base object which is cast into a | ||
816 | * struct scic_sds_remote_device object. | ||
817 | * | ||
818 | */ | ||
819 | static void scic_sds_stp_remote_device_ready_cmd_substate_enter( | ||
820 | struct sci_base_object *device) | ||
821 | { | ||
822 | struct scic_sds_remote_device *this_device; | ||
823 | |||
824 | this_device = (struct scic_sds_remote_device *)device; | ||
825 | |||
826 | BUG_ON(this_device->working_request == NULL); | ||
827 | |||
828 | SET_STATE_HANDLER( | ||
829 | this_device, | ||
830 | scic_sds_stp_remote_device_ready_substate_handler_table, | ||
831 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD | ||
832 | ); | ||
833 | |||
834 | scic_cb_remote_device_not_ready( | ||
835 | scic_sds_remote_device_get_controller(this_device), | ||
836 | this_device, | ||
837 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED | ||
838 | ); | ||
839 | } | ||
840 | |||
841 | /* | ||
842 | * ***************************************************************************** | ||
843 | * * STP REMOTE DEVICE READY NCQ SUBSTATE | ||
844 | * ***************************************************************************** */ | ||
845 | |||
846 | /** | ||
847 | * | ||
848 | * @device: This is the SCI base object which is cast into a | ||
849 | * struct scic_sds_remote_device object. | ||
850 | * | ||
851 | */ | ||
852 | static void scic_sds_stp_remote_device_ready_ncq_substate_enter( | ||
853 | struct sci_base_object *device) | ||
854 | { | ||
855 | struct scic_sds_remote_device *this_device; | ||
856 | |||
857 | this_device = (struct scic_sds_remote_device *)device; | ||
858 | |||
859 | SET_STATE_HANDLER( | ||
860 | this_device, | ||
861 | scic_sds_stp_remote_device_ready_substate_handler_table, | ||
862 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ | ||
863 | ); | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * ***************************************************************************** | ||
868 | * * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE | ||
869 | * ***************************************************************************** */ | ||
870 | |||
871 | /** | ||
872 | * | ||
873 | * @device: This is the SCI base object which is cast into a | ||
874 | * struct scic_sds_remote_device object. | ||
875 | * | ||
876 | */ | ||
877 | static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter( | ||
878 | struct sci_base_object *device) | ||
879 | { | ||
880 | struct scic_sds_remote_device *this_device; | ||
881 | |||
882 | this_device = (struct scic_sds_remote_device *)device; | ||
883 | |||
884 | SET_STATE_HANDLER( | ||
885 | this_device, | ||
886 | scic_sds_stp_remote_device_ready_substate_handler_table, | ||
887 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR | ||
888 | ); | ||
889 | |||
890 | if (this_device->not_ready_reason == | ||
891 | SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) { | ||
892 | scic_cb_remote_device_not_ready( | ||
893 | scic_sds_remote_device_get_controller(this_device), | ||
894 | this_device, | ||
895 | this_device->not_ready_reason | ||
896 | ); | ||
897 | } | ||
898 | } | ||
899 | |||
900 | /* | ||
901 | * ***************************************************************************** | ||
902 | * * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE | ||
903 | * ***************************************************************************** */ | ||
904 | |||
905 | /** | ||
906 | * The enter routine to READY AWAIT RESET substate. | ||
907 | * @device: This is the SCI base object which is cast into a | ||
908 | * struct scic_sds_remote_device object. | ||
909 | * | ||
910 | */ | ||
911 | static void scic_sds_stp_remote_device_ready_await_reset_substate_enter( | ||
912 | struct sci_base_object *device) | ||
913 | { | ||
914 | struct scic_sds_remote_device *this_device; | ||
915 | |||
916 | this_device = (struct scic_sds_remote_device *)device; | ||
917 | |||
918 | SET_STATE_HANDLER( | ||
919 | this_device, | ||
920 | scic_sds_stp_remote_device_ready_substate_handler_table, | ||
921 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET | ||
922 | ); | ||
923 | } | ||
924 | |||
925 | #if !defined(DISABLE_ATAPI) | ||
926 | /* | ||
927 | * ***************************************************************************** | ||
928 | * * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE | ||
929 | * ***************************************************************************** */ | ||
930 | |||
931 | /** | ||
932 | * The enter routine to READY ATAPI ERROR substate. | ||
933 | * @device: This is the SCI base object which is cast into a | ||
934 | * struct scic_sds_remote_device object. | ||
935 | * | ||
936 | */ | ||
937 | void scic_sds_stp_remote_device_ready_atapi_error_substate_enter( | ||
938 | struct sci_base_object *device) | ||
939 | { | ||
940 | struct scic_sds_remote_device *this_device; | ||
941 | |||
942 | this_device = (struct scic_sds_remote_device *)device; | ||
943 | |||
944 | SET_STATE_HANDLER( | ||
945 | this_device, | ||
946 | scic_sds_stp_remote_device_ready_substate_handler_table, | ||
947 | SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR | ||
948 | ); | ||
949 | } | ||
950 | #endif /* !defined(DISABLE_ATAPI) */ | ||
951 | |||
952 | /* --------------------------------------------------------------------------- */ | ||
953 | |||
954 | const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = { | ||
955 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = { | ||
956 | .enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter, | ||
957 | }, | ||
958 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = { | ||
959 | .enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter, | ||
960 | }, | ||
961 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = { | ||
962 | .enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter, | ||
963 | }, | ||
964 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = { | ||
965 | .enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter, | ||
966 | }, | ||
967 | #if !defined(DISABLE_ATAPI) | ||
968 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = { | ||
969 | .enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter, | ||
970 | }, | ||
971 | #endif | ||
972 | [SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = { | ||
973 | .enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter, | ||
974 | }, | ||
975 | }; | ||
diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.c b/drivers/scsi/isci/core/scic_sds_stp_request.c new file mode 100644 index 000000000000..c14f6f10edb1 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_request.c | |||
@@ -0,0 +1,2004 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | |||
57 | #include "intel_ata.h" | ||
58 | #include "intel_sata.h" | ||
59 | #include "intel_sat.h" | ||
60 | #include "sci_base_state.h" | ||
61 | #include "sci_base_state_machine.h" | ||
62 | #include "scic_io_request.h" | ||
63 | #include "scic_remote_device.h" | ||
64 | #include "scic_sds_controller.h" | ||
65 | #include "scic_sds_remote_device.h" | ||
66 | #include "scic_sds_request.h" | ||
67 | #include "scic_sds_stp_pio_request.h" | ||
68 | #include "scic_sds_stp_request.h" | ||
69 | #include "scic_sds_unsolicited_frame_control.h" | ||
70 | #include "scic_user_callback.h" | ||
71 | #include "sci_environment.h" | ||
72 | #include "sci_types.h" | ||
73 | #include "sci_util.h" | ||
74 | #include "scu_completion_codes.h" | ||
75 | #include "scu_event_codes.h" | ||
76 | #include "scu_task_context.h" | ||
77 | |||
78 | /** | ||
79 | * scic_sds_stp_request_get_h2d_reg_buffer() - | ||
80 | * | ||
81 | * This macro returns the address of the stp h2d reg fis buffer in the io | ||
82 | * request memory | ||
83 | */ | ||
84 | #define scic_sds_stp_request_get_h2d_reg_buffer(memory) \ | ||
85 | ((struct sata_fis_reg_h2d *)(\ | ||
86 | ((char *)(memory)) + sizeof(struct scic_sds_stp_request) \ | ||
87 | )) | ||
88 | |||
89 | /** | ||
90 | * scic_sds_stp_request_get_response_buffer() - | ||
91 | * | ||
92 | * This macro returns the address of the ssp response iu buffer in the io | ||
93 | * request memory | ||
94 | */ | ||
95 | #define scic_sds_stp_request_get_response_buffer(memory) \ | ||
96 | ((struct sata_fis_reg_d2h *)(\ | ||
97 | ((char *)(scic_sds_stp_request_get_h2d_reg_buffer(memory))) \ | ||
98 | + sizeof(struct sata_fis_reg_h2d) \ | ||
99 | )) | ||
100 | |||
101 | /** | ||
102 | * scic_sds_stp_request_get_task_context_buffer() - | ||
103 | * | ||
104 | * This macro returns the address of the task context buffer in the io request | ||
105 | * memory | ||
106 | */ | ||
107 | #define scic_sds_stp_request_get_task_context_buffer(memory) \ | ||
108 | ((struct scu_task_context *)(\ | ||
109 | ((char *)(scic_sds_stp_request_get_response_buffer(memory))) \ | ||
110 | + sizeof(struct sci_ssp_response_iu) \ | ||
111 | )) | ||
112 | |||
113 | /** | ||
114 | * scic_sds_stp_request_get_sgl_element_buffer() - | ||
115 | * | ||
116 | * This macro returns the address of the sgl elment pairs in the io request | ||
117 | * memory buffer | ||
118 | */ | ||
119 | #define scic_sds_stp_request_get_sgl_element_buffer(memory) \ | ||
120 | ((struct scu_sgl_element_pair *)(\ | ||
121 | ((char *)(scic_sds_stp_request_get_task_context_buffer(memory))) \ | ||
122 | + sizeof(struct scu_task_context) \ | ||
123 | )) | ||
124 | |||
125 | /** | ||
126 | * | ||
127 | * | ||
128 | * This method return the memory space required for STP PIO requests. u32 | ||
129 | */ | ||
130 | u32 scic_sds_stp_request_get_object_size(void) | ||
131 | { | ||
132 | return sizeof(struct scic_sds_stp_request) | ||
133 | + sizeof(struct sata_fis_reg_h2d) | ||
134 | + sizeof(struct sata_fis_reg_d2h) | ||
135 | + sizeof(struct scu_task_context) | ||
136 | + sizeof(struct scu_sgl_element_pair) * SCU_MAX_SGL_ELEMENT_PAIRS; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * | ||
141 | * | ||
142 | * | ||
143 | */ | ||
144 | void scic_sds_stp_request_assign_buffers( | ||
145 | struct scic_sds_request *request) | ||
146 | { | ||
147 | struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; | ||
148 | |||
149 | this_request->parent.command_buffer = | ||
150 | scic_sds_stp_request_get_h2d_reg_buffer(this_request); | ||
151 | this_request->parent.response_buffer = | ||
152 | scic_sds_stp_request_get_response_buffer(this_request); | ||
153 | this_request->parent.sgl_element_pair_buffer = | ||
154 | scic_sds_stp_request_get_sgl_element_buffer(this_request); | ||
155 | this_request->parent.sgl_element_pair_buffer = | ||
156 | scic_sds_request_align_sgl_element_buffer(this_request->parent.sgl_element_pair_buffer); | ||
157 | |||
158 | if (this_request->parent.was_tag_assigned_by_user == false) { | ||
159 | this_request->parent.task_context_buffer = | ||
160 | scic_sds_stp_request_get_task_context_buffer(this_request); | ||
161 | this_request->parent.task_context_buffer = | ||
162 | scic_sds_request_align_task_context_buffer(this_request->parent.task_context_buffer); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * This method is will fill in the SCU Task Context for any type of SATA | ||
168 | * request. This is called from the various SATA constructors. | ||
169 | * @this_request: The general IO request object which is to be used in | ||
170 | * constructing the SCU task context. | ||
171 | * @task_context: The buffer pointer for the SCU task context which is being | ||
172 | * constructed. | ||
173 | * | ||
174 | * The general io request construction is complete. The buffer assignment for | ||
175 | * the command buffer is complete. none Revisit task context construction to | ||
176 | * determine what is common for SSP/SMP/STP task context structures. | ||
177 | */ | ||
178 | static void scu_sata_reqeust_construct_task_context( | ||
179 | struct scic_sds_request *this_request, | ||
180 | struct scu_task_context *task_context) | ||
181 | { | ||
182 | dma_addr_t physical_address; | ||
183 | struct scic_sds_controller *owning_controller; | ||
184 | struct scic_sds_remote_device *target_device; | ||
185 | struct scic_sds_port *target_port; | ||
186 | |||
187 | owning_controller = scic_sds_request_get_controller(this_request); | ||
188 | target_device = scic_sds_request_get_device(this_request); | ||
189 | target_port = scic_sds_request_get_port(this_request); | ||
190 | |||
191 | /* Fill in the TC with the its required data */ | ||
192 | task_context->abort = 0; | ||
193 | task_context->priority = SCU_TASK_PRIORITY_NORMAL; | ||
194 | task_context->initiator_request = 1; | ||
195 | task_context->connection_rate = | ||
196 | scic_remote_device_get_connection_rate(target_device); | ||
197 | task_context->protocol_engine_index = | ||
198 | scic_sds_controller_get_protocol_engine_group(owning_controller); | ||
199 | task_context->logical_port_index = | ||
200 | scic_sds_port_get_index(target_port); | ||
201 | task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_STP; | ||
202 | task_context->valid = SCU_TASK_CONTEXT_VALID; | ||
203 | task_context->context_type = SCU_TASK_CONTEXT_TYPE; | ||
204 | |||
205 | task_context->remote_node_index = | ||
206 | scic_sds_remote_device_get_index(this_request->target_device); | ||
207 | task_context->command_code = 0; | ||
208 | |||
209 | task_context->link_layer_control = 0; | ||
210 | task_context->do_not_dma_ssp_good_response = 1; | ||
211 | task_context->strict_ordering = 0; | ||
212 | task_context->control_frame = 0; | ||
213 | task_context->timeout_enable = 0; | ||
214 | task_context->block_guard_enable = 0; | ||
215 | |||
216 | task_context->address_modifier = 0; | ||
217 | task_context->task_phase = 0x01; | ||
218 | |||
219 | task_context->ssp_command_iu_length = | ||
220 | (sizeof(struct sata_fis_reg_h2d) - sizeof(u32)) / sizeof(u32); | ||
221 | |||
222 | /* Set the first word of the H2D REG FIS */ | ||
223 | task_context->type.words[0] = *(u32 *)this_request->command_buffer; | ||
224 | |||
225 | if (this_request->was_tag_assigned_by_user) { | ||
226 | /* Build the task context now since we have already read the data */ | ||
227 | this_request->post_context = ( | ||
228 | SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ||
229 | | ( | ||
230 | scic_sds_controller_get_protocol_engine_group(owning_controller) | ||
231 | << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT | ||
232 | ) | ||
233 | | ( | ||
234 | scic_sds_port_get_index(target_port) | ||
235 | << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ||
236 | ) | ||
237 | | scic_sds_io_tag_get_index(this_request->io_tag) | ||
238 | ); | ||
239 | } else { | ||
240 | /* Build the task context now since we have already read the data */ | ||
241 | this_request->post_context = ( | ||
242 | SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC | ||
243 | | ( | ||
244 | scic_sds_controller_get_protocol_engine_group(owning_controller) | ||
245 | << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT | ||
246 | ) | ||
247 | | ( | ||
248 | scic_sds_port_get_index(target_port) | ||
249 | << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | ||
250 | ) | ||
251 | /* This is not assigned because we have to wait until we get a TCi */ | ||
252 | ); | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * Copy the physical address for the command buffer to the SCU Task Context | ||
257 | * We must offset the command buffer by 4 bytes because the first 4 bytes are | ||
258 | * transfered in the body of the TC */ | ||
259 | scic_cb_io_request_get_physical_address( | ||
260 | scic_sds_request_get_controller(this_request), | ||
261 | this_request, | ||
262 | ((char *)this_request->command_buffer) + sizeof(u32), | ||
263 | &physical_address | ||
264 | ); | ||
265 | |||
266 | task_context->command_iu_upper = | ||
267 | upper_32_bits(physical_address); | ||
268 | task_context->command_iu_lower = | ||
269 | lower_32_bits(physical_address); | ||
270 | |||
271 | /* SATA Requests do not have a response buffer */ | ||
272 | task_context->response_iu_upper = 0; | ||
273 | task_context->response_iu_lower = 0; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * | ||
278 | * @this_request: | ||
279 | * | ||
280 | * This method will perform any general sata request construction. What part of | ||
281 | * SATA IO request construction is general? none | ||
282 | */ | ||
283 | void scic_sds_stp_non_ncq_request_construct( | ||
284 | struct scic_sds_request *this_request) | ||
285 | { | ||
286 | this_request->has_started_substate_machine = true; | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * | ||
291 | * @this_request: This parameter specifies the request to be constructed as an | ||
292 | * optimized request. | ||
293 | * @optimized_task_type: This parameter specifies whether the request is to be | ||
294 | * an UDMA request or a NCQ request. - A value of 0 indicates UDMA. - A | ||
295 | * value of 1 indicates NCQ. | ||
296 | * | ||
297 | * This method will perform request construction common to all types of STP | ||
298 | * requests that are optimized by the silicon (i.e. UDMA, NCQ). This method | ||
299 | * returns an indication as to whether the construction was successful. | ||
300 | */ | ||
301 | static void scic_sds_stp_optimized_request_construct( | ||
302 | struct scic_sds_request *this_request, | ||
303 | u8 optimized_task_type, | ||
304 | u32 transfer_length, | ||
305 | SCI_IO_REQUEST_DATA_DIRECTION data_direction) | ||
306 | { | ||
307 | struct scu_task_context *task_context = this_request->task_context_buffer; | ||
308 | |||
309 | /* Build the STP task context structure */ | ||
310 | scu_sata_reqeust_construct_task_context(this_request, task_context); | ||
311 | |||
312 | /* Copy over the SGL elements */ | ||
313 | scic_sds_request_build_sgl(this_request); | ||
314 | |||
315 | /* Copy over the number of bytes to be transfered */ | ||
316 | task_context->transfer_length_bytes = transfer_length; | ||
317 | |||
318 | if (data_direction == SCI_IO_REQUEST_DATA_OUT) { | ||
319 | /* | ||
320 | * The difference between the DMA IN and DMA OUT request task type | ||
321 | * values are consistent with the difference between FPDMA READ | ||
322 | * and FPDMA WRITE values. Add the supplied task type parameter | ||
323 | * to this difference to set the task type properly for this | ||
324 | * DATA OUT (WRITE) case. */ | ||
325 | task_context->task_type = optimized_task_type + (SCU_TASK_TYPE_DMA_OUT | ||
326 | - SCU_TASK_TYPE_DMA_IN); | ||
327 | } else { | ||
328 | /* | ||
329 | * For the DATA IN (READ) case, simply save the supplied | ||
330 | * optimized task type. */ | ||
331 | task_context->task_type = optimized_task_type; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | /** | ||
336 | * | ||
337 | * @this_request: This parameter specifies the request to be constructed. | ||
338 | * | ||
339 | * This method will construct the STP UDMA request and its associated TC data. | ||
340 | * This method returns an indication as to whether the construction was | ||
341 | * successful. SCI_SUCCESS Currently this method always returns this value. | ||
342 | */ | ||
343 | enum sci_status scic_sds_stp_udma_request_construct( | ||
344 | struct scic_sds_request *this_request, | ||
345 | u32 transfer_length, | ||
346 | SCI_IO_REQUEST_DATA_DIRECTION data_direction) | ||
347 | { | ||
348 | scic_sds_stp_non_ncq_request_construct(this_request); | ||
349 | |||
350 | scic_sds_stp_optimized_request_construct( | ||
351 | this_request, | ||
352 | SCU_TASK_TYPE_DMA_IN, | ||
353 | transfer_length, | ||
354 | data_direction | ||
355 | ); | ||
356 | |||
357 | sci_base_state_machine_construct( | ||
358 | &this_request->started_substate_machine, | ||
359 | &this_request->parent.parent, | ||
360 | scic_sds_stp_request_started_udma_substate_table, | ||
361 | SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE | ||
362 | ); | ||
363 | |||
364 | return SCI_SUCCESS; | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * | ||
369 | * @this_request: This parameter specifies the request to be constructed. | ||
370 | * | ||
371 | * This method will construct the STP UDMA request and its associated TC data. | ||
372 | * This method returns an indication as to whether the construction was | ||
373 | * successful. SCI_SUCCESS Currently this method always returns this value. | ||
374 | */ | ||
375 | enum sci_status scic_sds_stp_ncq_request_construct( | ||
376 | struct scic_sds_request *this_request, | ||
377 | u32 transfer_length, | ||
378 | SCI_IO_REQUEST_DATA_DIRECTION data_direction) | ||
379 | { | ||
380 | scic_sds_stp_optimized_request_construct( | ||
381 | this_request, | ||
382 | SCU_TASK_TYPE_FPDMAQ_READ, | ||
383 | transfer_length, | ||
384 | data_direction | ||
385 | ); | ||
386 | return SCI_SUCCESS; | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * | ||
391 | * @this_request: This parameter specifies the STP request object for which to | ||
392 | * construct a RAW command frame task context. | ||
393 | * @task_context: This parameter specifies the SCU specific task context buffer | ||
394 | * to construct. | ||
395 | * | ||
396 | * This method performs the operations common to all SATA/STP requests | ||
397 | * utilizing the raw frame method. none | ||
398 | */ | ||
399 | void scu_stp_raw_request_construct_task_context( | ||
400 | struct scic_sds_stp_request *this_request, | ||
401 | struct scu_task_context *task_context) | ||
402 | { | ||
403 | scu_sata_reqeust_construct_task_context(&this_request->parent, task_context); | ||
404 | |||
405 | task_context->control_frame = 0; | ||
406 | task_context->priority = SCU_TASK_PRIORITY_NORMAL; | ||
407 | task_context->task_type = SCU_TASK_TYPE_SATA_RAW_FRAME; | ||
408 | task_context->type.stp.fis_type = SATA_FIS_TYPE_REGH2D; | ||
409 | task_context->transfer_length_bytes = sizeof(struct sata_fis_reg_h2d) - sizeof(u32); | ||
410 | } | ||
411 | |||
412 | /** | ||
413 | * | ||
414 | * @this_request: This parameter specifies the core request object to | ||
415 | * construction into an STP/SATA non-data request. | ||
416 | * | ||
417 | * This method will construct the STP Non-data request and its associated TC | ||
418 | * data. A non-data request essentially behaves like a 0 length read request | ||
419 | * in the SCU. This method currently always returns SCI_SUCCESS | ||
420 | */ | ||
421 | enum sci_status scic_sds_stp_non_data_request_construct( | ||
422 | struct scic_sds_request *this_request) | ||
423 | { | ||
424 | scic_sds_stp_non_ncq_request_construct(this_request); | ||
425 | |||
426 | /* Build the STP task context structure */ | ||
427 | scu_stp_raw_request_construct_task_context( | ||
428 | (struct scic_sds_stp_request *)this_request, | ||
429 | this_request->task_context_buffer | ||
430 | ); | ||
431 | |||
432 | sci_base_state_machine_construct( | ||
433 | &this_request->started_substate_machine, | ||
434 | &this_request->parent.parent, | ||
435 | scic_sds_stp_request_started_non_data_substate_table, | ||
436 | SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE | ||
437 | ); | ||
438 | |||
439 | return SCI_SUCCESS; | ||
440 | } | ||
441 | |||
442 | |||
443 | enum sci_status scic_sds_stp_soft_reset_request_construct( | ||
444 | struct scic_sds_request *this_request) | ||
445 | { | ||
446 | scic_sds_stp_non_ncq_request_construct(this_request); | ||
447 | |||
448 | /* Build the STP task context structure */ | ||
449 | scu_stp_raw_request_construct_task_context( | ||
450 | (struct scic_sds_stp_request *)this_request, | ||
451 | this_request->task_context_buffer | ||
452 | ); | ||
453 | |||
454 | sci_base_state_machine_construct( | ||
455 | &this_request->started_substate_machine, | ||
456 | &this_request->parent.parent, | ||
457 | scic_sds_stp_request_started_soft_reset_substate_table, | ||
458 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE | ||
459 | ); | ||
460 | |||
461 | return SCI_SUCCESS; | ||
462 | } | ||
463 | |||
464 | |||
465 | void scic_stp_io_request_set_ncq_tag( | ||
466 | struct scic_sds_request *req, | ||
467 | u16 ncq_tag) | ||
468 | { | ||
469 | /** | ||
470 | * @note This could be made to return an error to the user if the user | ||
471 | * attempts to set the NCQ tag in the wrong state. | ||
472 | */ | ||
473 | req->task_context_buffer->type.stp.ncq_tag = ncq_tag; | ||
474 | } | ||
475 | |||
476 | |||
477 | void *scic_stp_io_request_get_h2d_reg_address( | ||
478 | struct scic_sds_request *req) | ||
479 | { | ||
480 | return req->command_buffer; | ||
481 | } | ||
482 | |||
483 | |||
484 | void *scic_stp_io_request_get_d2h_reg_address( | ||
485 | struct scic_sds_request *req) | ||
486 | { | ||
487 | return &((struct scic_sds_stp_request *)req)->d2h_reg_fis; | ||
488 | } | ||
489 | |||
490 | /** | ||
491 | * | ||
492 | * @this_request: | ||
493 | * | ||
494 | * Get the next SGL element from the request. - Check on which SGL element pair | ||
495 | * we are working - if working on SLG pair element A - advance to element B - | ||
496 | * else - check to see if there are more SGL element pairs for this IO request | ||
497 | * - if there are more SGL element pairs - advance to the next pair and return | ||
498 | * element A struct scu_sgl_element* | ||
499 | */ | ||
500 | struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl( | ||
501 | struct scic_sds_stp_request *this_request | ||
502 | ) { | ||
503 | struct scu_sgl_element *current_sgl; | ||
504 | |||
505 | if (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { | ||
506 | if ( | ||
507 | (this_request->type.pio.request_current.sgl_pair->B.address_lower == 0) | ||
508 | && (this_request->type.pio.request_current.sgl_pair->B.address_upper == 0) | ||
509 | ) { | ||
510 | current_sgl = NULL; | ||
511 | } else { | ||
512 | this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_B; | ||
513 | current_sgl = &(this_request->type.pio.request_current.sgl_pair->B); | ||
514 | } | ||
515 | } else { | ||
516 | if ( | ||
517 | (this_request->type.pio.request_current.sgl_pair->next_pair_lower == 0) | ||
518 | && (this_request->type.pio.request_current.sgl_pair->next_pair_upper == 0) | ||
519 | ) { | ||
520 | current_sgl = NULL; | ||
521 | } else { | ||
522 | dma_addr_t physical_address; | ||
523 | |||
524 | sci_cb_make_physical_address( | ||
525 | physical_address, | ||
526 | this_request->type.pio.request_current.sgl_pair->next_pair_upper, | ||
527 | this_request->type.pio.request_current.sgl_pair->next_pair_lower | ||
528 | ); | ||
529 | |||
530 | this_request->type.pio.request_current.sgl_pair = | ||
531 | (struct scu_sgl_element_pair *)scic_cb_get_virtual_address( | ||
532 | this_request->parent.owning_controller, | ||
533 | physical_address | ||
534 | ); | ||
535 | |||
536 | this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; | ||
537 | |||
538 | current_sgl = &(this_request->type.pio.request_current.sgl_pair->A); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | return current_sgl; | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * | ||
547 | * @scic_io_request: The core request object which is cast to a SATA PIO | ||
548 | * request object. | ||
549 | * | ||
550 | * This method will construct the SATA PIO request. This method returns an | ||
551 | * indication as to whether the construction was successful. SCI_SUCCESS | ||
552 | * Currently this method always returns this value. | ||
553 | */ | ||
554 | enum sci_status scic_sds_stp_pio_request_construct( | ||
555 | struct scic_sds_request *scic_io_request, | ||
556 | u8 sat_protocol, | ||
557 | bool copy_rx_frame) | ||
558 | { | ||
559 | struct scic_sds_stp_request *this_request; | ||
560 | |||
561 | this_request = (struct scic_sds_stp_request *)scic_io_request; | ||
562 | |||
563 | scic_sds_stp_non_ncq_request_construct(&this_request->parent); | ||
564 | |||
565 | scu_stp_raw_request_construct_task_context( | ||
566 | this_request, this_request->parent.task_context_buffer | ||
567 | ); | ||
568 | |||
569 | this_request->type.pio.current_transfer_bytes = 0; | ||
570 | this_request->type.pio.ending_error = 0; | ||
571 | this_request->type.pio.ending_status = 0; | ||
572 | |||
573 | this_request->type.pio.request_current.sgl_offset = 0; | ||
574 | this_request->type.pio.request_current.sgl_set = SCU_SGL_ELEMENT_PAIR_A; | ||
575 | this_request->type.pio.sat_protocol = sat_protocol; | ||
576 | |||
577 | if (copy_rx_frame) { | ||
578 | scic_sds_request_build_sgl(&this_request->parent); | ||
579 | /* | ||
580 | * Since the IO request copy of the TC contains the same data as | ||
581 | * the actual TC this pointer is vaild for either. */ | ||
582 | this_request->type.pio.request_current.sgl_pair = | ||
583 | &this_request->parent.task_context_buffer->sgl_pair_ab; | ||
584 | } else { | ||
585 | /* The user does not want the data copied to the SGL buffer location */ | ||
586 | this_request->type.pio.request_current.sgl_pair = NULL; | ||
587 | } | ||
588 | |||
589 | sci_base_state_machine_construct( | ||
590 | &this_request->parent.started_substate_machine, | ||
591 | &this_request->parent.parent.parent, | ||
592 | scic_sds_stp_request_started_pio_substate_table, | ||
593 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE | ||
594 | ); | ||
595 | |||
596 | return SCI_SUCCESS; | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * | ||
601 | * @this_request: | ||
602 | * @completion_code: | ||
603 | * | ||
604 | * This method processes a TC completion. The expected TC completion is for | ||
605 | * the transmission of the H2D register FIS containing the SATA/STP non-data | ||
606 | * request. This method always successfully processes the TC completion. | ||
607 | * SCI_SUCCESS This value is always returned. | ||
608 | */ | ||
609 | static enum sci_status scic_sds_stp_request_non_data_await_h2d_tc_completion_handler( | ||
610 | struct scic_sds_request *this_request, | ||
611 | u32 completion_code) | ||
612 | { | ||
613 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
614 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
615 | scic_sds_request_set_status( | ||
616 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
617 | ); | ||
618 | |||
619 | sci_base_state_machine_change_state( | ||
620 | &this_request->started_substate_machine, | ||
621 | SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE | ||
622 | ); | ||
623 | break; | ||
624 | |||
625 | default: | ||
626 | /* | ||
627 | * All other completion status cause the IO to be complete. If a NAK | ||
628 | * was received, then it is up to the user to retry the request. */ | ||
629 | scic_sds_request_set_status( | ||
630 | this_request, | ||
631 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
632 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
633 | ); | ||
634 | |||
635 | sci_base_state_machine_change_state( | ||
636 | &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED | ||
637 | ); | ||
638 | break; | ||
639 | } | ||
640 | |||
641 | return SCI_SUCCESS; | ||
642 | } | ||
643 | |||
644 | /** | ||
645 | * | ||
646 | * @request: This parameter specifies the request for which a frame has been | ||
647 | * received. | ||
648 | * @frame_index: This parameter specifies the index of the frame that has been | ||
649 | * received. | ||
650 | * | ||
651 | * This method processes frames received from the target while waiting for a | ||
652 | * device to host register FIS. If a non-register FIS is received during this | ||
653 | * time, it is treated as a protocol violation from an IO perspective. Indicate | ||
654 | * if the received frame was processed successfully. | ||
655 | */ | ||
656 | static enum sci_status scic_sds_stp_request_non_data_await_d2h_frame_handler( | ||
657 | struct scic_sds_request *request, | ||
658 | u32 frame_index) | ||
659 | { | ||
660 | enum sci_status status; | ||
661 | struct sata_fis_header *frame_header; | ||
662 | u32 *frame_buffer; | ||
663 | struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; | ||
664 | |||
665 | status = scic_sds_unsolicited_frame_control_get_header( | ||
666 | &(this_request->parent.owning_controller->uf_control), | ||
667 | frame_index, | ||
668 | (void **)&frame_header | ||
669 | ); | ||
670 | |||
671 | if (status == SCI_SUCCESS) { | ||
672 | switch (frame_header->fis_type) { | ||
673 | case SATA_FIS_TYPE_REGD2H: | ||
674 | scic_sds_unsolicited_frame_control_get_buffer( | ||
675 | &(this_request->parent.owning_controller->uf_control), | ||
676 | frame_index, | ||
677 | (void **)&frame_buffer | ||
678 | ); | ||
679 | |||
680 | scic_sds_controller_copy_sata_response( | ||
681 | &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer | ||
682 | ); | ||
683 | |||
684 | /* The command has completed with error */ | ||
685 | scic_sds_request_set_status( | ||
686 | &this_request->parent, | ||
687 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
688 | SCI_FAILURE_IO_RESPONSE_VALID | ||
689 | ); | ||
690 | break; | ||
691 | |||
692 | default: | ||
693 | dev_warn(scic_to_dev(request->owning_controller), | ||
694 | "%s: IO Request:0x%p Frame Id:%d protocol " | ||
695 | "violation occurred\n", | ||
696 | __func__, this_request, frame_index); | ||
697 | |||
698 | scic_sds_request_set_status( | ||
699 | &this_request->parent, | ||
700 | SCU_TASK_DONE_UNEXP_FIS, | ||
701 | SCI_FAILURE_PROTOCOL_VIOLATION | ||
702 | ); | ||
703 | break; | ||
704 | } | ||
705 | |||
706 | sci_base_state_machine_change_state( | ||
707 | &this_request->parent.parent.state_machine, | ||
708 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
709 | ); | ||
710 | |||
711 | /* Frame has been decoded return it to the controller */ | ||
712 | scic_sds_controller_release_frame( | ||
713 | this_request->parent.owning_controller, frame_index | ||
714 | ); | ||
715 | } else | ||
716 | dev_err(scic_to_dev(request->owning_controller), | ||
717 | "%s: SCIC IO Request 0x%p could not get frame header " | ||
718 | "for frame index %d, status %x\n", | ||
719 | __func__, this_request, frame_index, status); | ||
720 | |||
721 | return status; | ||
722 | } | ||
723 | |||
724 | /* --------------------------------------------------------------------------- */ | ||
725 | |||
726 | const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[] = { | ||
727 | [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { | ||
728 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
729 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
730 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
731 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
732 | .tc_completion_handler = scic_sds_stp_request_non_data_await_h2d_tc_completion_handler, | ||
733 | .event_handler = scic_sds_request_default_event_handler, | ||
734 | .frame_handler = scic_sds_request_default_frame_handler, | ||
735 | }, | ||
736 | [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { | ||
737 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
738 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
739 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
740 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
741 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
742 | .event_handler = scic_sds_request_default_event_handler, | ||
743 | .frame_handler = scic_sds_stp_request_non_data_await_d2h_frame_handler, | ||
744 | } | ||
745 | }; | ||
746 | |||
747 | static void scic_sds_stp_request_started_non_data_await_h2d_completion_enter( | ||
748 | struct sci_base_object *object) | ||
749 | { | ||
750 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
751 | |||
752 | SET_STATE_HANDLER( | ||
753 | this_request, | ||
754 | scic_sds_stp_request_started_non_data_substate_handler_table, | ||
755 | SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE | ||
756 | ); | ||
757 | |||
758 | scic_sds_remote_device_set_working_request( | ||
759 | this_request->target_device, this_request | ||
760 | ); | ||
761 | } | ||
762 | |||
763 | static void scic_sds_stp_request_started_non_data_await_d2h_enter( | ||
764 | struct sci_base_object *object) | ||
765 | { | ||
766 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
767 | |||
768 | SET_STATE_HANDLER( | ||
769 | this_request, | ||
770 | scic_sds_stp_request_started_non_data_substate_handler_table, | ||
771 | SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE | ||
772 | ); | ||
773 | } | ||
774 | |||
775 | /* --------------------------------------------------------------------------- */ | ||
776 | |||
777 | const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[] = { | ||
778 | [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE] = { | ||
779 | .enter_state = scic_sds_stp_request_started_non_data_await_h2d_completion_enter, | ||
780 | }, | ||
781 | [SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE] = { | ||
782 | .enter_state = scic_sds_stp_request_started_non_data_await_d2h_enter, | ||
783 | }, | ||
784 | }; | ||
785 | |||
786 | #define SCU_MAX_FRAME_BUFFER_SIZE 0x400 /* 1K is the maximum SCU frame data payload */ | ||
787 | |||
788 | /** | ||
789 | * | ||
790 | * @this_request: | ||
791 | * @length: | ||
792 | * | ||
793 | * This function will transmit DATA_FIS from (current sgl + offset) for input | ||
794 | * parameter length. current sgl and offset is alreay stored in the IO request | ||
795 | * enum sci_status | ||
796 | */ | ||
797 | |||
798 | static enum sci_status scic_sds_stp_request_pio_data_out_trasmit_data_frame( | ||
799 | struct scic_sds_request *this_request, | ||
800 | u32 length) | ||
801 | { | ||
802 | struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_request; | ||
803 | sci_base_controller_request_handler_t continue_io; | ||
804 | struct scu_sgl_element *current_sgl; | ||
805 | struct scic_sds_controller *scic; | ||
806 | u32 state; | ||
807 | |||
808 | /* | ||
809 | * Recycle the TC and reconstruct it for sending out DATA FIS containing | ||
810 | * for the data from current_sgl+offset for the input length */ | ||
811 | struct scu_task_context *task_context = scic_sds_controller_get_task_context_buffer( | ||
812 | this_request->owning_controller, | ||
813 | this_request->io_tag | ||
814 | ); | ||
815 | |||
816 | if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) | ||
817 | current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); | ||
818 | else | ||
819 | current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); | ||
820 | |||
821 | /* update the TC */ | ||
822 | task_context->command_iu_upper = current_sgl->address_upper; | ||
823 | task_context->command_iu_lower = current_sgl->address_lower; | ||
824 | task_context->transfer_length_bytes = length; | ||
825 | task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA; | ||
826 | |||
827 | /* send the new TC out. */ | ||
828 | scic = this_request->owning_controller; | ||
829 | state = scic->parent.state_machine.current_state_id; | ||
830 | continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; | ||
831 | return continue_io(&scic->parent, &this_request->target_device->parent, | ||
832 | &this_request->parent); | ||
833 | } | ||
834 | |||
835 | /** | ||
836 | * | ||
837 | * @this_request: | ||
838 | * | ||
839 | * enum sci_status | ||
840 | */ | ||
841 | static enum sci_status scic_sds_stp_request_pio_data_out_transmit_data( | ||
842 | struct scic_sds_request *this_sds_request) | ||
843 | { | ||
844 | |||
845 | struct scu_sgl_element *current_sgl; | ||
846 | u32 sgl_offset; | ||
847 | u32 remaining_bytes_in_current_sgl = 0; | ||
848 | enum sci_status status = SCI_SUCCESS; | ||
849 | |||
850 | struct scic_sds_stp_request *this_sds_stp_request = (struct scic_sds_stp_request *)this_sds_request; | ||
851 | |||
852 | sgl_offset = this_sds_stp_request->type.pio.request_current.sgl_offset; | ||
853 | |||
854 | if (this_sds_stp_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) { | ||
855 | current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->A); | ||
856 | remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->A.length - sgl_offset; | ||
857 | } else { | ||
858 | current_sgl = &(this_sds_stp_request->type.pio.request_current.sgl_pair->B); | ||
859 | remaining_bytes_in_current_sgl = this_sds_stp_request->type.pio.request_current.sgl_pair->B.length - sgl_offset; | ||
860 | } | ||
861 | |||
862 | |||
863 | if (this_sds_stp_request->type.pio.pio_transfer_bytes > 0) { | ||
864 | if (this_sds_stp_request->type.pio.pio_transfer_bytes >= remaining_bytes_in_current_sgl) { | ||
865 | /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = remaining_bytes_in_current_sgl */ | ||
866 | status = scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, remaining_bytes_in_current_sgl); | ||
867 | if (status == SCI_SUCCESS) { | ||
868 | this_sds_stp_request->type.pio.pio_transfer_bytes -= remaining_bytes_in_current_sgl; | ||
869 | |||
870 | /* update the current sgl, sgl_offset and save for future */ | ||
871 | current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_sds_stp_request); | ||
872 | sgl_offset = 0; | ||
873 | } | ||
874 | } else if (this_sds_stp_request->type.pio.pio_transfer_bytes < remaining_bytes_in_current_sgl) { | ||
875 | /* recycle the TC and send the H2D Data FIS from (current sgl + sgl_offset) and length = type.pio.pio_transfer_bytes */ | ||
876 | scic_sds_stp_request_pio_data_out_trasmit_data_frame(this_sds_request, this_sds_stp_request->type.pio.pio_transfer_bytes); | ||
877 | |||
878 | if (status == SCI_SUCCESS) { | ||
879 | /* Sgl offset will be adjusted and saved for future */ | ||
880 | sgl_offset += this_sds_stp_request->type.pio.pio_transfer_bytes; | ||
881 | current_sgl->address_lower += this_sds_stp_request->type.pio.pio_transfer_bytes; | ||
882 | this_sds_stp_request->type.pio.pio_transfer_bytes = 0; | ||
883 | } | ||
884 | } | ||
885 | } | ||
886 | |||
887 | if (status == SCI_SUCCESS) { | ||
888 | this_sds_stp_request->type.pio.request_current.sgl_offset = sgl_offset; | ||
889 | } | ||
890 | |||
891 | return status; | ||
892 | } | ||
893 | |||
894 | /** | ||
895 | * | ||
896 | * @this_request: The request that is used for the SGL processing. | ||
897 | * @data_buffer: The buffer of data to be copied. | ||
898 | * @length: The length of the data transfer. | ||
899 | * | ||
900 | * Copy the data from the buffer for the length specified to the IO reqeust SGL | ||
901 | * specified data region. enum sci_status | ||
902 | */ | ||
903 | static enum sci_status scic_sds_stp_request_pio_data_in_copy_data_buffer( | ||
904 | struct scic_sds_stp_request *this_request, | ||
905 | u8 *data_buffer, | ||
906 | u32 length) | ||
907 | { | ||
908 | enum sci_status status; | ||
909 | struct scu_sgl_element *current_sgl; | ||
910 | u32 sgl_offset; | ||
911 | u32 data_offset; | ||
912 | u8 *source_address; | ||
913 | u8 *destination_address; | ||
914 | u32 copy_length; | ||
915 | |||
916 | /* Initial setup to get the current working SGL and the offset within the buffer */ | ||
917 | current_sgl = | ||
918 | (this_request->type.pio.request_current.sgl_set == SCU_SGL_ELEMENT_PAIR_A) ? | ||
919 | &(this_request->type.pio.request_current.sgl_pair->A) : | ||
920 | &(this_request->type.pio.request_current.sgl_pair->B); | ||
921 | |||
922 | sgl_offset = this_request->type.pio.request_current.sgl_offset; | ||
923 | |||
924 | source_address = data_buffer; | ||
925 | data_offset = 0; | ||
926 | |||
927 | status = SCI_SUCCESS; | ||
928 | |||
929 | /* While we are still doing Ok and there is more data to transfer */ | ||
930 | while ( | ||
931 | (length > 0) | ||
932 | && (status == SCI_SUCCESS) | ||
933 | ) { | ||
934 | if (current_sgl->length == sgl_offset) { | ||
935 | /* This SGL has been exauhasted so we need to get the next SGL */ | ||
936 | current_sgl = scic_sds_stp_request_pio_get_next_sgl(this_request); | ||
937 | |||
938 | if (current_sgl == NULL) | ||
939 | status = SCI_FAILURE; | ||
940 | else | ||
941 | sgl_offset = 0; | ||
942 | } else { | ||
943 | dma_addr_t physical_address; | ||
944 | |||
945 | sci_cb_make_physical_address( | ||
946 | physical_address, | ||
947 | current_sgl->address_upper, | ||
948 | current_sgl->address_lower | ||
949 | ); | ||
950 | |||
951 | destination_address = (u8 *)scic_cb_get_virtual_address( | ||
952 | this_request->parent.owning_controller, | ||
953 | physical_address | ||
954 | ); | ||
955 | |||
956 | source_address += data_offset; | ||
957 | destination_address += sgl_offset; | ||
958 | |||
959 | copy_length = min(length, current_sgl->length - sgl_offset); | ||
960 | |||
961 | memcpy(destination_address, source_address, copy_length); | ||
962 | |||
963 | length -= copy_length; | ||
964 | sgl_offset += copy_length; | ||
965 | data_offset += copy_length; | ||
966 | } | ||
967 | } | ||
968 | |||
969 | this_request->type.pio.request_current.sgl_offset = sgl_offset; | ||
970 | |||
971 | return status; | ||
972 | } | ||
973 | |||
974 | /** | ||
975 | * | ||
976 | * @this_request: The PIO DATA IN request that is to receive the data. | ||
977 | * @data_buffer: The buffer to copy from. | ||
978 | * | ||
979 | * Copy the data buffer to the io request data region. enum sci_status | ||
980 | */ | ||
981 | static enum sci_status scic_sds_stp_request_pio_data_in_copy_data( | ||
982 | struct scic_sds_stp_request *this_request, | ||
983 | u8 *data_buffer) | ||
984 | { | ||
985 | enum sci_status status; | ||
986 | |||
987 | /* | ||
988 | * If there is less than 1K remaining in the transfer request | ||
989 | * copy just the data for the transfer */ | ||
990 | if (this_request->type.pio.pio_transfer_bytes < SCU_MAX_FRAME_BUFFER_SIZE) { | ||
991 | status = scic_sds_stp_request_pio_data_in_copy_data_buffer( | ||
992 | this_request, data_buffer, this_request->type.pio.pio_transfer_bytes); | ||
993 | |||
994 | if (status == SCI_SUCCESS) | ||
995 | this_request->type.pio.pio_transfer_bytes = 0; | ||
996 | } else { | ||
997 | /* We are transfering the whole frame so copy */ | ||
998 | status = scic_sds_stp_request_pio_data_in_copy_data_buffer( | ||
999 | this_request, data_buffer, SCU_MAX_FRAME_BUFFER_SIZE); | ||
1000 | |||
1001 | if (status == SCI_SUCCESS) | ||
1002 | this_request->type.pio.pio_transfer_bytes -= SCU_MAX_FRAME_BUFFER_SIZE; | ||
1003 | } | ||
1004 | |||
1005 | return status; | ||
1006 | } | ||
1007 | |||
1008 | /** | ||
1009 | * | ||
1010 | * @this_request: | ||
1011 | * @completion_code: | ||
1012 | * | ||
1013 | * enum sci_status | ||
1014 | */ | ||
1015 | static enum sci_status scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler( | ||
1016 | struct scic_sds_request *this_request, | ||
1017 | u32 completion_code) | ||
1018 | { | ||
1019 | enum sci_status status = SCI_SUCCESS; | ||
1020 | |||
1021 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1022 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1023 | scic_sds_request_set_status( | ||
1024 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1025 | ); | ||
1026 | |||
1027 | sci_base_state_machine_change_state( | ||
1028 | &this_request->started_substate_machine, | ||
1029 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE | ||
1030 | ); | ||
1031 | break; | ||
1032 | |||
1033 | default: | ||
1034 | /* | ||
1035 | * All other completion status cause the IO to be complete. If a NAK | ||
1036 | * was received, then it is up to the user to retry the request. */ | ||
1037 | scic_sds_request_set_status( | ||
1038 | this_request, | ||
1039 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1040 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1041 | ); | ||
1042 | |||
1043 | sci_base_state_machine_change_state( | ||
1044 | &this_request->parent.state_machine, | ||
1045 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1046 | ); | ||
1047 | break; | ||
1048 | } | ||
1049 | |||
1050 | return status; | ||
1051 | } | ||
1052 | |||
1053 | /** | ||
1054 | * | ||
1055 | * @this_request: | ||
1056 | * @frame_index: | ||
1057 | * | ||
1058 | * enum sci_status | ||
1059 | */ | ||
1060 | static enum sci_status scic_sds_stp_request_pio_await_frame_frame_handler( | ||
1061 | struct scic_sds_request *request, | ||
1062 | u32 frame_index) | ||
1063 | { | ||
1064 | enum sci_status status; | ||
1065 | struct sata_fis_header *frame_header; | ||
1066 | u32 *frame_buffer; | ||
1067 | struct scic_sds_stp_request *this_request; | ||
1068 | |||
1069 | this_request = (struct scic_sds_stp_request *)request; | ||
1070 | |||
1071 | status = scic_sds_unsolicited_frame_control_get_header( | ||
1072 | &(this_request->parent.owning_controller->uf_control), | ||
1073 | frame_index, | ||
1074 | (void **)&frame_header | ||
1075 | ); | ||
1076 | |||
1077 | if (status == SCI_SUCCESS) { | ||
1078 | switch (frame_header->fis_type) { | ||
1079 | case SATA_FIS_TYPE_PIO_SETUP: | ||
1080 | /* Get from the frame buffer the PIO Setup Data */ | ||
1081 | scic_sds_unsolicited_frame_control_get_buffer( | ||
1082 | &(this_request->parent.owning_controller->uf_control), | ||
1083 | frame_index, | ||
1084 | (void **)&frame_buffer | ||
1085 | ); | ||
1086 | |||
1087 | /* | ||
1088 | * Get the data from the PIO Setup | ||
1089 | * The SCU Hardware returns first word in the frame_header and the rest | ||
1090 | * of the data is in the frame buffer so we need to back up one dword */ | ||
1091 | this_request->type.pio.pio_transfer_bytes = | ||
1092 | (u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count; | ||
1093 | this_request->type.pio.ending_status = | ||
1094 | (u8)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->ending_status; | ||
1095 | |||
1096 | scic_sds_controller_copy_sata_response( | ||
1097 | &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer | ||
1098 | ); | ||
1099 | |||
1100 | this_request->d2h_reg_fis.status = | ||
1101 | this_request->type.pio.ending_status; | ||
1102 | |||
1103 | /* The next state is dependent on whether the request was PIO Data-in or Data out */ | ||
1104 | if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_IN) { | ||
1105 | sci_base_state_machine_change_state( | ||
1106 | &this_request->parent.started_substate_machine, | ||
1107 | SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE | ||
1108 | ); | ||
1109 | } else if (this_request->type.pio.sat_protocol == SAT_PROTOCOL_PIO_DATA_OUT) { | ||
1110 | /* Transmit data */ | ||
1111 | status = scic_sds_stp_request_pio_data_out_transmit_data(request); | ||
1112 | if (status == SCI_SUCCESS) { | ||
1113 | sci_base_state_machine_change_state( | ||
1114 | &this_request->parent.started_substate_machine, | ||
1115 | SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE | ||
1116 | ); | ||
1117 | } | ||
1118 | } | ||
1119 | break; | ||
1120 | |||
1121 | case SATA_FIS_TYPE_SETDEVBITS: | ||
1122 | sci_base_state_machine_change_state( | ||
1123 | &this_request->parent.started_substate_machine, | ||
1124 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE | ||
1125 | ); | ||
1126 | break; | ||
1127 | |||
1128 | case SATA_FIS_TYPE_REGD2H: | ||
1129 | if ((frame_header->status & ATA_STATUS_REG_BSY_BIT) == 0) { | ||
1130 | scic_sds_unsolicited_frame_control_get_buffer( | ||
1131 | &(this_request->parent.owning_controller->uf_control), | ||
1132 | frame_index, | ||
1133 | (void **)&frame_buffer | ||
1134 | ); | ||
1135 | |||
1136 | scic_sds_controller_copy_sata_response( | ||
1137 | &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer); | ||
1138 | |||
1139 | scic_sds_request_set_status( | ||
1140 | &this_request->parent, | ||
1141 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1142 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1143 | ); | ||
1144 | |||
1145 | sci_base_state_machine_change_state( | ||
1146 | &this_request->parent.parent.state_machine, | ||
1147 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1148 | ); | ||
1149 | } else { | ||
1150 | /* | ||
1151 | * Now why is the drive sending a D2H Register FIS when it is still busy? | ||
1152 | * Do nothing since we are still in the right state. */ | ||
1153 | dev_dbg(scic_to_dev(request->owning_controller), | ||
1154 | "%s: SCIC PIO Request 0x%p received " | ||
1155 | "D2H Register FIS with BSY status " | ||
1156 | "0x%x\n", | ||
1157 | __func__, | ||
1158 | this_request, | ||
1159 | frame_header->status); | ||
1160 | } | ||
1161 | break; | ||
1162 | |||
1163 | default: | ||
1164 | break; | ||
1165 | } | ||
1166 | |||
1167 | /* Frame is decoded return it to the controller */ | ||
1168 | scic_sds_controller_release_frame( | ||
1169 | this_request->parent.owning_controller, | ||
1170 | frame_index | ||
1171 | ); | ||
1172 | } else | ||
1173 | dev_err(scic_to_dev(request->owning_controller), | ||
1174 | "%s: SCIC IO Request 0x%p could not get frame header " | ||
1175 | "for frame index %d, status %x\n", | ||
1176 | __func__, this_request, frame_index, status); | ||
1177 | |||
1178 | return status; | ||
1179 | } | ||
1180 | |||
1181 | /** | ||
1182 | * | ||
1183 | * @this_request: | ||
1184 | * @frame_index: | ||
1185 | * | ||
1186 | * enum sci_status | ||
1187 | */ | ||
1188 | static enum sci_status scic_sds_stp_request_pio_data_in_await_data_frame_handler( | ||
1189 | struct scic_sds_request *request, | ||
1190 | u32 frame_index) | ||
1191 | { | ||
1192 | enum sci_status status; | ||
1193 | struct sata_fis_header *frame_header; | ||
1194 | struct sata_fis_data *frame_buffer; | ||
1195 | struct scic_sds_stp_request *this_request; | ||
1196 | |||
1197 | this_request = (struct scic_sds_stp_request *)request; | ||
1198 | |||
1199 | status = scic_sds_unsolicited_frame_control_get_header( | ||
1200 | &(this_request->parent.owning_controller->uf_control), | ||
1201 | frame_index, | ||
1202 | (void **)&frame_header | ||
1203 | ); | ||
1204 | |||
1205 | if (status == SCI_SUCCESS) { | ||
1206 | if (frame_header->fis_type == SATA_FIS_TYPE_DATA) { | ||
1207 | if (this_request->type.pio.request_current.sgl_pair == NULL) { | ||
1208 | this_request->parent.saved_rx_frame_index = frame_index; | ||
1209 | this_request->type.pio.pio_transfer_bytes = 0; | ||
1210 | } else { | ||
1211 | status = scic_sds_unsolicited_frame_control_get_buffer( | ||
1212 | &(this_request->parent.owning_controller->uf_control), | ||
1213 | frame_index, | ||
1214 | (void **)&frame_buffer | ||
1215 | ); | ||
1216 | |||
1217 | status = scic_sds_stp_request_pio_data_in_copy_data(this_request, (u8 *)frame_buffer); | ||
1218 | |||
1219 | /* Frame is decoded return it to the controller */ | ||
1220 | scic_sds_controller_release_frame( | ||
1221 | this_request->parent.owning_controller, | ||
1222 | frame_index | ||
1223 | ); | ||
1224 | } | ||
1225 | |||
1226 | /* | ||
1227 | * Check for the end of the transfer, are there more bytes remaining | ||
1228 | * for this data transfer */ | ||
1229 | if ( | ||
1230 | (status == SCI_SUCCESS) | ||
1231 | && (this_request->type.pio.pio_transfer_bytes == 0) | ||
1232 | ) { | ||
1233 | if ((this_request->type.pio.ending_status & ATA_STATUS_REG_BSY_BIT) == 0) { | ||
1234 | scic_sds_request_set_status( | ||
1235 | &this_request->parent, | ||
1236 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1237 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1238 | ); | ||
1239 | |||
1240 | sci_base_state_machine_change_state( | ||
1241 | &this_request->parent.parent.state_machine, | ||
1242 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1243 | ); | ||
1244 | } else { | ||
1245 | sci_base_state_machine_change_state( | ||
1246 | &this_request->parent.started_substate_machine, | ||
1247 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE | ||
1248 | ); | ||
1249 | } | ||
1250 | } | ||
1251 | } else { | ||
1252 | dev_err(scic_to_dev(request->owning_controller), | ||
1253 | "%s: SCIC PIO Request 0x%p received frame %d " | ||
1254 | "with fis type 0x%02x when expecting a data " | ||
1255 | "fis.\n", | ||
1256 | __func__, | ||
1257 | this_request, | ||
1258 | frame_index, | ||
1259 | frame_header->fis_type); | ||
1260 | |||
1261 | scic_sds_request_set_status( | ||
1262 | &this_request->parent, | ||
1263 | SCU_TASK_DONE_GOOD, | ||
1264 | SCI_FAILURE_IO_REQUIRES_SCSI_ABORT | ||
1265 | ); | ||
1266 | |||
1267 | sci_base_state_machine_change_state( | ||
1268 | &this_request->parent.parent.state_machine, | ||
1269 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1270 | ); | ||
1271 | |||
1272 | /* Frame is decoded return it to the controller */ | ||
1273 | scic_sds_controller_release_frame( | ||
1274 | this_request->parent.owning_controller, | ||
1275 | frame_index | ||
1276 | ); | ||
1277 | } | ||
1278 | } else | ||
1279 | dev_err(scic_to_dev(request->owning_controller), | ||
1280 | "%s: SCIC IO Request 0x%p could not get frame header " | ||
1281 | "for frame index %d, status %x\n", | ||
1282 | __func__, this_request, frame_index, status); | ||
1283 | |||
1284 | return status; | ||
1285 | } | ||
1286 | |||
1287 | |||
1288 | /** | ||
1289 | * | ||
1290 | * @this_request: | ||
1291 | * @completion_code: | ||
1292 | * | ||
1293 | * enum sci_status | ||
1294 | */ | ||
1295 | static enum sci_status scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler( | ||
1296 | |||
1297 | struct scic_sds_request *this_request, | ||
1298 | u32 completion_code) | ||
1299 | { | ||
1300 | enum sci_status status = SCI_SUCCESS; | ||
1301 | bool all_frames_transferred = false; | ||
1302 | |||
1303 | struct scic_sds_stp_request *this_scic_sds_stp_request = (struct scic_sds_stp_request *)this_request; | ||
1304 | |||
1305 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1306 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1307 | /* Transmit data */ | ||
1308 | if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes != 0) { | ||
1309 | status = scic_sds_stp_request_pio_data_out_transmit_data(this_request); | ||
1310 | if (status == SCI_SUCCESS) { | ||
1311 | if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) | ||
1312 | all_frames_transferred = true; | ||
1313 | } | ||
1314 | } else if (this_scic_sds_stp_request->type.pio.pio_transfer_bytes == 0) { | ||
1315 | /* | ||
1316 | * this will happen if the all data is written at the | ||
1317 | * first time after the pio setup fis is received | ||
1318 | */ | ||
1319 | all_frames_transferred = true; | ||
1320 | } | ||
1321 | |||
1322 | /* all data transferred. */ | ||
1323 | if (all_frames_transferred) { | ||
1324 | /* | ||
1325 | * Change the state to SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_FRAME_SUBSTATE | ||
1326 | * and wait for PIO_SETUP fis / or D2H REg fis. */ | ||
1327 | sci_base_state_machine_change_state( | ||
1328 | &this_request->started_substate_machine, | ||
1329 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE | ||
1330 | ); | ||
1331 | } | ||
1332 | break; | ||
1333 | |||
1334 | default: | ||
1335 | /* | ||
1336 | * All other completion status cause the IO to be complete. If a NAK | ||
1337 | * was received, then it is up to the user to retry the request. */ | ||
1338 | scic_sds_request_set_status( | ||
1339 | this_request, | ||
1340 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1341 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1342 | ); | ||
1343 | |||
1344 | sci_base_state_machine_change_state( | ||
1345 | &this_request->parent.state_machine, | ||
1346 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1347 | ); | ||
1348 | break; | ||
1349 | } | ||
1350 | |||
1351 | return status; | ||
1352 | } | ||
1353 | |||
1354 | /** | ||
1355 | * | ||
1356 | * @request: This is the request which is receiving the event. | ||
1357 | * @event_code: This is the event code that the request on which the request is | ||
1358 | * expected to take action. | ||
1359 | * | ||
1360 | * This method will handle any link layer events while waiting for the data | ||
1361 | * frame. enum sci_status SCI_SUCCESS SCI_FAILURE | ||
1362 | */ | ||
1363 | static enum sci_status scic_sds_stp_request_pio_data_in_await_data_event_handler( | ||
1364 | struct scic_sds_request *request, | ||
1365 | u32 event_code) | ||
1366 | { | ||
1367 | enum sci_status status; | ||
1368 | |||
1369 | switch (scu_get_event_specifier(event_code)) { | ||
1370 | case SCU_TASK_DONE_CRC_ERR << SCU_EVENT_SPECIFIC_CODE_SHIFT: | ||
1371 | /* | ||
1372 | * We are waiting for data and the SCU has R_ERR the data frame. | ||
1373 | * Go back to waiting for the D2H Register FIS */ | ||
1374 | sci_base_state_machine_change_state( | ||
1375 | &request->started_substate_machine, | ||
1376 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE | ||
1377 | ); | ||
1378 | |||
1379 | status = SCI_SUCCESS; | ||
1380 | break; | ||
1381 | |||
1382 | default: | ||
1383 | dev_err(scic_to_dev(request->owning_controller), | ||
1384 | "%s: SCIC PIO Request 0x%p received unexpected " | ||
1385 | "event 0x%08x\n", | ||
1386 | __func__, request, event_code); | ||
1387 | |||
1388 | /* / @todo Should we fail the PIO request when we get an unexpected event? */ | ||
1389 | status = SCI_FAILURE; | ||
1390 | break; | ||
1391 | } | ||
1392 | |||
1393 | return status; | ||
1394 | } | ||
1395 | |||
1396 | /* --------------------------------------------------------------------------- */ | ||
1397 | |||
1398 | const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[] = { | ||
1399 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { | ||
1400 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1401 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1402 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1403 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1404 | .tc_completion_handler = scic_sds_stp_request_pio_await_h2d_completion_tc_completion_handler, | ||
1405 | .event_handler = scic_sds_request_default_event_handler, | ||
1406 | .frame_handler = scic_sds_request_default_frame_handler | ||
1407 | }, | ||
1408 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { | ||
1409 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1410 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1411 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1412 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1413 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1414 | .event_handler = scic_sds_request_default_event_handler, | ||
1415 | .frame_handler = scic_sds_stp_request_pio_await_frame_frame_handler | ||
1416 | }, | ||
1417 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { | ||
1418 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1419 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1420 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1421 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1422 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1423 | .event_handler = scic_sds_stp_request_pio_data_in_await_data_event_handler, | ||
1424 | .frame_handler = scic_sds_stp_request_pio_data_in_await_data_frame_handler | ||
1425 | }, | ||
1426 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { | ||
1427 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1428 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1429 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1430 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1431 | .tc_completion_handler = scic_sds_stp_request_pio_data_out_await_data_transmit_completion_tc_completion_handler, | ||
1432 | .event_handler = scic_sds_request_default_event_handler, | ||
1433 | .frame_handler = scic_sds_request_default_frame_handler, | ||
1434 | } | ||
1435 | }; | ||
1436 | |||
1437 | static void scic_sds_stp_request_started_pio_await_h2d_completion_enter( | ||
1438 | struct sci_base_object *object) | ||
1439 | { | ||
1440 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1441 | |||
1442 | SET_STATE_HANDLER( | ||
1443 | this_request, | ||
1444 | scic_sds_stp_request_started_pio_substate_handler_table, | ||
1445 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE | ||
1446 | ); | ||
1447 | |||
1448 | scic_sds_remote_device_set_working_request( | ||
1449 | this_request->target_device, this_request); | ||
1450 | } | ||
1451 | |||
1452 | static void scic_sds_stp_request_started_pio_await_frame_enter( | ||
1453 | struct sci_base_object *object) | ||
1454 | { | ||
1455 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1456 | |||
1457 | SET_STATE_HANDLER( | ||
1458 | this_request, | ||
1459 | scic_sds_stp_request_started_pio_substate_handler_table, | ||
1460 | SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE | ||
1461 | ); | ||
1462 | } | ||
1463 | |||
1464 | static void scic_sds_stp_request_started_pio_data_in_await_data_enter( | ||
1465 | struct sci_base_object *object) | ||
1466 | { | ||
1467 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1468 | |||
1469 | SET_STATE_HANDLER( | ||
1470 | this_request, | ||
1471 | scic_sds_stp_request_started_pio_substate_handler_table, | ||
1472 | SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE | ||
1473 | ); | ||
1474 | } | ||
1475 | |||
1476 | static void scic_sds_stp_request_started_pio_data_out_transmit_data_enter( | ||
1477 | struct sci_base_object *object) | ||
1478 | { | ||
1479 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1480 | |||
1481 | SET_STATE_HANDLER( | ||
1482 | this_request, | ||
1483 | scic_sds_stp_request_started_pio_substate_handler_table, | ||
1484 | SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE | ||
1485 | ); | ||
1486 | } | ||
1487 | |||
1488 | /* --------------------------------------------------------------------------- */ | ||
1489 | |||
1490 | const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[] = { | ||
1491 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE] = { | ||
1492 | .enter_state = scic_sds_stp_request_started_pio_await_h2d_completion_enter, | ||
1493 | }, | ||
1494 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE] = { | ||
1495 | .enter_state = scic_sds_stp_request_started_pio_await_frame_enter, | ||
1496 | }, | ||
1497 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE] = { | ||
1498 | .enter_state = scic_sds_stp_request_started_pio_data_in_await_data_enter, | ||
1499 | }, | ||
1500 | [SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE] = { | ||
1501 | .enter_state = scic_sds_stp_request_started_pio_data_out_transmit_data_enter, | ||
1502 | } | ||
1503 | }; | ||
1504 | |||
1505 | static void scic_sds_stp_request_udma_complete_request( | ||
1506 | struct scic_sds_request *this_request, | ||
1507 | u32 scu_status, | ||
1508 | enum sci_status sci_status) | ||
1509 | { | ||
1510 | scic_sds_request_set_status( | ||
1511 | this_request, scu_status, sci_status | ||
1512 | ); | ||
1513 | |||
1514 | sci_base_state_machine_change_state( | ||
1515 | &this_request->parent.state_machine, | ||
1516 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1517 | ); | ||
1518 | } | ||
1519 | |||
1520 | /** | ||
1521 | * | ||
1522 | * @this_request: | ||
1523 | * @frame_index: | ||
1524 | * | ||
1525 | * enum sci_status | ||
1526 | */ | ||
1527 | static enum sci_status scic_sds_stp_request_udma_general_frame_handler( | ||
1528 | struct scic_sds_request *this_request, | ||
1529 | u32 frame_index) | ||
1530 | { | ||
1531 | enum sci_status status; | ||
1532 | struct sata_fis_header *frame_header; | ||
1533 | u32 *frame_buffer; | ||
1534 | |||
1535 | status = scic_sds_unsolicited_frame_control_get_header( | ||
1536 | &this_request->owning_controller->uf_control, | ||
1537 | frame_index, | ||
1538 | (void **)&frame_header | ||
1539 | ); | ||
1540 | |||
1541 | if ( | ||
1542 | (status == SCI_SUCCESS) | ||
1543 | && (frame_header->fis_type == SATA_FIS_TYPE_REGD2H) | ||
1544 | ) { | ||
1545 | scic_sds_unsolicited_frame_control_get_buffer( | ||
1546 | &this_request->owning_controller->uf_control, | ||
1547 | frame_index, | ||
1548 | (void **)&frame_buffer | ||
1549 | ); | ||
1550 | |||
1551 | scic_sds_controller_copy_sata_response( | ||
1552 | &((struct scic_sds_stp_request *)this_request)->d2h_reg_fis, | ||
1553 | (u32 *)frame_header, | ||
1554 | frame_buffer | ||
1555 | ); | ||
1556 | } | ||
1557 | |||
1558 | scic_sds_controller_release_frame( | ||
1559 | this_request->owning_controller, frame_index); | ||
1560 | |||
1561 | return status; | ||
1562 | } | ||
1563 | |||
1564 | /** | ||
1565 | * This method process TC completions while in the state where we are waiting | ||
1566 | * for TC completions. | ||
1567 | * @this_request: | ||
1568 | * @completion_code: | ||
1569 | * | ||
1570 | * enum sci_status | ||
1571 | */ | ||
1572 | static enum sci_status scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler( | ||
1573 | struct scic_sds_request *request, | ||
1574 | u32 completion_code) | ||
1575 | { | ||
1576 | enum sci_status status = SCI_SUCCESS; | ||
1577 | struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; | ||
1578 | |||
1579 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1580 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1581 | scic_sds_stp_request_udma_complete_request( | ||
1582 | &this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1583 | ); | ||
1584 | break; | ||
1585 | |||
1586 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_UNEXP_FIS): | ||
1587 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_REG_ERR): | ||
1588 | /* | ||
1589 | * We must check ther response buffer to see if the D2H Register FIS was | ||
1590 | * received before we got the TC completion. */ | ||
1591 | if (this_request->d2h_reg_fis.fis_type == SATA_FIS_TYPE_REGD2H) { | ||
1592 | scic_sds_remote_device_suspend( | ||
1593 | this_request->parent.target_device, | ||
1594 | SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) | ||
1595 | ); | ||
1596 | |||
1597 | scic_sds_stp_request_udma_complete_request( | ||
1598 | &this_request->parent, | ||
1599 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1600 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1601 | ); | ||
1602 | } else { | ||
1603 | /* | ||
1604 | * If we have an error completion status for the TC then we can expect a | ||
1605 | * D2H register FIS from the device so we must change state to wait for it */ | ||
1606 | sci_base_state_machine_change_state( | ||
1607 | &this_request->parent.started_substate_machine, | ||
1608 | SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE | ||
1609 | ); | ||
1610 | } | ||
1611 | break; | ||
1612 | |||
1613 | /* | ||
1614 | * / @todo Check to see if any of these completion status need to wait for | ||
1615 | * / the device to host register fis. */ | ||
1616 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_INV_FIS_LEN): | ||
1617 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_MAX_PLD_ERR): | ||
1618 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_LL_R_ERR): | ||
1619 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_CRC_ERR): | ||
1620 | scic_sds_remote_device_suspend( | ||
1621 | this_request->parent.target_device, | ||
1622 | SCU_EVENT_SPECIFIC(SCU_NORMALIZE_COMPLETION_STATUS(completion_code)) | ||
1623 | ); | ||
1624 | /* Fall through to the default case */ | ||
1625 | default: | ||
1626 | /* All other completion status cause the IO to be complete. */ | ||
1627 | scic_sds_stp_request_udma_complete_request( | ||
1628 | &this_request->parent, | ||
1629 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1630 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1631 | ); | ||
1632 | break; | ||
1633 | } | ||
1634 | |||
1635 | return status; | ||
1636 | } | ||
1637 | |||
1638 | static enum sci_status scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler( | ||
1639 | struct scic_sds_request *this_request, | ||
1640 | u32 frame_index) | ||
1641 | { | ||
1642 | enum sci_status status; | ||
1643 | |||
1644 | /* Use the general frame handler to copy the resposne data */ | ||
1645 | status = scic_sds_stp_request_udma_general_frame_handler(this_request, frame_index); | ||
1646 | |||
1647 | if (status == SCI_SUCCESS) { | ||
1648 | scic_sds_stp_request_udma_complete_request( | ||
1649 | this_request, | ||
1650 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1651 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1652 | ); | ||
1653 | } | ||
1654 | |||
1655 | return status; | ||
1656 | } | ||
1657 | |||
1658 | /* --------------------------------------------------------------------------- */ | ||
1659 | |||
1660 | const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[] = { | ||
1661 | [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { | ||
1662 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1663 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1664 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1665 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1666 | .tc_completion_handler = scic_sds_stp_request_udma_await_tc_completion_tc_completion_handler, | ||
1667 | .event_handler = scic_sds_request_default_event_handler, | ||
1668 | .frame_handler = scic_sds_stp_request_udma_general_frame_handler, | ||
1669 | }, | ||
1670 | [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { | ||
1671 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1672 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1673 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1674 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1675 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1676 | .event_handler = scic_sds_request_default_event_handler, | ||
1677 | .frame_handler = scic_sds_stp_request_udma_await_d2h_reg_fis_frame_handler, | ||
1678 | }, | ||
1679 | }; | ||
1680 | |||
1681 | static void scic_sds_stp_request_started_udma_await_tc_completion_enter( | ||
1682 | struct sci_base_object *object) | ||
1683 | { | ||
1684 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1685 | |||
1686 | SET_STATE_HANDLER( | ||
1687 | this_request, | ||
1688 | scic_sds_stp_request_started_udma_substate_handler_table, | ||
1689 | SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE | ||
1690 | ); | ||
1691 | } | ||
1692 | |||
1693 | /** | ||
1694 | * | ||
1695 | * | ||
1696 | * This state is entered when there is an TC completion failure. The hardware | ||
1697 | * received an unexpected condition while processing the IO request and now | ||
1698 | * will UF the D2H register FIS to complete the IO. | ||
1699 | */ | ||
1700 | static void scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter( | ||
1701 | struct sci_base_object *object) | ||
1702 | { | ||
1703 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1704 | |||
1705 | SET_STATE_HANDLER( | ||
1706 | this_request, | ||
1707 | scic_sds_stp_request_started_udma_substate_handler_table, | ||
1708 | SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE | ||
1709 | ); | ||
1710 | } | ||
1711 | |||
1712 | /* --------------------------------------------------------------------------- */ | ||
1713 | |||
1714 | const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[] = { | ||
1715 | [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE] = { | ||
1716 | .enter_state = scic_sds_stp_request_started_udma_await_tc_completion_enter, | ||
1717 | }, | ||
1718 | [SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE] = { | ||
1719 | .enter_state = scic_sds_stp_request_started_udma_await_d2h_reg_fis_enter, | ||
1720 | }, | ||
1721 | }; | ||
1722 | |||
1723 | /** | ||
1724 | * | ||
1725 | * @this_request: | ||
1726 | * @completion_code: | ||
1727 | * | ||
1728 | * This method processes a TC completion. The expected TC completion is for | ||
1729 | * the transmission of the H2D register FIS containing the SATA/STP non-data | ||
1730 | * request. This method always successfully processes the TC completion. | ||
1731 | * SCI_SUCCESS This value is always returned. | ||
1732 | */ | ||
1733 | static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler( | ||
1734 | struct scic_sds_request *this_request, | ||
1735 | u32 completion_code) | ||
1736 | { | ||
1737 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1738 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1739 | scic_sds_request_set_status( | ||
1740 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1741 | ); | ||
1742 | |||
1743 | sci_base_state_machine_change_state( | ||
1744 | &this_request->started_substate_machine, | ||
1745 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE | ||
1746 | ); | ||
1747 | break; | ||
1748 | |||
1749 | default: | ||
1750 | /* | ||
1751 | * All other completion status cause the IO to be complete. If a NAK | ||
1752 | * was received, then it is up to the user to retry the request. */ | ||
1753 | scic_sds_request_set_status( | ||
1754 | this_request, | ||
1755 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1756 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1757 | ); | ||
1758 | |||
1759 | sci_base_state_machine_change_state( | ||
1760 | &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED | ||
1761 | ); | ||
1762 | break; | ||
1763 | } | ||
1764 | |||
1765 | return SCI_SUCCESS; | ||
1766 | } | ||
1767 | |||
1768 | /** | ||
1769 | * | ||
1770 | * @this_request: | ||
1771 | * @completion_code: | ||
1772 | * | ||
1773 | * This method processes a TC completion. The expected TC completion is for | ||
1774 | * the transmission of the H2D register FIS containing the SATA/STP non-data | ||
1775 | * request. This method always successfully processes the TC completion. | ||
1776 | * SCI_SUCCESS This value is always returned. | ||
1777 | */ | ||
1778 | static enum sci_status scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler( | ||
1779 | struct scic_sds_request *this_request, | ||
1780 | u32 completion_code) | ||
1781 | { | ||
1782 | switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) { | ||
1783 | case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD): | ||
1784 | scic_sds_request_set_status( | ||
1785 | this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS | ||
1786 | ); | ||
1787 | |||
1788 | sci_base_state_machine_change_state( | ||
1789 | &this_request->started_substate_machine, | ||
1790 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE | ||
1791 | ); | ||
1792 | break; | ||
1793 | |||
1794 | default: | ||
1795 | /* | ||
1796 | * All other completion status cause the IO to be complete. If a NAK | ||
1797 | * was received, then it is up to the user to retry the request. */ | ||
1798 | scic_sds_request_set_status( | ||
1799 | this_request, | ||
1800 | SCU_NORMALIZE_COMPLETION_STATUS(completion_code), | ||
1801 | SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR | ||
1802 | ); | ||
1803 | |||
1804 | sci_base_state_machine_change_state( | ||
1805 | &this_request->parent.state_machine, SCI_BASE_REQUEST_STATE_COMPLETED | ||
1806 | ); | ||
1807 | break; | ||
1808 | } | ||
1809 | |||
1810 | return SCI_SUCCESS; | ||
1811 | } | ||
1812 | |||
1813 | /** | ||
1814 | * | ||
1815 | * @request: This parameter specifies the request for which a frame has been | ||
1816 | * received. | ||
1817 | * @frame_index: This parameter specifies the index of the frame that has been | ||
1818 | * received. | ||
1819 | * | ||
1820 | * This method processes frames received from the target while waiting for a | ||
1821 | * device to host register FIS. If a non-register FIS is received during this | ||
1822 | * time, it is treated as a protocol violation from an IO perspective. Indicate | ||
1823 | * if the received frame was processed successfully. | ||
1824 | */ | ||
1825 | static enum sci_status scic_sds_stp_request_soft_reset_await_d2h_frame_handler( | ||
1826 | struct scic_sds_request *request, | ||
1827 | u32 frame_index) | ||
1828 | { | ||
1829 | enum sci_status status; | ||
1830 | struct sata_fis_header *frame_header; | ||
1831 | u32 *frame_buffer; | ||
1832 | struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request; | ||
1833 | |||
1834 | status = scic_sds_unsolicited_frame_control_get_header( | ||
1835 | &(this_request->parent.owning_controller->uf_control), | ||
1836 | frame_index, | ||
1837 | (void **)&frame_header | ||
1838 | ); | ||
1839 | |||
1840 | if (status == SCI_SUCCESS) { | ||
1841 | switch (frame_header->fis_type) { | ||
1842 | case SATA_FIS_TYPE_REGD2H: | ||
1843 | scic_sds_unsolicited_frame_control_get_buffer( | ||
1844 | &(this_request->parent.owning_controller->uf_control), | ||
1845 | frame_index, | ||
1846 | (void **)&frame_buffer | ||
1847 | ); | ||
1848 | |||
1849 | scic_sds_controller_copy_sata_response( | ||
1850 | &this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer | ||
1851 | ); | ||
1852 | |||
1853 | /* The command has completed with error */ | ||
1854 | scic_sds_request_set_status( | ||
1855 | &this_request->parent, | ||
1856 | SCU_TASK_DONE_CHECK_RESPONSE, | ||
1857 | SCI_FAILURE_IO_RESPONSE_VALID | ||
1858 | ); | ||
1859 | break; | ||
1860 | |||
1861 | default: | ||
1862 | dev_warn(scic_to_dev(request->owning_controller), | ||
1863 | "%s: IO Request:0x%p Frame Id:%d protocol " | ||
1864 | "violation occurred\n", | ||
1865 | __func__, | ||
1866 | this_request, | ||
1867 | frame_index); | ||
1868 | |||
1869 | scic_sds_request_set_status( | ||
1870 | &this_request->parent, | ||
1871 | SCU_TASK_DONE_UNEXP_FIS, | ||
1872 | SCI_FAILURE_PROTOCOL_VIOLATION | ||
1873 | ); | ||
1874 | break; | ||
1875 | } | ||
1876 | |||
1877 | sci_base_state_machine_change_state( | ||
1878 | &this_request->parent.parent.state_machine, | ||
1879 | SCI_BASE_REQUEST_STATE_COMPLETED | ||
1880 | ); | ||
1881 | |||
1882 | /* Frame has been decoded return it to the controller */ | ||
1883 | scic_sds_controller_release_frame( | ||
1884 | this_request->parent.owning_controller, frame_index | ||
1885 | ); | ||
1886 | } else | ||
1887 | dev_err(scic_to_dev(request->owning_controller), | ||
1888 | "%s: SCIC IO Request 0x%p could not get frame header " | ||
1889 | "for frame index %d, status %x\n", | ||
1890 | __func__, this_request, frame_index, status); | ||
1891 | |||
1892 | return status; | ||
1893 | } | ||
1894 | |||
1895 | /* --------------------------------------------------------------------------- */ | ||
1896 | |||
1897 | const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[] = { | ||
1898 | [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { | ||
1899 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1900 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1901 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1902 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1903 | .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_asserted_tc_completion_handler, | ||
1904 | .event_handler = scic_sds_request_default_event_handler, | ||
1905 | .frame_handler = scic_sds_request_default_frame_handler, | ||
1906 | }, | ||
1907 | [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { | ||
1908 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1909 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1910 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1911 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1912 | .tc_completion_handler = scic_sds_stp_request_soft_reset_await_h2d_diagnostic_tc_completion_handler, | ||
1913 | .event_handler = scic_sds_request_default_event_handler, | ||
1914 | .frame_handler = scic_sds_request_default_frame_handler, | ||
1915 | }, | ||
1916 | [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { | ||
1917 | .parent.start_handler = scic_sds_request_default_start_handler, | ||
1918 | .parent.abort_handler = scic_sds_request_started_state_abort_handler, | ||
1919 | .parent.complete_handler = scic_sds_request_default_complete_handler, | ||
1920 | .parent.destruct_handler = scic_sds_request_default_destruct_handler, | ||
1921 | .tc_completion_handler = scic_sds_request_default_tc_completion_handler, | ||
1922 | .event_handler = scic_sds_request_default_event_handler, | ||
1923 | .frame_handler = scic_sds_stp_request_soft_reset_await_d2h_frame_handler, | ||
1924 | }, | ||
1925 | }; | ||
1926 | |||
1927 | static void scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter( | ||
1928 | struct sci_base_object *object) | ||
1929 | { | ||
1930 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1931 | |||
1932 | SET_STATE_HANDLER( | ||
1933 | this_request, | ||
1934 | scic_sds_stp_request_started_soft_reset_substate_handler_table, | ||
1935 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE | ||
1936 | ); | ||
1937 | |||
1938 | scic_sds_remote_device_set_working_request( | ||
1939 | this_request->target_device, this_request | ||
1940 | ); | ||
1941 | } | ||
1942 | |||
1943 | static void scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter( | ||
1944 | struct sci_base_object *object) | ||
1945 | { | ||
1946 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1947 | sci_base_controller_request_handler_t continue_io; | ||
1948 | struct scu_task_context *task_context; | ||
1949 | struct sata_fis_reg_h2d *h2d_fis; | ||
1950 | struct scic_sds_controller *scic; | ||
1951 | enum sci_status status; | ||
1952 | u32 state; | ||
1953 | |||
1954 | /* Clear the SRST bit */ | ||
1955 | h2d_fis = scic_stp_io_request_get_h2d_reg_address(this_request); | ||
1956 | h2d_fis->control = 0; | ||
1957 | |||
1958 | /* Clear the TC control bit */ | ||
1959 | task_context = scic_sds_controller_get_task_context_buffer( | ||
1960 | this_request->owning_controller, this_request->io_tag); | ||
1961 | task_context->control_frame = 0; | ||
1962 | |||
1963 | scic = this_request->owning_controller; | ||
1964 | state = scic->parent.state_machine.current_state_id; | ||
1965 | continue_io = scic_sds_controller_state_handler_table[state].base.continue_io; | ||
1966 | |||
1967 | status = continue_io(&scic->parent, &this_request->target_device->parent, | ||
1968 | &this_request->parent); | ||
1969 | |||
1970 | if (status == SCI_SUCCESS) { | ||
1971 | SET_STATE_HANDLER( | ||
1972 | this_request, | ||
1973 | scic_sds_stp_request_started_soft_reset_substate_handler_table, | ||
1974 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE | ||
1975 | ); | ||
1976 | } | ||
1977 | } | ||
1978 | |||
1979 | static void scic_sds_stp_request_started_soft_reset_await_d2h_response_enter( | ||
1980 | struct sci_base_object *object) | ||
1981 | { | ||
1982 | struct scic_sds_request *this_request = (struct scic_sds_request *)object; | ||
1983 | |||
1984 | SET_STATE_HANDLER( | ||
1985 | this_request, | ||
1986 | scic_sds_stp_request_started_soft_reset_substate_handler_table, | ||
1987 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE | ||
1988 | ); | ||
1989 | } | ||
1990 | |||
1991 | /* --------------------------------------------------------------------------- */ | ||
1992 | |||
1993 | const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[] = { | ||
1994 | [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE] = { | ||
1995 | .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_asserted_completion_enter, | ||
1996 | }, | ||
1997 | [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE] = { | ||
1998 | .enter_state = scic_sds_stp_request_started_soft_reset_await_h2d_diagnostic_completion_enter, | ||
1999 | }, | ||
2000 | [SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE] = { | ||
2001 | .enter_state = scic_sds_stp_request_started_soft_reset_await_d2h_response_enter, | ||
2002 | }, | ||
2003 | }; | ||
2004 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_stp_request.h b/drivers/scsi/isci/core/scic_sds_stp_request.h new file mode 100644 index 000000000000..5578d2baf7ca --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_stp_request.h | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_SDS_STP_REQUEST_T_ | ||
57 | #define _SCIC_SDS_STP_REQUEST_T_ | ||
58 | |||
59 | #include "intel_sata.h" | ||
60 | #include "sci_types.h" | ||
61 | #include "scic_sds_request.h" | ||
62 | |||
63 | /** | ||
64 | * This structure represents the additional information that is required to | ||
65 | * handle SATA PIO requests. | ||
66 | * | ||
67 | * | ||
68 | */ | ||
69 | struct scic_sds_stp_request { | ||
70 | struct scic_sds_request parent; | ||
71 | |||
72 | struct sata_fis_reg_d2h d2h_reg_fis; | ||
73 | |||
74 | union { | ||
75 | u32 ncq; | ||
76 | |||
77 | u32 udma; | ||
78 | |||
79 | struct { | ||
80 | /** | ||
81 | * Total transfer for the entire PIO request recorded at request constuction | ||
82 | * time. | ||
83 | * | ||
84 | * @todo Should we just decrement this value for each byte of data transitted | ||
85 | * or received to elemenate the current_transfer_bytes field? | ||
86 | */ | ||
87 | u32 total_transfer_bytes; | ||
88 | |||
89 | /** | ||
90 | * Total number of bytes received/transmitted in data frames since the start | ||
91 | * of the IO request. At the end of the IO request this should equal the | ||
92 | * total_transfer_bytes. | ||
93 | */ | ||
94 | u32 current_transfer_bytes; | ||
95 | |||
96 | /** | ||
97 | * The number of bytes requested in the in the PIO setup. | ||
98 | */ | ||
99 | u32 pio_transfer_bytes; | ||
100 | |||
101 | /** | ||
102 | * PIO Setup ending status value to tell us if we need to wait for another FIS | ||
103 | * or if the transfer is complete. On the receipt of a D2H FIS this will be | ||
104 | * the status field of that FIS. | ||
105 | */ | ||
106 | u8 ending_status; | ||
107 | |||
108 | /** | ||
109 | * On receipt of a D2H FIS this will be the ending error field if the | ||
110 | * ending_status has the SATA_STATUS_ERR bit set. | ||
111 | */ | ||
112 | u8 ending_error; | ||
113 | |||
114 | /** | ||
115 | * Protocol Type. This is filled in by core during IO Request construction type. | ||
116 | */ | ||
117 | u8 sat_protocol; | ||
118 | |||
119 | struct { | ||
120 | struct scu_sgl_element_pair *sgl_pair; | ||
121 | u8 sgl_set; | ||
122 | u32 sgl_offset; | ||
123 | } request_current; | ||
124 | } pio; | ||
125 | |||
126 | struct { | ||
127 | /** | ||
128 | * The number of bytes requested in the PIO setup before CDB data frame. | ||
129 | */ | ||
130 | u32 device_preferred_cdb_length; | ||
131 | } packet; | ||
132 | } type; | ||
133 | |||
134 | }; | ||
135 | |||
136 | /** | ||
137 | * enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES - This enumeration depicts | ||
138 | * the various sub-states associated with a SATA/STP UDMA protocol operation. | ||
139 | * | ||
140 | * | ||
141 | */ | ||
142 | enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES { | ||
143 | SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE, | ||
144 | SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE, | ||
145 | }; | ||
146 | |||
147 | /** | ||
148 | * enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES - This enumeration | ||
149 | * depicts the various sub-states associated with a SATA/STP non-data | ||
150 | * protocol operation. | ||
151 | * | ||
152 | * | ||
153 | */ | ||
154 | enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES { | ||
155 | SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE, | ||
156 | SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE, | ||
157 | }; | ||
158 | |||
159 | /** | ||
160 | * enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES - THis enumeration | ||
161 | * depicts the various sub-states associated with a SATA/STP soft reset | ||
162 | * operation. | ||
163 | * | ||
164 | * | ||
165 | */ | ||
166 | enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES { | ||
167 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE, | ||
168 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE, | ||
169 | SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE, | ||
170 | }; | ||
171 | |||
172 | extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[]; | ||
173 | |||
174 | extern const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[]; | ||
175 | |||
176 | extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[]; | ||
177 | |||
178 | extern const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[]; | ||
179 | |||
180 | extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[]; | ||
181 | |||
182 | extern const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[]; | ||
183 | |||
184 | /* --------------------------------------------------------------------------- */ | ||
185 | |||
186 | u32 scic_sds_stp_request_get_object_size(void); | ||
187 | |||
188 | |||
189 | void scic_sds_stp_non_ncq_request_construct( | ||
190 | struct scic_sds_request *this_request); | ||
191 | |||
192 | enum sci_status scic_sds_stp_pio_request_construct( | ||
193 | struct scic_sds_request *scic_io_request, | ||
194 | u8 sat_protocol, | ||
195 | bool copy_rx_frame); | ||
196 | |||
197 | enum sci_status scic_sds_stp_pio_request_construct_pass_through( | ||
198 | struct scic_sds_request *scic_io_request, | ||
199 | struct scic_stp_passthru_request_callbacks *passthru_cb); | ||
200 | |||
201 | enum sci_status scic_sds_stp_udma_request_construct( | ||
202 | struct scic_sds_request *this_request, | ||
203 | u32 transfer_length, | ||
204 | SCI_IO_REQUEST_DATA_DIRECTION data_direction); | ||
205 | |||
206 | enum sci_status scic_sds_stp_non_data_request_construct( | ||
207 | struct scic_sds_request *this_request); | ||
208 | |||
209 | enum sci_status scic_sds_stp_soft_reset_request_construct( | ||
210 | struct scic_sds_request *this_request); | ||
211 | |||
212 | enum sci_status scic_sds_stp_ncq_request_construct( | ||
213 | struct scic_sds_request *this_request, | ||
214 | u32 transfer_length, | ||
215 | SCI_IO_REQUEST_DATA_DIRECTION data_direction); | ||
216 | |||
217 | void scu_stp_raw_request_construct_task_context( | ||
218 | struct scic_sds_stp_request *this_request, | ||
219 | struct scu_task_context *task_context); | ||
220 | |||
221 | #endif /* _SCIC_SDS_STP_REQUEST_T_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c new file mode 100644 index 000000000000..7ca2f1709f6d --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.c | |||
@@ -0,0 +1,379 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the implementation of the | ||
58 | * struct scic_sds_unsolicited_frame_control object and it's public, protected, and | ||
59 | * private methods. | ||
60 | * | ||
61 | * | ||
62 | */ | ||
63 | |||
64 | #include "scic_sds_unsolicited_frame_control.h" | ||
65 | #include "scu_registers.h" | ||
66 | #include "scic_sds_controller.h" | ||
67 | #include "scic_user_callback.h" | ||
68 | #include "sci_util.h" | ||
69 | #include "sci_environment.h" | ||
70 | |||
71 | /** | ||
72 | * The UF buffer address table size must be programmed to a power of 2. Find | ||
73 | * the first power of 2 that is equal to or greater then the number of | ||
74 | * unsolicited frame buffers to be utilized. | ||
75 | * @uf_control: This parameter specifies the UF control object for which to | ||
76 | * update the address table count. | ||
77 | * | ||
78 | */ | ||
79 | void scic_sds_unsolicited_frame_control_set_address_table_count( | ||
80 | struct scic_sds_unsolicited_frame_control *uf_control) | ||
81 | { | ||
82 | uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES; | ||
83 | while ( | ||
84 | (uf_control->address_table.count < uf_control->buffers.count) | ||
85 | && (uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES) | ||
86 | ) { | ||
87 | uf_control->address_table.count <<= 1; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * This method will program the unsolicited frames (UFs) into the UF address | ||
93 | * table and construct the UF frame structure being modeled in the core. It | ||
94 | * will handle the case where some of the UFs are not being used and thus | ||
95 | * should have entries programmed to zero in the address table. | ||
96 | * @uf_control: This parameter specifies the unsolicted frame control object | ||
97 | * for which to construct the unsolicited frames objects. | ||
98 | * @uf_buffer_phys_address: This parameter specifies the physical address for | ||
99 | * the first unsolicited frame buffer. | ||
100 | * @uf_buffer_virt_address: This parameter specifies the virtual address for | ||
101 | * the first unsolicited frame buffer. | ||
102 | * @unused_uf_header_entries: This parameter specifies the number of unused UF | ||
103 | * headers. This value can be non-zero when there are a non-power of 2 | ||
104 | * number of unsolicited frames being supported. | ||
105 | * @used_uf_header_entries: This parameter specifies the number of actually | ||
106 | * utilized UF headers. | ||
107 | * | ||
108 | */ | ||
109 | static void scic_sds_unsolicited_frame_control_construct_frames( | ||
110 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
111 | dma_addr_t uf_buffer_phys_address, | ||
112 | unsigned long uf_buffer_virt_address, | ||
113 | u32 unused_uf_header_entries, | ||
114 | u32 used_uf_header_entries) | ||
115 | { | ||
116 | u32 index; | ||
117 | struct scic_sds_unsolicited_frame *uf; | ||
118 | |||
119 | /* | ||
120 | * Program the unused buffers into the UF address table and the | ||
121 | * controller's array of UFs. */ | ||
122 | for (index = 0; index < unused_uf_header_entries; index++) { | ||
123 | uf = &uf_control->buffers.array[index]; | ||
124 | |||
125 | sci_cb_make_physical_address( | ||
126 | uf_control->address_table.array[index], 0, 0 | ||
127 | ); | ||
128 | uf->buffer = NULL; | ||
129 | uf->header = &uf_control->headers.array[index]; | ||
130 | uf->state = UNSOLICITED_FRAME_EMPTY; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Program the actual used UF buffers into the UF address table and | ||
135 | * the controller's array of UFs. */ | ||
136 | for (index = unused_uf_header_entries; | ||
137 | index < unused_uf_header_entries + used_uf_header_entries; | ||
138 | index++) { | ||
139 | uf = &uf_control->buffers.array[index]; | ||
140 | |||
141 | uf_control->address_table.array[index] = uf_buffer_phys_address; | ||
142 | |||
143 | uf->buffer = (void *)uf_buffer_virt_address; | ||
144 | uf->header = &uf_control->headers.array[index]; | ||
145 | uf->state = UNSOLICITED_FRAME_EMPTY; | ||
146 | |||
147 | /* | ||
148 | * Increment the address of the physical and virtual memory pointers | ||
149 | * Everything is aligned on 1k boundary with an increment of 1k */ | ||
150 | uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE; | ||
151 | sci_physical_address_add( | ||
152 | uf_buffer_phys_address, SCU_UNSOLICITED_FRAME_BUFFER_SIZE | ||
153 | ); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * This method constructs the various members of the unsolicted frame control | ||
159 | * object (buffers, headers, address, table, etc). | ||
160 | * @uf_control: This parameter specifies the unsolicited frame control object | ||
161 | * to construct. | ||
162 | * @mde: This parameter specifies the memory descriptor from which to derive | ||
163 | * all of the address information needed to get the unsolicited frame | ||
164 | * functionality working. | ||
165 | * @controller: This parameter specifies the controller object associated with | ||
166 | * the uf_control being constructed. | ||
167 | * | ||
168 | */ | ||
169 | void scic_sds_unsolicited_frame_control_construct( | ||
170 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
171 | struct sci_physical_memory_descriptor *mde, | ||
172 | struct scic_sds_controller *controller) | ||
173 | { | ||
174 | u32 unused_uf_header_entries; | ||
175 | u32 used_uf_header_entries; | ||
176 | u32 used_uf_buffer_bytes; | ||
177 | u32 unused_uf_header_bytes; | ||
178 | u32 used_uf_header_bytes; | ||
179 | dma_addr_t uf_buffer_phys_address; | ||
180 | |||
181 | /* | ||
182 | * Prepare all of the memory sizes for the UF headers, UF address | ||
183 | * table, and UF buffers themselves. */ | ||
184 | used_uf_buffer_bytes = uf_control->buffers.count | ||
185 | * SCU_UNSOLICITED_FRAME_BUFFER_SIZE; | ||
186 | unused_uf_header_entries = uf_control->address_table.count | ||
187 | - uf_control->buffers.count; | ||
188 | used_uf_header_entries = uf_control->buffers.count; | ||
189 | unused_uf_header_bytes = unused_uf_header_entries | ||
190 | * sizeof(struct scu_unsolicited_frame_header); | ||
191 | used_uf_header_bytes = used_uf_header_entries | ||
192 | * sizeof(struct scu_unsolicited_frame_header); | ||
193 | |||
194 | /* | ||
195 | * The Unsolicited Frame buffers are set at the start of the UF | ||
196 | * memory descriptor entry. The headers and address table will be | ||
197 | * placed after the buffers. */ | ||
198 | uf_buffer_phys_address = mde->physical_address; | ||
199 | |||
200 | /* | ||
201 | * Program the location of the UF header table into the SCU. | ||
202 | * Notes: | ||
203 | * - The address must align on a 64-byte boundary. Guaranteed to be | ||
204 | * on 64-byte boundary already 1KB boundary for unsolicited frames. | ||
205 | * - Program unused header entries to overlap with the last | ||
206 | * unsolicited frame. The silicon will never DMA to these unused | ||
207 | * headers, since we program the UF address table pointers to | ||
208 | * NULL. */ | ||
209 | uf_control->headers.physical_address = uf_buffer_phys_address; | ||
210 | sci_physical_address_add( | ||
211 | uf_control->headers.physical_address, used_uf_buffer_bytes); | ||
212 | sci_physical_address_subtract( | ||
213 | uf_control->headers.physical_address, unused_uf_header_bytes); | ||
214 | uf_control->headers.array | ||
215 | = (struct scu_unsolicited_frame_header *) | ||
216 | scic_cb_get_virtual_address( | ||
217 | controller, uf_control->headers.physical_address | ||
218 | ); | ||
219 | |||
220 | /* | ||
221 | * Program the location of the UF address table into the SCU. | ||
222 | * Notes: | ||
223 | * - The address must align on a 64-bit boundary. Guaranteed to be on 64 | ||
224 | * byte boundary already due to above programming headers being on a | ||
225 | * 64-bit boundary and headers are on a 64-bytes in size. */ | ||
226 | uf_control->address_table.physical_address = uf_buffer_phys_address; | ||
227 | sci_physical_address_add( | ||
228 | uf_control->address_table.physical_address, used_uf_buffer_bytes); | ||
229 | sci_physical_address_add( | ||
230 | uf_control->address_table.physical_address, used_uf_header_bytes); | ||
231 | uf_control->address_table.array | ||
232 | = (dma_addr_t *) | ||
233 | scic_cb_get_virtual_address( | ||
234 | controller, uf_control->address_table.physical_address | ||
235 | ); | ||
236 | |||
237 | uf_control->get = 0; | ||
238 | |||
239 | /* | ||
240 | * UF buffer requirements are: | ||
241 | * - The last entry in the UF queue is not NULL. | ||
242 | * - There is a power of 2 number of entries (NULL or not-NULL) | ||
243 | * programmed into the queue. | ||
244 | * - Aligned on a 1KB boundary. */ | ||
245 | |||
246 | /* | ||
247 | * If the user provided less then the maximum amount of memory, | ||
248 | * then be sure that we programm the first entries in the UF | ||
249 | * address table to NULL. */ | ||
250 | scic_sds_unsolicited_frame_control_construct_frames( | ||
251 | uf_control, | ||
252 | uf_buffer_phys_address, | ||
253 | (unsigned long)mde->virtual_address, | ||
254 | unused_uf_header_entries, | ||
255 | used_uf_header_entries | ||
256 | ); | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * This method returns the frame header for the specified frame index. | ||
261 | * @uf_control: | ||
262 | * @frame_index: | ||
263 | * @frame_header: | ||
264 | * | ||
265 | * enum sci_status | ||
266 | */ | ||
267 | enum sci_status scic_sds_unsolicited_frame_control_get_header( | ||
268 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
269 | u32 frame_index, | ||
270 | void **frame_header) | ||
271 | { | ||
272 | if (frame_index < uf_control->address_table.count) { | ||
273 | /* | ||
274 | * Skip the first word in the frame since this is a controll word used | ||
275 | * by the hardware. */ | ||
276 | *frame_header = &uf_control->buffers.array[frame_index].header->data; | ||
277 | |||
278 | return SCI_SUCCESS; | ||
279 | } | ||
280 | |||
281 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * This method returns the frame buffer for the specified frame index. | ||
286 | * @uf_control: | ||
287 | * @frame_index: | ||
288 | * @frame_buffer: | ||
289 | * | ||
290 | * enum sci_status | ||
291 | */ | ||
292 | enum sci_status scic_sds_unsolicited_frame_control_get_buffer( | ||
293 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
294 | u32 frame_index, | ||
295 | void **frame_buffer) | ||
296 | { | ||
297 | if (frame_index < uf_control->address_table.count) { | ||
298 | *frame_buffer = uf_control->buffers.array[frame_index].buffer; | ||
299 | |||
300 | return SCI_SUCCESS; | ||
301 | } | ||
302 | |||
303 | return SCI_FAILURE_INVALID_PARAMETER_VALUE; | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * This method releases the frame once this is done the frame is available for | ||
308 | * re-use by the hardware. The data contained in the frame header and frame | ||
309 | * buffer is no longer valid. | ||
310 | * @uf_control: This parameter specifies the UF control object | ||
311 | * @frame_index: This parameter specifies the frame index to attempt to release. | ||
312 | * | ||
313 | * This method returns an indication to the caller as to whether the | ||
314 | * unsolicited frame get pointer should be updated. true This value indicates | ||
315 | * the unsolicited frame get pointer should be updated (i.e. write | ||
316 | * SCU_UFQGP_WRITE). false This value indicates the get pointer should not be | ||
317 | * updated. | ||
318 | */ | ||
319 | bool scic_sds_unsolicited_frame_control_release_frame( | ||
320 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
321 | u32 frame_index) | ||
322 | { | ||
323 | u32 frame_get; | ||
324 | u32 frame_cycle; | ||
325 | |||
326 | frame_get = uf_control->get & (uf_control->address_table.count - 1); | ||
327 | frame_cycle = uf_control->get & uf_control->address_table.count; | ||
328 | |||
329 | /* | ||
330 | * In the event there are NULL entries in the UF table, we need to | ||
331 | * advance the get pointer in order to find out if this frame should | ||
332 | * be released (i.e. update the get pointer). */ | ||
333 | while (((lower_32_bits(uf_control->address_table.array[frame_get]) | ||
334 | == 0) && | ||
335 | (upper_32_bits(uf_control->address_table.array[frame_get]) | ||
336 | == 0)) && | ||
337 | (frame_get < uf_control->address_table.count)) | ||
338 | frame_get++; | ||
339 | |||
340 | /* | ||
341 | * The table has a NULL entry as it's last element. This is | ||
342 | * illegal. */ | ||
343 | BUG_ON(frame_get >= uf_control->address_table.count); | ||
344 | |||
345 | if (frame_index < uf_control->address_table.count) { | ||
346 | uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED; | ||
347 | |||
348 | /* | ||
349 | * The frame index is equal to the current get pointer so we | ||
350 | * can now free up all of the frame entries that */ | ||
351 | if (frame_get == frame_index) { | ||
352 | while ( | ||
353 | uf_control->buffers.array[frame_get].state | ||
354 | == UNSOLICITED_FRAME_RELEASED | ||
355 | ) { | ||
356 | uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY; | ||
357 | |||
358 | INCREMENT_QUEUE_GET( | ||
359 | frame_get, | ||
360 | frame_cycle, | ||
361 | uf_control->address_table.count - 1, | ||
362 | uf_control->address_table.count | ||
363 | ); | ||
364 | } | ||
365 | |||
366 | uf_control->get = | ||
367 | (SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get); | ||
368 | |||
369 | return true; | ||
370 | } else { | ||
371 | /* | ||
372 | * Frames remain in use until we advance the get pointer | ||
373 | * so there is nothing we can do here */ | ||
374 | } | ||
375 | } | ||
376 | |||
377 | return false; | ||
378 | } | ||
379 | |||
diff --git a/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h new file mode 100644 index 000000000000..49db83faac37 --- /dev/null +++ b/drivers/scsi/isci/core/scic_sds_unsolicited_frame_control.h | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains all of the unsolicited frame related management for the | ||
58 | * address table, the headers, and actual payload buffers. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ | ||
64 | #define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ | ||
65 | |||
66 | #include "scu_unsolicited_frame.h" | ||
67 | #include "sci_memory_descriptor_list.h" | ||
68 | #include "scu_constants.h" | ||
69 | #include "sci_status.h" | ||
70 | |||
71 | /** | ||
72 | * enum UNSOLICITED_FRAME_STATE - | ||
73 | * | ||
74 | * This enumeration represents the current unsolicited frame state. The | ||
75 | * controller object can not updtate the hardware unsolicited frame put pointer | ||
76 | * unless it has already processed the priror unsolicited frames. | ||
77 | */ | ||
78 | enum UNSOLICITED_FRAME_STATE { | ||
79 | /** | ||
80 | * This state is when the frame is empty and not in use. It is | ||
81 | * different from the released state in that the hardware could DMA | ||
82 | * data to this frame buffer. | ||
83 | */ | ||
84 | UNSOLICITED_FRAME_EMPTY, | ||
85 | |||
86 | /** | ||
87 | * This state is set when the frame buffer is in use by by some | ||
88 | * object in the system. | ||
89 | */ | ||
90 | UNSOLICITED_FRAME_IN_USE, | ||
91 | |||
92 | /** | ||
93 | * This state is set when the frame is returned to the free pool | ||
94 | * but one or more frames prior to this one are still in use. | ||
95 | * Once all of the frame before this one are freed it will go to | ||
96 | * the empty state. | ||
97 | */ | ||
98 | UNSOLICITED_FRAME_RELEASED, | ||
99 | |||
100 | UNSOLICITED_FRAME_MAX_STATES | ||
101 | }; | ||
102 | |||
103 | /** | ||
104 | * struct scic_sds_unsolicited_frame - | ||
105 | * | ||
106 | * This is the unsolicited frame data structure it acts as the container for | ||
107 | * the current frame state, frame header and frame buffer. | ||
108 | */ | ||
109 | struct scic_sds_unsolicited_frame { | ||
110 | /** | ||
111 | * This field contains the current frame state | ||
112 | */ | ||
113 | enum UNSOLICITED_FRAME_STATE state; | ||
114 | |||
115 | /** | ||
116 | * This field points to the frame header data. | ||
117 | */ | ||
118 | struct scu_unsolicited_frame_header *header; | ||
119 | |||
120 | /** | ||
121 | * This field points to the frame buffer data. | ||
122 | */ | ||
123 | void *buffer; | ||
124 | |||
125 | }; | ||
126 | |||
127 | /** | ||
128 | * struct scic_sds_uf_header_array - | ||
129 | * | ||
130 | * This structure contains all of the unsolicited frame header information. | ||
131 | */ | ||
132 | struct scic_sds_uf_header_array { | ||
133 | /** | ||
134 | * This field is represents a virtual pointer to the start | ||
135 | * address of the UF address table. The table contains | ||
136 | * 64-bit pointers as required by the hardware. | ||
137 | */ | ||
138 | struct scu_unsolicited_frame_header *array; | ||
139 | |||
140 | /** | ||
141 | * This field specifies the physical address location for the UF | ||
142 | * buffer array. | ||
143 | */ | ||
144 | dma_addr_t physical_address; | ||
145 | |||
146 | }; | ||
147 | |||
148 | /* | ||
149 | * Determine the size of the unsolicited frame array including | ||
150 | * unused buffers. */ | ||
151 | #if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES | ||
152 | #define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES | ||
153 | #else | ||
154 | #define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES | ||
155 | #endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */ | ||
156 | |||
157 | /** | ||
158 | * struct scic_sds_uf_buffer_array - | ||
159 | * | ||
160 | * This structure contains all of the unsolicited frame buffer (actual payload) | ||
161 | * information. | ||
162 | */ | ||
163 | struct scic_sds_uf_buffer_array { | ||
164 | /** | ||
165 | * This field is the minimum number of unsolicited frames supported by the | ||
166 | * hardware and the number of unsolicited frames requested by the software. | ||
167 | */ | ||
168 | u32 count; | ||
169 | |||
170 | /** | ||
171 | * This field is the SCIC_UNSOLICITED_FRAME data its used to manage | ||
172 | * the data for the unsolicited frame requests. It also represents | ||
173 | * the virtual address location that corresponds to the | ||
174 | * physical_address field. | ||
175 | */ | ||
176 | struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE]; | ||
177 | |||
178 | /** | ||
179 | * This field specifies the physical address location for the UF | ||
180 | * buffer array. | ||
181 | */ | ||
182 | dma_addr_t physical_address; | ||
183 | |||
184 | }; | ||
185 | |||
186 | /** | ||
187 | * struct scic_sds_uf_address_table_array - | ||
188 | * | ||
189 | * This object maintains all of the unsolicited frame address table specific | ||
190 | * data. The address table is a collection of 64-bit pointers that point to | ||
191 | * 1KB buffers into which the silicon will DMA unsolicited frames. | ||
192 | */ | ||
193 | struct scic_sds_uf_address_table_array { | ||
194 | /** | ||
195 | * This field specifies the actual programmed size of the | ||
196 | * unsolicited frame buffer address table. The size of the table | ||
197 | * can be larger than the actual number of UF buffers, but it must | ||
198 | * be a power of 2 and the last entry in the table is not allowed | ||
199 | * to be NULL. | ||
200 | */ | ||
201 | u32 count; | ||
202 | |||
203 | /** | ||
204 | * This field represents a virtual pointer that refers to the | ||
205 | * starting address of the UF address table. | ||
206 | * 64-bit pointers are required by the hardware. | ||
207 | */ | ||
208 | dma_addr_t *array; | ||
209 | |||
210 | /** | ||
211 | * This field specifies the physical address location for the UF | ||
212 | * address table. | ||
213 | */ | ||
214 | dma_addr_t physical_address; | ||
215 | |||
216 | }; | ||
217 | |||
218 | /** | ||
219 | * struct scic_sds_unsolicited_frame_control - | ||
220 | * | ||
221 | * This object contains all of the data necessary to handle unsolicited frames. | ||
222 | */ | ||
223 | struct scic_sds_unsolicited_frame_control { | ||
224 | /** | ||
225 | * This field is the software copy of the unsolicited frame queue | ||
226 | * get pointer. The controller object writes this value to the | ||
227 | * hardware to let the hardware put more unsolicited frame entries. | ||
228 | */ | ||
229 | u32 get; | ||
230 | |||
231 | /** | ||
232 | * This field contains all of the unsolicited frame header | ||
233 | * specific fields. | ||
234 | */ | ||
235 | struct scic_sds_uf_header_array headers; | ||
236 | |||
237 | /** | ||
238 | * This field contains all of the unsolicited frame buffer | ||
239 | * specific fields. | ||
240 | */ | ||
241 | struct scic_sds_uf_buffer_array buffers; | ||
242 | |||
243 | /** | ||
244 | * This field contains all of the unsolicited frame address table | ||
245 | * specific fields. | ||
246 | */ | ||
247 | struct scic_sds_uf_address_table_array address_table; | ||
248 | |||
249 | }; | ||
250 | |||
251 | void scic_sds_unsolicited_frame_control_set_address_table_count( | ||
252 | struct scic_sds_unsolicited_frame_control *uf_control); | ||
253 | |||
254 | struct scic_sds_controller; | ||
255 | void scic_sds_unsolicited_frame_control_construct( | ||
256 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
257 | struct sci_physical_memory_descriptor *mde, | ||
258 | struct scic_sds_controller *this_controller); | ||
259 | |||
260 | enum sci_status scic_sds_unsolicited_frame_control_get_header( | ||
261 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
262 | u32 frame_index, | ||
263 | void **frame_header); | ||
264 | |||
265 | enum sci_status scic_sds_unsolicited_frame_control_get_buffer( | ||
266 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
267 | u32 frame_index, | ||
268 | void **frame_buffer); | ||
269 | |||
270 | bool scic_sds_unsolicited_frame_control_release_frame( | ||
271 | struct scic_sds_unsolicited_frame_control *uf_control, | ||
272 | u32 frame_index); | ||
273 | |||
274 | /** | ||
275 | * scic_sds_unsolicited_frame_control_get_mde_size() - | ||
276 | * | ||
277 | * This macro simply calculates the size of the memory descriptor entry that | ||
278 | * relates to unsolicited frames and the surrounding silicon memory required to | ||
279 | * utilize it. | ||
280 | */ | ||
281 | #define scic_sds_unsolicited_frame_control_get_mde_size(uf_control) \ | ||
282 | (((uf_control).buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) \ | ||
283 | + ((uf_control).address_table.count * sizeof(dma_addr_t)) \ | ||
284 | + ((uf_control).buffers.count * sizeof(struct scu_unsolicited_frame_header))) | ||
285 | |||
286 | #endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scic_task_request.h b/drivers/scsi/isci/core/scic_task_request.h new file mode 100644 index 000000000000..ef76cb6bdbea --- /dev/null +++ b/drivers/scsi/isci/core/scic_task_request.h | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_TASK_REQUEST_H_ | ||
57 | #define _SCIC_TASK_REQUEST_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures and interface methods that can be | ||
61 | * referenced and used by the SCI user for to utilize task management | ||
62 | * requests. | ||
63 | * | ||
64 | * | ||
65 | */ | ||
66 | |||
67 | |||
68 | #include "sci_types.h" | ||
69 | #include "sci_status.h" | ||
70 | |||
71 | struct scic_sds_request; | ||
72 | struct scic_sds_remote_device; | ||
73 | struct scic_sds_controller; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * scic_task_request_construct() - This method is called by the SCI user to | ||
78 | * construct all SCI Core task management requests, regardless of protocol. | ||
79 | * Memory initialization and functionality common to all task request types | ||
80 | * is performed in this method. | ||
81 | * @scic_controller: the handle to the core controller object for which to | ||
82 | * build the task managmement request. | ||
83 | * @scic_remote_device: the handle to the core remote device object for which | ||
84 | * to build the task management request. passed, then a copy of the request | ||
85 | * is built internally. The request will be copied into the actual | ||
86 | * controller request memory when the task is allocated internally during | ||
87 | * the scic_controller_start_task() method. | ||
88 | * @io_tag: This parameter specifies the IO tag to be associated with this | ||
89 | * request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the | ||
90 | * request is built internally. The request will be copied into the actual | ||
91 | * controller request memory when the IO tag is allocated internally during | ||
92 | * the scic_controller_start_io() method. | ||
93 | * @user_task_request_object: This parameter specifies the user task request to | ||
94 | * be utilized during construction. This task pointer will become the | ||
95 | * associated object for the core task request object. | ||
96 | * @scic_task_request_memory: This parameter specifies the memory location to | ||
97 | * be utilized when building the core request. | ||
98 | * @new_scic_task_request_handle: This parameter specifies a pointer to the | ||
99 | * handle the core will expect in further interactions with the core task | ||
100 | * request object. | ||
101 | * | ||
102 | * The SCI core implementation will create an association between the user task | ||
103 | * request object and the core task request object. Indicate if the controller | ||
104 | * successfully built the task request. SCI_SUCCESS This value is returned if | ||
105 | * the task request was successfully built. | ||
106 | */ | ||
107 | enum sci_status scic_task_request_construct( | ||
108 | struct scic_sds_controller *scic_controller, | ||
109 | struct scic_sds_remote_device *scic_remote_device, | ||
110 | u16 io_tag, | ||
111 | void *user_task_request_object, | ||
112 | void *scic_task_request_memory, | ||
113 | struct scic_sds_request **new_scic_task_request_handle); | ||
114 | |||
115 | /** | ||
116 | * scic_task_request_construct_ssp() - This method is called by the SCI user to | ||
117 | * construct all SCI Core SSP task management requests. Memory | ||
118 | * initialization and functionality common to all task request types is | ||
119 | * performed in this method. | ||
120 | * @scic_task_request: This parameter specifies the handle to the core task | ||
121 | * request object for which to construct a SATA specific task management | ||
122 | * request. | ||
123 | * | ||
124 | * Indicate if the controller successfully built the task request. SCI_SUCCESS | ||
125 | * This value is returned if the task request was successfully built. | ||
126 | */ | ||
127 | enum sci_status scic_task_request_construct_ssp( | ||
128 | struct scic_sds_request *scic_task_request); | ||
129 | |||
130 | /** | ||
131 | * scic_task_request_construct_sata() - This method is called by the SCI user | ||
132 | * to construct all SCI Core SATA task management requests. Memory | ||
133 | * initialization and functionality common to all task request types is | ||
134 | * performed in this method. | ||
135 | * @scic_task_request_handle: This parameter specifies the handle to the core | ||
136 | * task request object for which to construct a SATA specific task | ||
137 | * management request. | ||
138 | * | ||
139 | * Indicate if the controller successfully built the task request. SCI_SUCCESS | ||
140 | * This value is returned if the task request was successfully built. | ||
141 | */ | ||
142 | enum sci_status scic_task_request_construct_sata( | ||
143 | struct scic_sds_request *scic_task_request_handle); | ||
144 | |||
145 | |||
146 | |||
147 | #endif /* _SCIC_TASK_REQUEST_H_ */ | ||
148 | |||
diff --git a/drivers/scsi/isci/core/scic_user_callback.h b/drivers/scsi/isci/core/scic_user_callback.h new file mode 100644 index 000000000000..6eca5a96649e --- /dev/null +++ b/drivers/scsi/isci/core/scic_user_callback.h | |||
@@ -0,0 +1,740 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCIC_USER_CALLBACK_H_ | ||
57 | #define _SCIC_USER_CALLBACK_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains all of the interface methods/macros that must be | ||
61 | * implemented by an SCI Core user. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | |||
67 | #include "sci_types.h" | ||
68 | #include "sci_status.h" | ||
69 | |||
70 | struct scic_sds_request; | ||
71 | struct scic_sds_phy; | ||
72 | struct scic_sds_port; | ||
73 | struct scic_sds_remote_device; | ||
74 | struct scic_sds_controller; | ||
75 | |||
76 | /** | ||
77 | * scic_cb_timer_create() - This callback method asks the user to create a | ||
78 | * timer and provide a handle for this timer for use in further timer | ||
79 | * interactions. | ||
80 | * @controller: This parameter specifies the controller with which this timer | ||
81 | * is to be associated. | ||
82 | * @timer_callback: This parameter specifies the callback method to be invoked | ||
83 | * whenever the timer expires. | ||
84 | * @cookie: This parameter specifies a piece of information that the user must | ||
85 | * retain. This cookie is to be supplied by the user anytime a timeout | ||
86 | * occurs for the created timer. | ||
87 | * | ||
88 | * The "timer_callback" method should be executed in a mutually exlusive manner | ||
89 | * from the controller completion handler handler (refer to | ||
90 | * scic_controller_get_handler_methods()). This method returns a handle to a | ||
91 | * timer object created by the user. The handle will be utilized for all | ||
92 | * further interactions relating to this timer. | ||
93 | */ | ||
94 | void *scic_cb_timer_create( | ||
95 | struct scic_sds_controller *controller, | ||
96 | void (*timer_callback)(void *), | ||
97 | void *cookie); | ||
98 | |||
99 | |||
100 | /** | ||
101 | * scic_cb_timer_start() - This callback method asks the user to start the | ||
102 | * supplied timer. | ||
103 | * @controller: This parameter specifies the controller with which this timer | ||
104 | * is to associated. | ||
105 | * @timer: This parameter specifies the timer to be started. | ||
106 | * @milliseconds: This parameter specifies the number of milliseconds for which | ||
107 | * to stall. The operating system driver is allowed to round this value up | ||
108 | * where necessary. | ||
109 | * | ||
110 | * All timers in the system started by the SCI Core are one shot timers. | ||
111 | * Therefore, the SCI user should make sure that it removes the timer from it's | ||
112 | * list when a timer actually fires. Additionally, SCI Core user's should be | ||
113 | * able to handle calls from the SCI Core to stop a timer that may already be | ||
114 | * stopped. none | ||
115 | */ | ||
116 | void scic_cb_timer_start( | ||
117 | struct scic_sds_controller *controller, | ||
118 | void *timer, | ||
119 | u32 milliseconds); | ||
120 | |||
121 | /** | ||
122 | * scic_cb_timer_stop() - This callback method asks the user to stop the | ||
123 | * supplied timer. | ||
124 | * @controller: This parameter specifies the controller with which this timer | ||
125 | * is to associated. | ||
126 | * @timer: This parameter specifies the timer to be stopped. | ||
127 | * | ||
128 | */ | ||
129 | void scic_cb_timer_stop( | ||
130 | struct scic_sds_controller *controller, | ||
131 | void *timer); | ||
132 | |||
133 | /** | ||
134 | * scic_cb_stall_execution() - This method is called when the core requires the | ||
135 | * OS driver to stall execution. This method is utilized during | ||
136 | * initialization or non-performance paths only. | ||
137 | * @microseconds: This parameter specifies the number of microseconds for which | ||
138 | * to stall. The operating system driver is allowed to round this value up | ||
139 | * where necessary. | ||
140 | * | ||
141 | * none. | ||
142 | */ | ||
143 | void scic_cb_stall_execution( | ||
144 | u32 microseconds); | ||
145 | |||
146 | /** | ||
147 | * scic_cb_controller_start_complete() - This user callback will inform the | ||
148 | * user that the controller has finished the start process. | ||
149 | * @controller: This parameter specifies the controller that was started. | ||
150 | * @completion_status: This parameter specifies the results of the start | ||
151 | * operation. SCI_SUCCESS indicates successful completion. | ||
152 | * | ||
153 | */ | ||
154 | void scic_cb_controller_start_complete( | ||
155 | struct scic_sds_controller *controller, | ||
156 | enum sci_status completion_status); | ||
157 | |||
158 | /** | ||
159 | * scic_cb_controller_stop_complete() - This user callback will inform the user | ||
160 | * that the controller has finished the stop process. | ||
161 | * @controller: This parameter specifies the controller that was stopped. | ||
162 | * @completion_status: This parameter specifies the results of the stop | ||
163 | * operation. SCI_SUCCESS indicates successful completion. | ||
164 | * | ||
165 | */ | ||
166 | void scic_cb_controller_stop_complete( | ||
167 | struct scic_sds_controller *controller, | ||
168 | enum sci_status completion_status); | ||
169 | |||
170 | /** | ||
171 | * scic_cb_io_request_complete() - This user callback will inform the user that | ||
172 | * an IO request has completed. | ||
173 | * @controller: This parameter specifies the controller on which the IO is | ||
174 | * completing. | ||
175 | * @remote_device: This parameter specifies the remote device on which this IO | ||
176 | * request is completing. | ||
177 | * @io_request: This parameter specifies the IO request that has completed. | ||
178 | * @completion_status: This parameter specifies the results of the IO request | ||
179 | * operation. SCI_SUCCESS indicates successful completion. | ||
180 | * | ||
181 | */ | ||
182 | void scic_cb_io_request_complete( | ||
183 | struct scic_sds_controller *controller, | ||
184 | struct scic_sds_remote_device *remote_device, | ||
185 | struct scic_sds_request *io_request, | ||
186 | enum sci_io_status completion_status); | ||
187 | |||
188 | /** | ||
189 | * scic_cb_task_request_complete() - This user callback will inform the user | ||
190 | * that a task management request completed. | ||
191 | * @controller: This parameter specifies the controller on which the task | ||
192 | * management request is completing. | ||
193 | * @remote_device: This parameter specifies the remote device on which this | ||
194 | * task management request is completing. | ||
195 | * @task_request: This parameter specifies the task management request that has | ||
196 | * completed. | ||
197 | * @completion_status: This parameter specifies the results of the IO request | ||
198 | * operation. SCI_SUCCESS indicates successful completion. | ||
199 | * | ||
200 | */ | ||
201 | void scic_cb_task_request_complete( | ||
202 | struct scic_sds_controller *controller, | ||
203 | struct scic_sds_remote_device *remote_device, | ||
204 | struct scic_sds_request *task_request, | ||
205 | enum sci_task_status completion_status); | ||
206 | |||
207 | #ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED | ||
208 | /** | ||
209 | * scic_cb_io_request_get_physical_address() - This callback method asks the | ||
210 | * user to provide the physical address for the supplied virtual address | ||
211 | * when building an io request object. | ||
212 | * @controller: This parameter is the core controller object handle. | ||
213 | * @io_request: This parameter is the io request object handle for which the | ||
214 | * physical address is being requested. | ||
215 | * @virtual_address: This paramter is the virtual address which is to be | ||
216 | * returned as a physical address. | ||
217 | * @physical_address: The physical address for the supplied virtual address. | ||
218 | * | ||
219 | * None. | ||
220 | */ | ||
221 | void scic_cb_io_request_get_physical_address( | ||
222 | struct scic_sds_controller *controller, | ||
223 | struct scic_sds_request *io_request, | ||
224 | void *virtual_address, | ||
225 | dma_addr_t *physical_address); | ||
226 | #endif /* SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED */ | ||
227 | |||
228 | /** | ||
229 | * scic_cb_io_request_get_transfer_length() - This callback method asks the | ||
230 | * user to provide the number of bytes to be transfered as part of this | ||
231 | * request. | ||
232 | * @scic_user_io_request: This parameter points to the user's IO request | ||
233 | * object. It is a cookie that allows the user to provide the necessary | ||
234 | * information for this callback. | ||
235 | * | ||
236 | * This method returns the number of payload data bytes to be transfered for | ||
237 | * this IO request. | ||
238 | */ | ||
239 | u32 scic_cb_io_request_get_transfer_length( | ||
240 | void *scic_user_io_request); | ||
241 | |||
242 | /** | ||
243 | * scic_cb_io_request_get_data_direction() - This callback method asks the user | ||
244 | * to provide the data direction for this request. | ||
245 | * @scic_user_io_request: This parameter points to the user's IO request | ||
246 | * object. It is a cookie that allows the user to provide the necessary | ||
247 | * information for this callback. | ||
248 | * | ||
249 | * This method returns the value of SCI_IO_REQUEST_DATA_OUT or | ||
250 | * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA. | ||
251 | */ | ||
252 | SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction( | ||
253 | void *scic_user_io_request); | ||
254 | |||
255 | #ifndef SCI_SGL_OPTIMIZATION_ENABLED | ||
256 | /** | ||
257 | * scic_cb_io_request_get_next_sge() - This callback method asks the user to | ||
258 | * provide the address to where the next Scatter-Gather Element is located. | ||
259 | * Details regarding usage: - Regarding the first SGE: the user should | ||
260 | * initialize an index, or a pointer, prior to construction of the request | ||
261 | * that will reference the very first scatter-gather element. This is | ||
262 | * important since this method is called for every scatter-gather element, | ||
263 | * including the first element. - Regarding the last SGE: the user should | ||
264 | * return NULL from this method when this method is called and the SGL has | ||
265 | * exhausted all elements. | ||
266 | * @scic_user_io_request: This parameter points to the user's IO request | ||
267 | * object. It is a cookie that allows the user to provide the necessary | ||
268 | * information for this callback. | ||
269 | * @current_sge_address: This parameter specifies the address for the current | ||
270 | * SGE (i.e. the one that has just processed). | ||
271 | * @next_sge: An address specifying the location for the next scatter gather | ||
272 | * element to be processed. | ||
273 | * | ||
274 | * None | ||
275 | */ | ||
276 | void scic_cb_io_request_get_next_sge( | ||
277 | void *scic_user_io_request, | ||
278 | void *current_sge_address, | ||
279 | void **next_sge); | ||
280 | #endif /* SCI_SGL_OPTIMIZATION_ENABLED */ | ||
281 | |||
282 | /** | ||
283 | * scic_cb_sge_get_address_field() - This callback method asks the user to | ||
284 | * provide the contents of the "address" field in the Scatter-Gather Element. | ||
285 | * @scic_user_io_request: This parameter points to the user's IO request | ||
286 | * object. It is a cookie that allows the user to provide the necessary | ||
287 | * information for this callback. | ||
288 | * @sge_address: This parameter specifies the address for the SGE from which to | ||
289 | * retrieve the address field. | ||
290 | * | ||
291 | * A physical address specifying the contents of the SGE's address field. | ||
292 | */ | ||
293 | dma_addr_t scic_cb_sge_get_address_field( | ||
294 | void *scic_user_io_request, | ||
295 | void *sge_address); | ||
296 | |||
297 | /** | ||
298 | * scic_cb_sge_get_length_field() - This callback method asks the user to | ||
299 | * provide the contents of the "length" field in the Scatter-Gather Element. | ||
300 | * @scic_user_io_request: This parameter points to the user's IO request | ||
301 | * object. It is a cookie that allows the user to provide the necessary | ||
302 | * information for this callback. | ||
303 | * @sge_address: This parameter specifies the address for the SGE from which to | ||
304 | * retrieve the address field. | ||
305 | * | ||
306 | * This method returns the length field specified inside the SGE referenced by | ||
307 | * the sge_address parameter. | ||
308 | */ | ||
309 | u32 scic_cb_sge_get_length_field( | ||
310 | void *scic_user_io_request, | ||
311 | void *sge_address); | ||
312 | |||
313 | /** | ||
314 | * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the | ||
315 | * user to provide the address for the command descriptor block (CDB) | ||
316 | * associated with this IO request. | ||
317 | * @scic_user_io_request: This parameter points to the user's IO request | ||
318 | * object. It is a cookie that allows the user to provide the necessary | ||
319 | * information for this callback. | ||
320 | * | ||
321 | * This method returns the virtual address of the CDB. | ||
322 | */ | ||
323 | void *scic_cb_ssp_io_request_get_cdb_address( | ||
324 | void *scic_user_io_request); | ||
325 | |||
326 | /** | ||
327 | * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user | ||
328 | * to provide the length of the command descriptor block (CDB) associated | ||
329 | * with this IO request. | ||
330 | * @scic_user_io_request: This parameter points to the user's IO request | ||
331 | * object. It is a cookie that allows the user to provide the necessary | ||
332 | * information for this callback. | ||
333 | * | ||
334 | * This method returns the length of the CDB. | ||
335 | */ | ||
336 | u32 scic_cb_ssp_io_request_get_cdb_length( | ||
337 | void *scic_user_io_request); | ||
338 | |||
339 | /** | ||
340 | * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to | ||
341 | * provide the Logical Unit (LUN) associated with this IO request. | ||
342 | * @scic_user_io_request: This parameter points to the user's IO request | ||
343 | * object. It is a cookie that allows the user to provide the necessary | ||
344 | * information for this callback. | ||
345 | * | ||
346 | * The contents of the value returned from this callback are defined by the | ||
347 | * protocol standard (e.g. T10 SAS specification). Please refer to the | ||
348 | * transport command information unit description in the associated standard. | ||
349 | * This method returns the LUN associated with this request. This should be u64? | ||
350 | */ | ||
351 | u32 scic_cb_ssp_io_request_get_lun( | ||
352 | void *scic_user_io_request); | ||
353 | |||
354 | /** | ||
355 | * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the | ||
356 | * user to provide the task attribute associated with this IO request. | ||
357 | * @scic_user_io_request: This parameter points to the user's IO request | ||
358 | * object. It is a cookie that allows the user to provide the necessary | ||
359 | * information for this callback. | ||
360 | * | ||
361 | * The contents of the value returned from this callback are defined by the | ||
362 | * protocol standard (e.g. T10 SAS specification). Please refer to the | ||
363 | * transport command information unit description in the associated standard. | ||
364 | * This method returns the task attribute associated with this IO request. | ||
365 | */ | ||
366 | u32 scic_cb_ssp_io_request_get_task_attribute( | ||
367 | void *scic_user_io_request); | ||
368 | |||
369 | /** | ||
370 | * scic_cb_ssp_io_request_get_command_priority() - This callback method asks | ||
371 | * the user to provide the command priority associated with this IO request. | ||
372 | * @scic_user_io_request: This parameter points to the user's IO request | ||
373 | * object. It is a cookie that allows the user to provide the necessary | ||
374 | * information for this callback. | ||
375 | * | ||
376 | * The contents of the value returned from this callback are defined by the | ||
377 | * protocol standard (e.g. T10 SAS specification). Please refer to the | ||
378 | * transport command information unit description in the associated standard. | ||
379 | * This method returns the command priority associated with this IO request. | ||
380 | */ | ||
381 | u32 scic_cb_ssp_io_request_get_command_priority( | ||
382 | void *scic_user_io_request); | ||
383 | |||
384 | /** | ||
385 | * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user | ||
386 | * if the received RX frame data is to be copied to the SGL or should be | ||
387 | * stored by the SCI core to be retrieved later with the | ||
388 | * scic_io_request_get_rx_frame(). | ||
389 | * @scic_user_io_request: This parameter points to the user's IO request | ||
390 | * object. It is a cookie that allows the user to provide the necessary | ||
391 | * information for this callback. | ||
392 | * | ||
393 | * This method returns true if the SCI core should copy the received frame data | ||
394 | * to the SGL location or false if the SCI user wants to retrieve the frame | ||
395 | * data at a later time. | ||
396 | */ | ||
397 | bool scic_cb_io_request_do_copy_rx_frames( | ||
398 | void *scic_user_io_request); | ||
399 | |||
400 | /** | ||
401 | * scic_cb_request_get_sat_protocol() - This callback method asks the user to | ||
402 | * return the SAT protocol definition for this IO request. This method is | ||
403 | * only called by the SCI core if the request type constructed is SATA. | ||
404 | * @scic_user_io_request: This parameter points to the user's IO request | ||
405 | * object. It is a cookie that allows the user to provide the necessary | ||
406 | * information for this callback. | ||
407 | * | ||
408 | * This method returns one of the sat.h defined protocols for the given io | ||
409 | * request. | ||
410 | */ | ||
411 | u8 scic_cb_request_get_sat_protocol( | ||
412 | void *scic_user_io_request); | ||
413 | |||
414 | |||
415 | /** | ||
416 | * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to | ||
417 | * be utilized for this task management request. | ||
418 | * @scic_user_task_request: This parameter points to the user's task request | ||
419 | * object. It is a cookie that allows the user to provide the necessary | ||
420 | * information for this callback. | ||
421 | * | ||
422 | * The contents of the value returned from this callback are defined by the | ||
423 | * protocol standard (e.g. T10 SAS specification). Please refer to the | ||
424 | * transport task information unit description in the associated standard. This | ||
425 | * method returns the LUN associated with this request. This should be u64? | ||
426 | */ | ||
427 | u32 scic_cb_ssp_task_request_get_lun( | ||
428 | void *scic_user_task_request); | ||
429 | |||
430 | /** | ||
431 | * scic_cb_ssp_task_request_get_function() - This method returns the task | ||
432 | * management function to be utilized for this task request. | ||
433 | * @scic_user_task_request: This parameter points to the user's task request | ||
434 | * object. It is a cookie that allows the user to provide the necessary | ||
435 | * information for this callback. | ||
436 | * | ||
437 | * The contents of the value returned from this callback are defined by the | ||
438 | * protocol standard (e.g. T10 SAS specification). Please refer to the | ||
439 | * transport task information unit description in the associated standard. This | ||
440 | * method returns an unsigned byte representing the task management function to | ||
441 | * be performed. | ||
442 | */ | ||
443 | u8 scic_cb_ssp_task_request_get_function( | ||
444 | void *scic_user_task_request); | ||
445 | |||
446 | /** | ||
447 | * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the | ||
448 | * task management IO tag to be managed. Depending upon the task management | ||
449 | * function the value returned from this method may be ignored. | ||
450 | * @scic_user_task_request: This parameter points to the user's task request | ||
451 | * object. It is a cookie that allows the user to provide the necessary | ||
452 | * information for this callback. | ||
453 | * | ||
454 | * This method returns an unsigned 16-bit word depicting the IO tag to be | ||
455 | * managed. | ||
456 | */ | ||
457 | u16 scic_cb_ssp_task_request_get_io_tag_to_manage( | ||
458 | void *scic_user_task_request); | ||
459 | |||
460 | /** | ||
461 | * scic_cb_ssp_task_request_get_response_data_address() - This callback method | ||
462 | * asks the user to provide the virtual address of the response data buffer | ||
463 | * for the supplied IO request. | ||
464 | * @scic_user_task_request: This parameter points to the user's task request | ||
465 | * object. It is a cookie that allows the user to provide the necessary | ||
466 | * information for this callback. | ||
467 | * | ||
468 | * This method returns the virtual address for the response data buffer | ||
469 | * associated with this IO request. | ||
470 | */ | ||
471 | void *scic_cb_ssp_task_request_get_response_data_address( | ||
472 | void *scic_user_task_request); | ||
473 | |||
474 | /** | ||
475 | * scic_cb_ssp_task_request_get_response_data_length() - This callback method | ||
476 | * asks the user to provide the length of the response data buffer for the | ||
477 | * supplied IO request. | ||
478 | * @scic_user_task_request: This parameter points to the user's task request | ||
479 | * object. It is a cookie that allows the user to provide the necessary | ||
480 | * information for this callback. | ||
481 | * | ||
482 | * This method returns the length of the response buffer data associated with | ||
483 | * this IO request. | ||
484 | */ | ||
485 | u32 scic_cb_ssp_task_request_get_response_data_length( | ||
486 | void *scic_user_task_request); | ||
487 | |||
488 | /** | ||
489 | * scic_cb_pci_get_bar() - In this method the user must return the base address | ||
490 | * register (BAR) value for the supplied base address register number. | ||
491 | * @controller: The controller for which to retrieve the bar number. | ||
492 | * @bar_number: This parameter depicts the BAR index/number to be read. | ||
493 | * | ||
494 | * Return a pointer value indicating the contents of the BAR. NULL indicates an | ||
495 | * invalid BAR index/number was specified. All other values indicate a valid | ||
496 | * VIRTUAL address from the BAR. | ||
497 | */ | ||
498 | void *scic_cb_pci_get_bar( | ||
499 | struct scic_sds_controller *controller, | ||
500 | u16 bar_number); | ||
501 | |||
502 | /** | ||
503 | * scic_cb_get_virtual_address() - This callback method asks the user to | ||
504 | * provide the virtual address for the supplied physical address. | ||
505 | * @controller: This parameter is the core controller object handle. | ||
506 | * @physical_address: This parameter is the physical address which is to be | ||
507 | * returned as a virtual address. | ||
508 | * | ||
509 | * The method returns the virtual address for the supplied physical address. | ||
510 | */ | ||
511 | void *scic_cb_get_virtual_address( | ||
512 | struct scic_sds_controller *controller, | ||
513 | dma_addr_t physical_address); | ||
514 | |||
515 | /** | ||
516 | * scic_cb_port_stop_complete() - This method informs the user when a stop | ||
517 | * operation on the port has completed. | ||
518 | * @controller: This parameter represents the controller which contains the | ||
519 | * port. | ||
520 | * @port: This parameter specifies the SCI port object for which the callback | ||
521 | * is being invoked. | ||
522 | * @completion_status: This parameter specifies the status for the operation | ||
523 | * being completed. | ||
524 | * | ||
525 | */ | ||
526 | void scic_cb_port_stop_complete( | ||
527 | struct scic_sds_controller *controller, | ||
528 | struct scic_sds_port *port, | ||
529 | enum sci_status completion_status); | ||
530 | |||
531 | /** | ||
532 | * scic_cb_port_hard_reset_complete() - This method informs the user when a | ||
533 | * hard reset on the port has completed. This hard reset could have been | ||
534 | * initiated by the user or by the remote port. | ||
535 | * @controller: This parameter represents the controller which contains the | ||
536 | * port. | ||
537 | * @port: This parameter specifies the SCI port object for which the callback | ||
538 | * is being invoked. | ||
539 | * @completion_status: This parameter specifies the status for the operation | ||
540 | * being completed. | ||
541 | * | ||
542 | */ | ||
543 | void scic_cb_port_hard_reset_complete( | ||
544 | struct scic_sds_controller *controller, | ||
545 | struct scic_sds_port *port, | ||
546 | enum sci_status completion_status); | ||
547 | |||
548 | /** | ||
549 | * scic_cb_port_ready() - This method informs the user that the port is now in | ||
550 | * a ready state and can be utilized to issue IOs. | ||
551 | * @controller: This parameter represents the controller which contains the | ||
552 | * port. | ||
553 | * @port: This parameter specifies the SCI port object for which the callback | ||
554 | * is being invoked. | ||
555 | * | ||
556 | */ | ||
557 | void scic_cb_port_ready( | ||
558 | struct scic_sds_controller *controller, | ||
559 | struct scic_sds_port *port); | ||
560 | |||
561 | /** | ||
562 | * scic_cb_port_not_ready() - This method informs the user that the port is now | ||
563 | * not in a ready (i.e. busy) state and can't be utilized to issue IOs. | ||
564 | * @controller: This parameter represents the controller which contains the | ||
565 | * port. | ||
566 | * @port: This parameter specifies the SCI port object for which the callback | ||
567 | * is being invoked. | ||
568 | * @reason_code: This parameter specifies the reason for the port not ready | ||
569 | * callback. | ||
570 | * | ||
571 | */ | ||
572 | void scic_cb_port_not_ready( | ||
573 | struct scic_sds_controller *controller, | ||
574 | struct scic_sds_port *port, | ||
575 | u32 reason_code); | ||
576 | |||
577 | /** | ||
578 | * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that | ||
579 | * a phy/link became ready, but the phy is not allowed in the port. In some | ||
580 | * situations the underlying hardware only allows for certain phy to port | ||
581 | * mappings. If these mappings are violated, then this API is invoked. | ||
582 | * @controller: This parameter represents the controller which contains the | ||
583 | * port. | ||
584 | * @port: This parameter specifies the SCI port object for which the callback | ||
585 | * is being invoked. | ||
586 | * @phy: This parameter specifies the phy that came ready, but the phy can't be | ||
587 | * a valid member of the port. | ||
588 | * | ||
589 | */ | ||
590 | void scic_cb_port_invalid_link_up( | ||
591 | struct scic_sds_controller *controller, | ||
592 | struct scic_sds_port *port, | ||
593 | struct scic_sds_phy *phy); | ||
594 | |||
595 | /** | ||
596 | * scic_cb_port_bc_change_primitive_received() - This callback method informs | ||
597 | * the user that a broadcast change primitive was received. | ||
598 | * @controller: This parameter represents the controller which contains the | ||
599 | * port. | ||
600 | * @port: This parameter specifies the SCI port object for which the callback | ||
601 | * is being invoked. For instances where the phy on which the primitive was | ||
602 | * received is not part of a port, this parameter will be | ||
603 | * SCI_INVALID_HANDLE_T. | ||
604 | * @phy: This parameter specifies the phy on which the primitive was received. | ||
605 | * | ||
606 | */ | ||
607 | void scic_cb_port_bc_change_primitive_received( | ||
608 | struct scic_sds_controller *controller, | ||
609 | struct scic_sds_port *port, | ||
610 | struct scic_sds_phy *phy); | ||
611 | |||
612 | |||
613 | |||
614 | |||
615 | /** | ||
616 | * scic_cb_port_link_up() - This callback method informs the user that a phy | ||
617 | * has become operational and is capable of communicating with the remote | ||
618 | * end point. | ||
619 | * @controller: This parameter represents the controller associated with the | ||
620 | * phy. | ||
621 | * @port: This parameter specifies the port object for which the user callback | ||
622 | * is being invoked. There may be conditions where this parameter can be | ||
623 | * SCI_INVALID_HANDLE | ||
624 | * @phy: This parameter specifies the phy object for which the user callback is | ||
625 | * being invoked. | ||
626 | * | ||
627 | */ | ||
628 | void scic_cb_port_link_up( | ||
629 | struct scic_sds_controller *controller, | ||
630 | struct scic_sds_port *port, | ||
631 | struct scic_sds_phy *phy); | ||
632 | |||
633 | /** | ||
634 | * scic_cb_port_link_down() - This callback method informs the user that a phy | ||
635 | * is no longer operational and is not capable of communicating with the | ||
636 | * remote end point. | ||
637 | * @controller: This parameter represents the controller associated with the | ||
638 | * phy. | ||
639 | * @port: This parameter specifies the port object for which the user callback | ||
640 | * is being invoked. There may be conditions where this parameter can be | ||
641 | * SCI_INVALID_HANDLE | ||
642 | * @phy: This parameter specifies the phy object for which the user callback is | ||
643 | * being invoked. | ||
644 | * | ||
645 | */ | ||
646 | void scic_cb_port_link_down( | ||
647 | struct scic_sds_controller *controller, | ||
648 | struct scic_sds_port *port, | ||
649 | struct scic_sds_phy *phy); | ||
650 | |||
651 | /** | ||
652 | * scic_cb_remote_device_start_complete() - This user callback method will | ||
653 | * inform the user that a start operation has completed. | ||
654 | * @controller: This parameter specifies the core controller associated with | ||
655 | * the completion callback. | ||
656 | * @remote_device: This parameter specifies the remote device associated with | ||
657 | * the completion callback. | ||
658 | * @completion_status: This parameter specifies the completion status for the | ||
659 | * operation. | ||
660 | * | ||
661 | */ | ||
662 | void scic_cb_remote_device_start_complete( | ||
663 | struct scic_sds_controller *controller, | ||
664 | struct scic_sds_remote_device *remote_device, | ||
665 | enum sci_status completion_status); | ||
666 | |||
667 | /** | ||
668 | * scic_cb_remote_device_stop_complete() - This user callback method will | ||
669 | * inform the user that a stop operation has completed. | ||
670 | * @controller: This parameter specifies the core controller associated with | ||
671 | * the completion callback. | ||
672 | * @remote_device: This parameter specifies the remote device associated with | ||
673 | * the completion callback. | ||
674 | * @completion_status: This parameter specifies the completion status for the | ||
675 | * operation. | ||
676 | * | ||
677 | */ | ||
678 | void scic_cb_remote_device_stop_complete( | ||
679 | struct scic_sds_controller *controller, | ||
680 | struct scic_sds_remote_device *remote_device, | ||
681 | enum sci_status completion_status); | ||
682 | |||
683 | /** | ||
684 | * scic_cb_remote_device_ready() - This user callback method will inform the | ||
685 | * user that a remote device is now capable of handling IO requests. | ||
686 | * @controller: This parameter specifies the core controller associated with | ||
687 | * the completion callback. | ||
688 | * @remote_device: This parameter specifies the remote device associated with | ||
689 | * the callback. | ||
690 | * | ||
691 | */ | ||
692 | void scic_cb_remote_device_ready( | ||
693 | struct scic_sds_controller *controller, | ||
694 | struct scic_sds_remote_device *remote_device); | ||
695 | |||
696 | /** | ||
697 | * scic_cb_remote_device_not_ready() - This user callback method will inform | ||
698 | * the user that a remote device is no longer capable of handling IO | ||
699 | * requests (until a ready callback is invoked). | ||
700 | * @controller: This parameter specifies the core controller associated with | ||
701 | * the completion callback. | ||
702 | * @remote_device: This parameter specifies the remote device associated with | ||
703 | * the callback. | ||
704 | * @reason_code: This paramete specifies the reason the remote device is not | ||
705 | * ready. | ||
706 | * | ||
707 | */ | ||
708 | void scic_cb_remote_device_not_ready( | ||
709 | struct scic_sds_controller *controller, | ||
710 | struct scic_sds_remote_device *remote_device, | ||
711 | u32 reason_code); | ||
712 | |||
713 | #if !defined(DISABLE_ATAPI) | ||
714 | /** | ||
715 | * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback gets | ||
716 | * from stp packet io's user request the CDB address. | ||
717 | * @scic_user_io_request: | ||
718 | * | ||
719 | * The cdb adress. | ||
720 | */ | ||
721 | void *scic_cb_stp_packet_io_request_get_cdb_address( | ||
722 | void *scic_user_io_request); | ||
723 | |||
724 | /** | ||
725 | * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback gets | ||
726 | * from stp packet io's user request the CDB length. | ||
727 | * @scic_user_io_request: | ||
728 | * | ||
729 | * The cdb length. | ||
730 | */ | ||
731 | u32 scic_cb_stp_packet_io_request_get_cdb_length( | ||
732 | void *scic_user_io_request); | ||
733 | #else /* !defined(DISABLE_ATAPI) */ | ||
734 | #define scic_cb_stp_packet_io_request_get_cdb_address(scic_user_io_request) NULL | ||
735 | #define scic_cb_stp_packet_io_request_get_cdb_length(scic_user_io_request) 0 | ||
736 | #endif /* !defined(DISABLE_ATAPI) */ | ||
737 | |||
738 | |||
739 | #endif /* _SCIC_USER_CALLBACK_H_ */ | ||
740 | |||
diff --git a/drivers/scsi/isci/core/scu_completion_codes.h b/drivers/scsi/isci/core/scu_completion_codes.h new file mode 100644 index 000000000000..17ee4c8b9122 --- /dev/null +++ b/drivers/scsi/isci/core/scu_completion_codes.h | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCU_COMPLETION_CODES_HEADER_ | ||
57 | #define _SCU_COMPLETION_CODES_HEADER_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the constants and macros for the SCU hardware completion | ||
61 | * codes. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #define SCU_COMPLETION_TYPE_SHIFT 28 | ||
67 | #define SCU_COMPLETION_TYPE_MASK 0x70000000 | ||
68 | |||
69 | /** | ||
70 | * SCU_COMPLETION_TYPE() - | ||
71 | * | ||
72 | * This macro constructs an SCU completion type | ||
73 | */ | ||
74 | #define SCU_COMPLETION_TYPE(type) \ | ||
75 | ((u32)(type) << SCU_COMPLETION_TYPE_SHIFT) | ||
76 | |||
77 | /** | ||
78 | * SCU_COMPLETION_TYPE() - | ||
79 | * | ||
80 | * These macros contain the SCU completion types SCU_COMPLETION_TYPE | ||
81 | */ | ||
82 | #define SCU_COMPLETION_TYPE_TASK SCU_COMPLETION_TYPE(0) | ||
83 | #define SCU_COMPLETION_TYPE_SDMA SCU_COMPLETION_TYPE(1) | ||
84 | #define SCU_COMPLETION_TYPE_UFI SCU_COMPLETION_TYPE(2) | ||
85 | #define SCU_COMPLETION_TYPE_EVENT SCU_COMPLETION_TYPE(3) | ||
86 | #define SCU_COMPLETION_TYPE_NOTIFY SCU_COMPLETION_TYPE(4) | ||
87 | |||
88 | /** | ||
89 | * | ||
90 | * | ||
91 | * These constants provide the shift and mask values for the various parts of | ||
92 | * an SCU completion code. | ||
93 | */ | ||
94 | #define SCU_COMPLETION_STATUS_MASK 0x0FFC0000 | ||
95 | #define SCU_COMPLETION_TL_STATUS_MASK 0x0FC00000 | ||
96 | #define SCU_COMPLETION_TL_STATUS_SHIFT 22 | ||
97 | #define SCU_COMPLETION_SDMA_STATUS_MASK 0x003C0000 | ||
98 | #define SCU_COMPLETION_PEG_MASK 0x00010000 | ||
99 | #define SCU_COMPLETION_PORT_MASK 0x00007000 | ||
100 | #define SCU_COMPLETION_PE_MASK SCU_COMPLETION_PORT_MASK | ||
101 | #define SCU_COMPLETION_PE_SHIFT 12 | ||
102 | #define SCU_COMPLETION_INDEX_MASK 0x00000FFF | ||
103 | |||
104 | /** | ||
105 | * SCU_GET_COMPLETION_TYPE() - | ||
106 | * | ||
107 | * This macro returns the SCU completion type. | ||
108 | */ | ||
109 | #define SCU_GET_COMPLETION_TYPE(completion_code) \ | ||
110 | ((completion_code) & SCU_COMPLETION_TYPE_MASK) | ||
111 | |||
112 | /** | ||
113 | * SCU_GET_COMPLETION_STATUS() - | ||
114 | * | ||
115 | * This macro returns the SCU completion status. | ||
116 | */ | ||
117 | #define SCU_GET_COMPLETION_STATUS(completion_code) \ | ||
118 | ((completion_code) & SCU_COMPLETION_STATUS_MASK) | ||
119 | |||
120 | /** | ||
121 | * SCU_GET_COMPLETION_TL_STATUS() - | ||
122 | * | ||
123 | * This macro returns the transport layer completion status. | ||
124 | */ | ||
125 | #define SCU_GET_COMPLETION_TL_STATUS(completion_code) \ | ||
126 | ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) | ||
127 | |||
128 | /** | ||
129 | * SCU_MAKE_COMPLETION_STATUS() - | ||
130 | * | ||
131 | * This macro takes a completion code and performs the shift and mask | ||
132 | * operations to turn it into a completion code that can be compared to a | ||
133 | * SCU_GET_COMPLETION_TL_STATUS. | ||
134 | */ | ||
135 | #define SCU_MAKE_COMPLETION_STATUS(completion_code) \ | ||
136 | ((u32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT) | ||
137 | |||
138 | /** | ||
139 | * SCU_NORMALIZE_COMPLETION_STATUS() - | ||
140 | * | ||
141 | * This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a | ||
142 | * return code. | ||
143 | */ | ||
144 | #define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \ | ||
145 | (\ | ||
146 | ((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) \ | ||
147 | >> SCU_COMPLETION_TL_STATUS_SHIFT \ | ||
148 | ) | ||
149 | |||
150 | /** | ||
151 | * SCU_GET_COMPLETION_SDMA_STATUS() - | ||
152 | * | ||
153 | * This macro returns the SDMA completion status. | ||
154 | */ | ||
155 | #define SCU_GET_COMPLETION_SDMA_STATUS(completion_code) \ | ||
156 | ((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK) | ||
157 | |||
158 | /** | ||
159 | * SCU_GET_COMPLETION_PEG() - | ||
160 | * | ||
161 | * This macro returns the Protocol Engine Group from the completion code. | ||
162 | */ | ||
163 | #define SCU_GET_COMPLETION_PEG(completion_code) \ | ||
164 | ((completion_code) & SCU_COMPLETION_PEG_MASK) | ||
165 | |||
166 | /** | ||
167 | * SCU_GET_COMPLETION_PORT() - | ||
168 | * | ||
169 | * This macro reuturns the logical port index from the completion code. | ||
170 | */ | ||
171 | #define SCU_GET_COMPLETION_PORT(completion_code) \ | ||
172 | ((completion_code) & SCU_COMPLETION_PORT_MASK) | ||
173 | |||
174 | /** | ||
175 | * SCU_GET_PROTOCOL_ENGINE_INDEX() - | ||
176 | * | ||
177 | * This macro returns the PE index from the completion code. | ||
178 | */ | ||
179 | #define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \ | ||
180 | (((completion_code) & SCU_COMPLETION_PE_MASK) >> SCU_COMPLETION_PE_SHIFT) | ||
181 | |||
182 | /** | ||
183 | * SCU_GET_COMPLETION_INDEX() - | ||
184 | * | ||
185 | * This macro returns the index of the completion which is either a TCi or an | ||
186 | * RNi depending on the completion type. | ||
187 | */ | ||
188 | #define SCU_GET_COMPLETION_INDEX(completion_code) \ | ||
189 | ((completion_code) & SCU_COMPLETION_INDEX_MASK) | ||
190 | |||
191 | #define SCU_UNSOLICITED_FRAME_MASK 0x0FFF0000 | ||
192 | #define SCU_UNSOLICITED_FRAME_SHIFT 16 | ||
193 | |||
194 | /** | ||
195 | * SCU_GET_FRAME_INDEX() - | ||
196 | * | ||
197 | * This macro returns a normalized frame index from an unsolicited frame | ||
198 | * completion. | ||
199 | */ | ||
200 | #define SCU_GET_FRAME_INDEX(completion_code) \ | ||
201 | (\ | ||
202 | ((completion_code) & SCU_UNSOLICITED_FRAME_MASK) \ | ||
203 | >> SCU_UNSOLICITED_FRAME_SHIFT \ | ||
204 | ) | ||
205 | |||
206 | #define SCU_UNSOLICITED_FRAME_ERROR_MASK 0x00008000 | ||
207 | |||
208 | /** | ||
209 | * SCU_GET_FRAME_ERROR() - | ||
210 | * | ||
211 | * This macro returns a zero (0) value if there is no frame error otherwise it | ||
212 | * returns non-zero (!0). | ||
213 | */ | ||
214 | #define SCU_GET_FRAME_ERROR(completion_code) \ | ||
215 | ((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK) | ||
216 | |||
217 | /** | ||
218 | * | ||
219 | * | ||
220 | * These constants represent normalized completion codes which must be shifted | ||
221 | * 18 bits to match it with the hardware completion code. In a 16-bit compiler, | ||
222 | * immediate constants are 16-bit values (the size of an int). If we shift | ||
223 | * those by 18 bits, we completely lose the value. To ensure the value is a | ||
224 | * 32-bit value like we want, each immediate value must be cast to a u32. | ||
225 | */ | ||
226 | #define SCU_TASK_DONE_GOOD ((u32)0x00) | ||
227 | #define SCU_TASK_DONE_CRC_ERR ((u32)0x14) | ||
228 | #define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14) | ||
229 | #define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15) | ||
230 | #define SCU_TASK_DONE_NAK_CMD_ERR ((u32)0x16) | ||
231 | #define SCU_TASK_DONE_LL_R_ERR ((u32)0x17) | ||
232 | #define SCU_TASK_DONE_ACK_NAK_TO ((u32)0x17) | ||
233 | #define SCU_TASK_DONE_LL_PERR ((u32)0x18) | ||
234 | #define SCU_TASK_DONE_LL_SY_TERM ((u32)0x19) | ||
235 | #define SCU_TASK_DONE_NAK_ERR ((u32)0x19) | ||
236 | #define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A) | ||
237 | #define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A) | ||
238 | #define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B) | ||
239 | #define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B) | ||
240 | #define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C) | ||
241 | #define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C) | ||
242 | #define SCU_TASK_DONE_INV_FIS_TYPE ((u32)0x1D) | ||
243 | #define SCU_TASK_DONE_XR_IU_LEN_ERR ((u32)0x1D) | ||
244 | #define SCU_TASK_DONE_INV_FIS_LEN ((u32)0x1E) | ||
245 | #define SCU_TASK_DONE_XR_WD_LEN ((u32)0x1E) | ||
246 | #define SCU_TASK_DONE_SDMA_ERR ((u32)0x1F) | ||
247 | #define SCU_TASK_DONE_OFFSET_ERR ((u32)0x20) | ||
248 | #define SCU_TASK_DONE_MAX_PLD_ERR ((u32)0x21) | ||
249 | #define SCU_TASK_DONE_EXCESS_DATA ((u32)0x22) | ||
250 | #define SCU_TASK_DONE_LF_ERR ((u32)0x23) | ||
251 | #define SCU_TASK_DONE_UNEXP_FIS ((u32)0x24) | ||
252 | #define SCU_TASK_DONE_UNEXP_RESP ((u32)0x24) | ||
253 | #define SCU_TASK_DONE_EARLY_RESP ((u32)0x25) | ||
254 | #define SCU_TASK_DONE_SMP_RESP_TO_ERR ((u32)0x26) | ||
255 | #define SCU_TASK_DONE_DMASETUP_DIRERR ((u32)0x27) | ||
256 | #define SCU_TASK_DONE_SMP_UFI_ERR ((u32)0x27) | ||
257 | #define SCU_TASK_DONE_XFERCNT_ERR ((u32)0x28) | ||
258 | #define SCU_TASK_DONE_SMP_FRM_TYPE_ERR ((u32)0x28) | ||
259 | #define SCU_TASK_DONE_SMP_LL_RX_ERR ((u32)0x29) | ||
260 | #define SCU_TASK_DONE_RESP_LEN_ERR ((u32)0x2A) | ||
261 | #define SCU_TASK_DONE_UNEXP_DATA ((u32)0x2B) | ||
262 | #define SCU_TASK_DONE_OPEN_FAIL ((u32)0x2C) | ||
263 | #define SCU_TASK_DONE_UNEXP_SDBFIS ((u32)0x2D) | ||
264 | #define SCU_TASK_DONE_REG_ERR ((u32)0x2E) | ||
265 | #define SCU_TASK_DONE_SDB_ERR ((u32)0x2F) | ||
266 | #define SCU_TASK_DONE_TASK_ABORT ((u32)0x30) | ||
267 | #define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION ((u32)0x34) | ||
268 | #define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1 ((u32)0x35) | ||
269 | #define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2 ((u32)0x36) | ||
270 | #define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3 ((u32)0x37) | ||
271 | #define SCU_TASK_OPEN_REJECT_BAD_DESTINATION ((u32)0x38) | ||
272 | #define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION ((u32)0x39) | ||
273 | #define SCU_TASK_DONE_VIIT_ENTRY_NV ((u32)0x3A) | ||
274 | #define SCU_TASK_DONE_IIT_ENTRY_NV ((u32)0x3B) | ||
275 | #define SCU_TASK_DONE_RNCNV_OUTBOUND ((u32)0x3C) | ||
276 | #define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY ((u32)0x3D) | ||
277 | #define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED ((u32)0x3E) | ||
278 | #define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED ((u32)0x3F) | ||
279 | |||
280 | #endif /* _SCU_COMPLETION_CODES_HEADER_ */ | ||
diff --git a/drivers/scsi/isci/core/scu_constants.h b/drivers/scsi/isci/core/scu_constants.h new file mode 100644 index 000000000000..a99d1103ad3b --- /dev/null +++ b/drivers/scsi/isci/core/scu_constants.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCU_CONSTANTS_H_ | ||
57 | #define _SCU_CONSTANTS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the SCU hardware constants. | ||
61 | * | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | #include "sci_controller_constants.h" | ||
66 | |||
67 | /** | ||
68 | * | ||
69 | * | ||
70 | * 2 indicates the maximum number of UFs that can occur for a given IO request. | ||
71 | * The hardware handles reception of additional unsolicited frames while all | ||
72 | * UFs are in use, by holding off the transmitting device. This number could | ||
73 | * be theoretically reduced to 1, but 2 provides for more reliable operation. | ||
74 | * During SATA PIO operation, it is possible under some conditions for there to | ||
75 | * be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H | ||
76 | * Register). It is unlikely to have all 3 pending all at once without some of | ||
77 | * them already being processed. | ||
78 | */ | ||
79 | #define SCU_MIN_UNSOLICITED_FRAMES (1) | ||
80 | #define SCU_MIN_CRITICAL_NOTIFICATIONS (24) | ||
81 | #define SCU_MIN_EVENTS (4) | ||
82 | #define SCU_MIN_COMPLETION_QUEUE_SCRATCH (2) | ||
83 | #define SCU_MIN_COMPLETION_QUEUE_ENTRIES (SCU_MIN_CRITICAL_NOTIFICATIONS \ | ||
84 | + SCU_MIN_EVENTS \ | ||
85 | + SCU_MIN_UNSOLICITED_FRAMES \ | ||
86 | + SCI_MIN_IO_REQUESTS \ | ||
87 | + SCU_MIN_COMPLETION_QUEUE_SCRATCH) | ||
88 | |||
89 | #define SCU_MAX_CRITICAL_NOTIFICATIONS (384) | ||
90 | #define SCU_MAX_EVENTS (128) | ||
91 | #define SCU_MAX_UNSOLICITED_FRAMES (128) | ||
92 | #define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128) | ||
93 | #define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \ | ||
94 | + SCU_MAX_EVENTS \ | ||
95 | + SCU_MAX_UNSOLICITED_FRAMES \ | ||
96 | + SCI_MAX_IO_REQUESTS \ | ||
97 | + SCU_MAX_COMPLETION_QUEUE_SCRATCH) | ||
98 | |||
99 | #if !defined(ENABLE_MINIMUM_MEMORY_MODE) | ||
100 | #define SCU_UNSOLICITED_FRAME_COUNT SCU_MAX_UNSOLICITED_FRAMES | ||
101 | #define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MAX_CRITICAL_NOTIFICATIONS | ||
102 | #define SCU_EVENT_COUNT SCU_MAX_EVENTS | ||
103 | #define SCU_COMPLETION_QUEUE_SCRATCH SCU_MAX_COMPLETION_QUEUE_SCRATCH | ||
104 | #define SCU_IO_REQUEST_COUNT SCI_MAX_IO_REQUESTS | ||
105 | #define SCU_IO_REQUEST_SGE_COUNT SCI_MAX_SCATTER_GATHER_ELEMENTS | ||
106 | #define SCU_COMPLETION_QUEUE_COUNT SCU_MAX_COMPLETION_QUEUE_ENTRIES | ||
107 | #else | ||
108 | #define SCU_UNSOLICITED_FRAME_COUNT SCU_MIN_UNSOLICITED_FRAMES | ||
109 | #define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MIN_CRITICAL_NOTIFICATIONS | ||
110 | #define SCU_EVENT_COUNT SCU_MIN_EVENTS | ||
111 | #define SCU_COMPLETION_QUEUE_SCRATCH SCU_MIN_COMPLETION_QUEUE_SCRATCH | ||
112 | #define SCU_IO_REQUEST_COUNT SCI_MIN_IO_REQUESTS | ||
113 | #define SCU_IO_REQUEST_SGE_COUNT SCI_MIN_SCATTER_GATHER_ELEMENTS | ||
114 | #define SCU_COMPLETION_QUEUE_COUNT SCU_MIN_COMPLETION_QUEUE_ENTRIES | ||
115 | #endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */ | ||
116 | |||
117 | /** | ||
118 | * | ||
119 | * | ||
120 | * The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion | ||
121 | * queue into which the hardware DMAs 32-bit quantas (completion entries). | ||
122 | */ | ||
123 | |||
124 | /** | ||
125 | * | ||
126 | * | ||
127 | * This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.). | ||
128 | */ | ||
129 | #if (SCU_COMPLETION_QUEUE_COUNT != 16) && \ | ||
130 | (SCU_COMPLETION_QUEUE_COUNT != 32) && \ | ||
131 | (SCU_COMPLETION_QUEUE_COUNT != 64) && \ | ||
132 | (SCU_COMPLETION_QUEUE_COUNT != 128) && \ | ||
133 | (SCU_COMPLETION_QUEUE_COUNT != 256) && \ | ||
134 | (SCU_COMPLETION_QUEUE_COUNT != 512) && \ | ||
135 | (SCU_COMPLETION_QUEUE_COUNT != 1024) | ||
136 | #error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2." | ||
137 | #endif | ||
138 | |||
139 | #if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES | ||
140 | #error "Invalid configuration of unsolicited frame constants" | ||
141 | #endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */ | ||
142 | |||
143 | #define SCU_MIN_UF_TABLE_ENTRIES (8) | ||
144 | #define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096) | ||
145 | #define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024) | ||
146 | #define SCU_INVALID_FRAME_INDEX (0xFFFF) | ||
147 | |||
148 | #define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF) | ||
149 | #define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF) | ||
150 | |||
151 | #endif /* _SCU_CONSTANTS_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scu_event_codes.h b/drivers/scsi/isci/core/scu_event_codes.h new file mode 100644 index 000000000000..36a945ad5722 --- /dev/null +++ b/drivers/scsi/isci/core/scu_event_codes.h | |||
@@ -0,0 +1,336 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef __SCU_EVENT_CODES_HEADER__ | ||
57 | #define __SCU_EVENT_CODES_HEADER__ | ||
58 | |||
59 | /** | ||
60 | * This file contains the constants and macros for the SCU event codes. | ||
61 | * | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | #define SCU_EVENT_TYPE_CODE_SHIFT 24 | ||
66 | #define SCU_EVENT_TYPE_CODE_MASK 0x0F000000 | ||
67 | |||
68 | #define SCU_EVENT_SPECIFIC_CODE_SHIFT 18 | ||
69 | #define SCU_EVENT_SPECIFIC_CODE_MASK 0x00FC0000 | ||
70 | |||
71 | #define SCU_EVENT_CODE_MASK \ | ||
72 | (SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK) | ||
73 | |||
74 | /** | ||
75 | * SCU_EVENT_TYPE() - | ||
76 | * | ||
77 | * This macro constructs an SCU event type from the type value. | ||
78 | */ | ||
79 | #define SCU_EVENT_TYPE(type) \ | ||
80 | ((u32)(type) << SCU_EVENT_TYPE_CODE_SHIFT) | ||
81 | |||
82 | /** | ||
83 | * SCU_EVENT_SPECIFIC() - | ||
84 | * | ||
85 | * This macro constructs an SCU event specifier from the code value. | ||
86 | */ | ||
87 | #define SCU_EVENT_SPECIFIC(code) \ | ||
88 | ((u32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT) | ||
89 | |||
90 | /** | ||
91 | * SCU_EVENT_MESSAGE() - | ||
92 | * | ||
93 | * This macro constructs a combines an SCU event type and SCU event specifier | ||
94 | * from the type and code values. | ||
95 | */ | ||
96 | #define SCU_EVENT_MESSAGE(type, code) \ | ||
97 | ((type) | SCU_EVENT_SPECIFIC(code)) | ||
98 | |||
99 | /** | ||
100 | * SCU_EVENT_TYPE() - | ||
101 | * | ||
102 | * SCU_EVENT_TYPES | ||
103 | */ | ||
104 | #define SCU_EVENT_TYPE_SMU_COMMAND_ERROR SCU_EVENT_TYPE(0x08) | ||
105 | #define SCU_EVENT_TYPE_SMU_PCQ_ERROR SCU_EVENT_TYPE(0x09) | ||
106 | #define SCU_EVENT_TYPE_SMU_ERROR SCU_EVENT_TYPE(0x00) | ||
107 | #define SCU_EVENT_TYPE_TRANSPORT_ERROR SCU_EVENT_TYPE(0x01) | ||
108 | #define SCU_EVENT_TYPE_BROADCAST_CHANGE SCU_EVENT_TYPE(0x02) | ||
109 | #define SCU_EVENT_TYPE_OSSP_EVENT SCU_EVENT_TYPE(0x03) | ||
110 | #define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F) | ||
111 | #define SCU_EVENT_TYPE_RNC_SUSPEND_TX SCU_EVENT_TYPE(0x04) | ||
112 | #define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX SCU_EVENT_TYPE(0x05) | ||
113 | #define SCU_EVENT_TYPE_RNC_OPS_MISC SCU_EVENT_TYPE(0x06) | ||
114 | #define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07) | ||
115 | #define SCU_EVENT_TYPE_ERR_CNT_EVENT SCU_EVENT_TYPE(0x0A) | ||
116 | |||
117 | /** | ||
118 | * | ||
119 | * | ||
120 | * SCU_EVENT_SPECIFIERS | ||
121 | */ | ||
122 | #define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20 | ||
123 | #define SCU_EVENT_SPECIFIER_RNC_RELEASE 0x00 | ||
124 | |||
125 | /** | ||
126 | * | ||
127 | * | ||
128 | * SMU_COMMAND_EVENTS | ||
129 | */ | ||
130 | #define SCU_EVENT_INVALID_CONTEXT_COMMAND \ | ||
131 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00) | ||
132 | |||
133 | /** | ||
134 | * | ||
135 | * | ||
136 | * SMU_PCQ_EVENTS | ||
137 | */ | ||
138 | #define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \ | ||
139 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00) | ||
140 | |||
141 | /** | ||
142 | * | ||
143 | * | ||
144 | * SMU_EVENTS | ||
145 | */ | ||
146 | #define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \ | ||
147 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02) | ||
148 | #define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \ | ||
149 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03) | ||
150 | #define SCU_EVENT_PCIE_INTERFACE_ERROR \ | ||
151 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04) | ||
152 | #define SCU_EVENT_FUNCTION_LEVEL_RESET \ | ||
153 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05) | ||
154 | |||
155 | /** | ||
156 | * | ||
157 | * | ||
158 | * TRANSPORT_LEVEL_ERRORS | ||
159 | */ | ||
160 | #define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR \ | ||
161 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00) | ||
162 | |||
163 | /** | ||
164 | * | ||
165 | * | ||
166 | * BROADCAST_CHANGE_EVENTS | ||
167 | */ | ||
168 | #define SCU_EVENT_BROADCAST_CHANGE \ | ||
169 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01) | ||
170 | #define SCU_EVENT_BROADCAST_RESERVED0 \ | ||
171 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02) | ||
172 | #define SCU_EVENT_BROADCAST_RESERVED1 \ | ||
173 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03) | ||
174 | #define SCU_EVENT_BROADCAST_SES \ | ||
175 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04) | ||
176 | #define SCU_EVENT_BROADCAST_EXPANDER \ | ||
177 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05) | ||
178 | #define SCU_EVENT_BROADCAST_AEN \ | ||
179 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06) | ||
180 | #define SCU_EVENT_BROADCAST_RESERVED3 \ | ||
181 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07) | ||
182 | #define SCU_EVENT_BROADCAST_RESERVED4 \ | ||
183 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08) | ||
184 | #define SCU_EVENT_PE_SUSPENDED \ | ||
185 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09) | ||
186 | |||
187 | /** | ||
188 | * | ||
189 | * | ||
190 | * OSSP_EVENTS | ||
191 | */ | ||
192 | #define SCU_EVENT_PORT_SELECTOR_DETECTED \ | ||
193 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10) | ||
194 | #define SCU_EVENT_SENT_PORT_SELECTION \ | ||
195 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11) | ||
196 | #define SCU_EVENT_HARD_RESET_TRANSMITTED \ | ||
197 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12) | ||
198 | #define SCU_EVENT_HARD_RESET_RECEIVED \ | ||
199 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13) | ||
200 | #define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \ | ||
201 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15) | ||
202 | #define SCU_EVENT_LINK_FAILURE \ | ||
203 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16) | ||
204 | #define SCU_EVENT_SATA_SPINUP_HOLD \ | ||
205 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17) | ||
206 | #define SCU_EVENT_SAS_15_SSC \ | ||
207 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18) | ||
208 | #define SCU_EVENT_SAS_15 \ | ||
209 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19) | ||
210 | #define SCU_EVENT_SAS_30_SSC \ | ||
211 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A) | ||
212 | #define SCU_EVENT_SAS_30 \ | ||
213 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B) | ||
214 | #define SCU_EVENT_SAS_60_SSC \ | ||
215 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C) | ||
216 | #define SCU_EVENT_SAS_60 \ | ||
217 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D) | ||
218 | #define SCU_EVENT_SATA_15_SSC \ | ||
219 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E) | ||
220 | #define SCU_EVENT_SATA_15 \ | ||
221 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F) | ||
222 | #define SCU_EVENT_SATA_30_SSC \ | ||
223 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20) | ||
224 | #define SCU_EVENT_SATA_30 \ | ||
225 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21) | ||
226 | #define SCU_EVENT_SATA_60_SSC \ | ||
227 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22) | ||
228 | #define SCU_EVENT_SATA_60 \ | ||
229 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23) | ||
230 | #define SCU_EVENT_SAS_PHY_DETECTED \ | ||
231 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24) | ||
232 | #define SCU_EVENT_SATA_PHY_DETECTED \ | ||
233 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25) | ||
234 | |||
235 | /** | ||
236 | * | ||
237 | * | ||
238 | * FATAL_INTERNAL_MEMORY_ERROR_EVENTS | ||
239 | */ | ||
240 | #define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \ | ||
241 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x00) | ||
242 | #define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \ | ||
243 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x01) | ||
244 | #define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \ | ||
245 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x02) | ||
246 | |||
247 | /** | ||
248 | * | ||
249 | * | ||
250 | * REMOTE_NODE_SUSPEND_EVENTS | ||
251 | */ | ||
252 | #define SCU_EVENT_TL_RNC_SUSPEND_TX \ | ||
253 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00) | ||
254 | #define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \ | ||
255 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00) | ||
256 | #define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \ | ||
257 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20) | ||
258 | #define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX \ | ||
259 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20) | ||
260 | |||
261 | /** | ||
262 | * | ||
263 | * | ||
264 | * REMOTE_NODE_MISC_EVENTS | ||
265 | */ | ||
266 | #define SCU_EVENT_POST_RCN_RELEASE \ | ||
267 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, SCU_EVENT_SPECIFIER_RNC_RELEASE) | ||
268 | #define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \ | ||
269 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01) | ||
270 | #define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \ | ||
271 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02) | ||
272 | #define SCU_EVENT_POST_RNC_COMPLETE \ | ||
273 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03) | ||
274 | #define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \ | ||
275 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04) | ||
276 | |||
277 | /** | ||
278 | * | ||
279 | * | ||
280 | * ERROR_COUNT_EVENT | ||
281 | */ | ||
282 | #define SCU_EVENT_RX_CREDIT_BLOCKED_RECEIVED \ | ||
283 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x00) | ||
284 | #define SCU_EVENT_TX_DONE_CREDIT_TIMEOUT \ | ||
285 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x01) | ||
286 | #define SCU_EVENT_RX_DONE_CREDIT_TIMEOUT \ | ||
287 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x02) | ||
288 | |||
289 | /** | ||
290 | * scu_get_event_type() - | ||
291 | * | ||
292 | * This macro returns the SCU event type from the event code. | ||
293 | */ | ||
294 | #define scu_get_event_type(event_code) \ | ||
295 | ((event_code) & SCU_EVENT_TYPE_CODE_MASK) | ||
296 | |||
297 | /** | ||
298 | * scu_get_event_specifier() - | ||
299 | * | ||
300 | * This macro returns the SCU event specifier from the event code. | ||
301 | */ | ||
302 | #define scu_get_event_specifier(event_code) \ | ||
303 | ((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK) | ||
304 | |||
305 | /** | ||
306 | * scu_get_event_code() - | ||
307 | * | ||
308 | * This macro returns the combined SCU event type and SCU event specifier from | ||
309 | * the event code. | ||
310 | */ | ||
311 | #define scu_get_event_code(event_code) \ | ||
312 | ((event_code) & SCU_EVENT_CODE_MASK) | ||
313 | |||
314 | |||
315 | /** | ||
316 | * | ||
317 | * | ||
318 | * PTS_SCHEDULE_EVENT | ||
319 | */ | ||
320 | #define SCU_EVENT_SMP_RESPONSE_NO_PE \ | ||
321 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00) | ||
322 | #define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \ | ||
323 | scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE) | ||
324 | |||
325 | #define SCU_EVENT_TASK_TIMEOUT \ | ||
326 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01) | ||
327 | #define SCU_EVENT_SPECIFIC_TASK_TIMEOUT \ | ||
328 | scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT) | ||
329 | |||
330 | #define SCU_EVENT_IT_NEXUS_TIMEOUT \ | ||
331 | SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02) | ||
332 | #define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \ | ||
333 | scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT) | ||
334 | |||
335 | |||
336 | #endif /* __SCU_EVENT_CODES_HEADER__ */ | ||
diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h new file mode 100644 index 000000000000..175d2b98bdf2 --- /dev/null +++ b/drivers/scsi/isci/core/scu_registers.h | |||
@@ -0,0 +1,1824 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCU_REGISTERS_H_ | ||
57 | #define _SCU_REGISTERS_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the constants and structures for the SCU memory mapped | ||
61 | * registers. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_types.h" | ||
67 | #include "scu_viit_data.h" | ||
68 | |||
69 | |||
70 | /* Generate a value for an SCU register */ | ||
71 | #define SCU_GEN_VALUE(name, value) \ | ||
72 | (((value) << name ## _SHIFT) & (name ## _MASK)) | ||
73 | |||
74 | /* | ||
75 | * Generate a bit value for an SCU register | ||
76 | * Make sure that the register MASK is just a single bit */ | ||
77 | #define SCU_GEN_BIT(name) \ | ||
78 | SCU_GEN_VALUE(name, ((u32)1)) | ||
79 | |||
80 | #define SCU_SET_BIT(name, reg_value) \ | ||
81 | ((reg_value) | SCU_GEN_BIT(name)) | ||
82 | |||
83 | #define SCU_CLEAR_BIT(name, reg_value) \ | ||
84 | ((reg_value)$ ~(SCU_GEN_BIT(name))) | ||
85 | |||
86 | /* | ||
87 | * ***************************************************************************** | ||
88 | * Unions for bitfield definitions of SCU Registers | ||
89 | * SMU Post Context Port | ||
90 | * ***************************************************************************** */ | ||
91 | #define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_SHIFT (0) | ||
92 | #define SMU_POST_CONTEXT_PORT_CONTEXT_INDEX_MASK (0x00000FFF) | ||
93 | #define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_SHIFT (12) | ||
94 | #define SMU_POST_CONTEXT_PORT_LOGICAL_PORT_INDEX_MASK (0x0000F000) | ||
95 | #define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_SHIFT (16) | ||
96 | #define SMU_POST_CONTEXT_PORT_PROTOCOL_ENGINE_MASK (0x00030000) | ||
97 | #define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_SHIFT (18) | ||
98 | #define SMU_POST_CONTEXT_PORT_COMMAND_CONTEXT_MASK (0x00FC0000) | ||
99 | #define SMU_POST_CONTEXT_PORT_RESERVED_MASK (0xFF000000) | ||
100 | |||
101 | #define SMU_PCP_GEN_VAL(name, value) \ | ||
102 | SCU_GEN_VALUE(SMU_POST_CONTEXT_PORT_ ## name, value) | ||
103 | |||
104 | /* ***************************************************************************** */ | ||
105 | #define SMU_INTERRUPT_STATUS_COMPLETION_SHIFT (31) | ||
106 | #define SMU_INTERRUPT_STATUS_COMPLETION_MASK (0x80000000) | ||
107 | #define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_SHIFT (1) | ||
108 | #define SMU_INTERRUPT_STATUS_QUEUE_SUSPEND_MASK (0x00000002) | ||
109 | #define SMU_INTERRUPT_STATUS_QUEUE_ERROR_SHIFT (0) | ||
110 | #define SMU_INTERRUPT_STATUS_QUEUE_ERROR_MASK (0x00000001) | ||
111 | #define SMU_INTERRUPT_STATUS_RESERVED_MASK (0x7FFFFFFC) | ||
112 | |||
113 | #define SMU_ISR_GEN_BIT(name) \ | ||
114 | SCU_GEN_BIT(SMU_INTERRUPT_STATUS_ ## name) | ||
115 | |||
116 | #define SMU_ISR_QUEUE_ERROR SMU_ISR_GEN_BIT(QUEUE_ERROR) | ||
117 | #define SMU_ISR_QUEUE_SUSPEND SMU_ISR_GEN_BIT(QUEUE_SUSPEND) | ||
118 | #define SMU_ISR_COMPLETION SMU_ISR_GEN_BIT(COMPLETION) | ||
119 | |||
120 | /* ***************************************************************************** */ | ||
121 | #define SMU_INTERRUPT_MASK_COMPLETION_SHIFT (31) | ||
122 | #define SMU_INTERRUPT_MASK_COMPLETION_MASK (0x80000000) | ||
123 | #define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_SHIFT (1) | ||
124 | #define SMU_INTERRUPT_MASK_QUEUE_SUSPEND_MASK (0x00000002) | ||
125 | #define SMU_INTERRUPT_MASK_QUEUE_ERROR_SHIFT (0) | ||
126 | #define SMU_INTERRUPT_MASK_QUEUE_ERROR_MASK (0x00000001) | ||
127 | #define SMU_INTERRUPT_MASK_RESERVED_MASK (0x7FFFFFFC) | ||
128 | |||
129 | #define SMU_IMR_GEN_BIT(name) \ | ||
130 | SCU_GEN_BIT(SMU_INTERRUPT_MASK_ ## name) | ||
131 | |||
132 | #define SMU_IMR_QUEUE_ERROR SMU_IMR_GEN_BIT(QUEUE_ERROR) | ||
133 | #define SMU_IMR_QUEUE_SUSPEND SMU_IMR_GEN_BIT(QUEUE_SUSPEND) | ||
134 | #define SMU_IMR_COMPLETION SMU_IMR_GEN_BIT(COMPLETION) | ||
135 | |||
136 | /* ***************************************************************************** */ | ||
137 | #define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_SHIFT (0) | ||
138 | #define SMU_INTERRUPT_COALESCING_CONTROL_TIMER_MASK (0x0000001F) | ||
139 | #define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_SHIFT (8) | ||
140 | #define SMU_INTERRUPT_COALESCING_CONTROL_NUMBER_MASK (0x0000FF00) | ||
141 | #define SMU_INTERRUPT_COALESCING_CONTROL_RESERVED_MASK (0xFFFF00E0) | ||
142 | |||
143 | #define SMU_ICC_GEN_VAL(name, value) \ | ||
144 | SCU_GEN_VALUE(SMU_INTERRUPT_COALESCING_CONTROL_ ## name, value) | ||
145 | |||
146 | /* ***************************************************************************** */ | ||
147 | #define SMU_TASK_CONTEXT_RANGE_START_SHIFT (0) | ||
148 | #define SMU_TASK_CONTEXT_RANGE_START_MASK (0x00000FFF) | ||
149 | #define SMU_TASK_CONTEXT_RANGE_ENDING_SHIFT (16) | ||
150 | #define SMU_TASK_CONTEXT_RANGE_ENDING_MASK (0x0FFF0000) | ||
151 | #define SMU_TASK_CONTEXT_RANGE_ENABLE_SHIFT (31) | ||
152 | #define SMU_TASK_CONTEXT_RANGE_ENABLE_MASK (0x80000000) | ||
153 | #define SMU_TASK_CONTEXT_RANGE_RESERVED_MASK (0x7000F000) | ||
154 | |||
155 | #define SMU_TCR_GEN_VAL(name, value) \ | ||
156 | SCU_GEN_VALUE(SMU_TASK_CONTEXT_RANGE_ ## name, value) | ||
157 | |||
158 | #define SMU_TCR_GEN_BIT(name, value) \ | ||
159 | SCU_GEN_BIT(SMU_TASK_CONTEXT_RANGE_ ## name) | ||
160 | |||
161 | /* ***************************************************************************** */ | ||
162 | |||
163 | #define SMU_COMPLETION_QUEUE_PUT_POINTER_SHIFT (0) | ||
164 | #define SMU_COMPLETION_QUEUE_PUT_POINTER_MASK (0x00003FFF) | ||
165 | #define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_SHIFT (15) | ||
166 | #define SMU_COMPLETION_QUEUE_PUT_CYCLE_BIT_MASK (0x00008000) | ||
167 | #define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_SHIFT (16) | ||
168 | #define SMU_COMPLETION_QUEUE_PUT_EVENT_POINTER_MASK (0x03FF0000) | ||
169 | #define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_SHIFT (26) | ||
170 | #define SMU_COMPLETION_QUEUE_PUT_EVENT_CYCLE_BIT_MASK (0x04000000) | ||
171 | #define SMU_COMPLETION_QUEUE_PUT_RESERVED_MASK (0xF8004000) | ||
172 | |||
173 | #define SMU_CQPR_GEN_VAL(name, value) \ | ||
174 | SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_PUT_ ## name, value) | ||
175 | |||
176 | #define SMU_CQPR_GEN_BIT(name) \ | ||
177 | SCU_GEN_BIT(SMU_COMPLETION_QUEUE_PUT_ ## name) | ||
178 | |||
179 | /* ***************************************************************************** */ | ||
180 | |||
181 | #define SMU_COMPLETION_QUEUE_GET_POINTER_SHIFT (0) | ||
182 | #define SMU_COMPLETION_QUEUE_GET_POINTER_MASK (0x00003FFF) | ||
183 | #define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_SHIFT (15) | ||
184 | #define SMU_COMPLETION_QUEUE_GET_CYCLE_BIT_MASK (0x00008000) | ||
185 | #define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_SHIFT (16) | ||
186 | #define SMU_COMPLETION_QUEUE_GET_EVENT_POINTER_MASK (0x03FF0000) | ||
187 | #define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_SHIFT (26) | ||
188 | #define SMU_COMPLETION_QUEUE_GET_EVENT_CYCLE_BIT_MASK (0x04000000) | ||
189 | #define SMU_COMPLETION_QUEUE_GET_ENABLE_SHIFT (30) | ||
190 | #define SMU_COMPLETION_QUEUE_GET_ENABLE_MASK (0x40000000) | ||
191 | #define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_SHIFT (31) | ||
192 | #define SMU_COMPLETION_QUEUE_GET_EVENT_ENABLE_MASK (0x80000000) | ||
193 | #define SMU_COMPLETION_QUEUE_GET_RESERVED_MASK (0x38004000) | ||
194 | |||
195 | #define SMU_CQGR_GEN_VAL(name, value) \ | ||
196 | SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_GET_ ## name, value) | ||
197 | |||
198 | #define SMU_CQGR_GEN_BIT(name) \ | ||
199 | SCU_GEN_BIT(SMU_COMPLETION_QUEUE_GET_ ## name) | ||
200 | |||
201 | #define SMU_CQGR_CYCLE_BIT \ | ||
202 | SMU_CQGR_GEN_BIT(CYCLE_BIT) | ||
203 | |||
204 | #define SMU_CQGR_EVENT_CYCLE_BIT \ | ||
205 | SMU_CQGR_GEN_BIT(EVENT_CYCLE_BIT) | ||
206 | |||
207 | #define SMU_CQGR_GET_POINTER_SET(value) \ | ||
208 | SMU_CQGR_GEN_VAL(POINTER, value) | ||
209 | |||
210 | |||
211 | /* ***************************************************************************** */ | ||
212 | #define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_SHIFT (0) | ||
213 | #define SMU_COMPLETION_QUEUE_CONTROL_QUEUE_LIMIT_MASK (0x00003FFF) | ||
214 | #define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_SHIFT (16) | ||
215 | #define SMU_COMPLETION_QUEUE_CONTROL_EVENT_LIMIT_MASK (0x03FF0000) | ||
216 | #define SMU_COMPLETION_QUEUE_CONTROL_RESERVED_MASK (0xFC00C000) | ||
217 | |||
218 | #define SMU_CQC_GEN_VAL(name, value) \ | ||
219 | SCU_GEN_VALUE(SMU_COMPLETION_QUEUE_CONTROL_ ## name, value) | ||
220 | |||
221 | #define SMU_CQC_QUEUE_LIMIT_SET(value) \ | ||
222 | SMU_CQC_GEN_VAL(QUEUE_LIMIT, value) | ||
223 | |||
224 | #define SMU_CQC_EVENT_LIMIT_SET(value) \ | ||
225 | SMU_CQC_GEN_VAL(EVENT_LIMIT, value) | ||
226 | |||
227 | |||
228 | /* ***************************************************************************** */ | ||
229 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT (0) | ||
230 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK (0x00000FFF) | ||
231 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT (12) | ||
232 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK (0x00007000) | ||
233 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT (15) | ||
234 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK (0x07FF8000) | ||
235 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_SHIFT (27) | ||
236 | #define SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK (0x08000000) | ||
237 | #define SMU_DEVICE_CONTEXT_CAPACITY_RESERVED_MASK (0xF0000000) | ||
238 | |||
239 | #define SMU_DCC_GEN_VAL(name, value) \ | ||
240 | SCU_GEN_VALUE(SMU_DEVICE_CONTEXT_CAPACITY_ ## name, value) | ||
241 | |||
242 | #define SMU_DCC_GET_MAX_PEG(value) \ | ||
243 | (\ | ||
244 | ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_PEG_MASK) \ | ||
245 | >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ | ||
246 | ) | ||
247 | |||
248 | #define SMU_DCC_GET_MAX_LP(value) \ | ||
249 | (\ | ||
250 | ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_MASK) \ | ||
251 | >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_LP_SHIFT \ | ||
252 | ) | ||
253 | |||
254 | #define SMU_DCC_GET_MAX_TC(value) \ | ||
255 | (\ | ||
256 | ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_MASK) \ | ||
257 | >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_TC_SHIFT \ | ||
258 | ) | ||
259 | |||
260 | #define SMU_DCC_GET_MAX_RNC(value) \ | ||
261 | (\ | ||
262 | ((value) & SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_MASK) \ | ||
263 | >> SMU_DEVICE_CONTEXT_CAPACITY_MAX_RNC_SHIFT \ | ||
264 | ) | ||
265 | |||
266 | /* -------------------------------------------------------------------------- */ | ||
267 | |||
268 | #define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_SHIFT (0) | ||
269 | #define SMU_CONTROL_STATUS_TASK_CONTEXT_RANGE_ENABLE_MASK (0x00000001) | ||
270 | #define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_SHIFT (1) | ||
271 | #define SMU_CONTROL_STATUS_COMPLETION_BYTE_SWAP_ENABLE_MASK (0x00000002) | ||
272 | #define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_SHIFT (16) | ||
273 | #define SMU_CONTROL_STATUS_CONTEXT_RAM_INIT_COMPLETED_MASK (0x00010000) | ||
274 | #define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_SHIFT (17) | ||
275 | #define SMU_CONTROL_STATUS_SCHEDULER_RAM_INIT_COMPLETED_MASK (0x00020000) | ||
276 | #define SMU_CONTROL_STATUS_RESERVED_MASK (0xFFFCFFFC) | ||
277 | |||
278 | #define SMU_SMUCSR_GEN_BIT(name) \ | ||
279 | SCU_GEN_BIT(SMU_CONTROL_STATUS_ ## name) | ||
280 | |||
281 | #define SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ | ||
282 | (SMU_SMUCSR_GEN_BIT(SCHEDULER_RAM_INIT_COMPLETED)) | ||
283 | |||
284 | #define SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ | ||
285 | (SMU_SMUCSR_GEN_BIT(CONTEXT_RAM_INIT_COMPLETED)) | ||
286 | |||
287 | #define SCU_RAM_INIT_COMPLETED \ | ||
288 | (\ | ||
289 | SMU_SMUCSR_CONTEXT_RAM_INIT_COMPLETED \ | ||
290 | | SMU_SMUCSR_SCHEDULER_RAM_INIT_COMPLETED \ | ||
291 | ) | ||
292 | |||
293 | /* -------------------------------------------------------------------------- */ | ||
294 | |||
295 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_SHIFT (0) | ||
296 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE0_MASK (0x00000001) | ||
297 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_SHIFT (1) | ||
298 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE1_MASK (0x00000002) | ||
299 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_SHIFT (2) | ||
300 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE2_MASK (0x00000004) | ||
301 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_SHIFT (3) | ||
302 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_PE3_MASK (0x00000008) | ||
303 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_SHIFT (8) | ||
304 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE0_MASK (0x00000100) | ||
305 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_SHIFT (9) | ||
306 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE1_MASK (0x00000200) | ||
307 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_SHIFT (10) | ||
308 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE2_MASK (0x00000400) | ||
309 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_SHIFT (11) | ||
310 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_PE3_MASK (0x00000800) | ||
311 | |||
312 | #define SMU_RESET_PROTOCOL_ENGINE(peg, pe) \ | ||
313 | ((1 << (pe)) << ((peg) * 8)) | ||
314 | |||
315 | #define SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ | ||
316 | (\ | ||
317 | SMU_RESET_PROTOCOL_ENGINE(peg, 0) \ | ||
318 | | SMU_RESET_PROTOCOL_ENGINE(peg, 1) \ | ||
319 | | SMU_RESET_PROTOCOL_ENGINE(peg, 2) \ | ||
320 | | SMU_RESET_PROTOCOL_ENGINE(peg, 3) \ | ||
321 | ) | ||
322 | |||
323 | #define SMU_RESET_ALL_PROTOCOL_ENGINES() \ | ||
324 | (\ | ||
325 | SMU_RESET_PEG_PROTOCOL_ENGINES(0) \ | ||
326 | | SMU_RESET_PEG_PROTOCOL_ENGINES(1) \ | ||
327 | ) | ||
328 | |||
329 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_SHIFT (16) | ||
330 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP0_MASK (0x00010000) | ||
331 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_SHIFT (17) | ||
332 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG0_LP2_MASK (0x00020000) | ||
333 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_SHIFT (18) | ||
334 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP0_MASK (0x00040000) | ||
335 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_SHIFT (19) | ||
336 | #define SMU_SOFTRESET_CONTROL_RESET_WIDE_PORT_PEG1_LP2_MASK (0x00080000) | ||
337 | |||
338 | #define SMU_RESET_WIDE_PORT_QUEUE(peg, wide_port) \ | ||
339 | ((1 << ((wide_port) / 2)) << ((peg) * 2) << 16) | ||
340 | |||
341 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_SHIFT (20) | ||
342 | #define SMU_SOFTRESET_CONTROL_RESET_PEG0_MASK (0x00100000) | ||
343 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_SHIFT (21) | ||
344 | #define SMU_SOFTRESET_CONTROL_RESET_PEG1_MASK (0x00200000) | ||
345 | #define SMU_SOFTRESET_CONTROL_RESET_SCU_SHIFT (22) | ||
346 | #define SMU_SOFTRESET_CONTROL_RESET_SCU_MASK (0x00400000) | ||
347 | |||
348 | /* | ||
349 | * It seems to make sense that if you are going to reset the protocol | ||
350 | * engine group that you would also reset all of the protocol engines */ | ||
351 | #define SMU_RESET_PROTOCOL_ENGINE_GROUP(peg) \ | ||
352 | (\ | ||
353 | (1 << ((peg) + 20)) \ | ||
354 | | SMU_RESET_WIDE_PORT_QUEUE(peg, 0) \ | ||
355 | | SMU_RESET_WIDE_PORT_QUEUE(peg, 1) \ | ||
356 | | SMU_RESET_PEG_PROTOCOL_ENGINES(peg) \ | ||
357 | ) | ||
358 | |||
359 | #define SMU_RESET_ALL_PROTOCOL_ENGINE_GROUPS() \ | ||
360 | (\ | ||
361 | SMU_RESET_PROTOCOL_ENGINE_GROUP(0) \ | ||
362 | | SMU_RESET_PROTOCOL_ENGINE_GROUP(1) \ | ||
363 | ) | ||
364 | |||
365 | #define SMU_RESET_SCU() (0xFFFFFFFF) | ||
366 | |||
367 | |||
368 | |||
369 | /* ***************************************************************************** */ | ||
370 | #define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_SHIFT (0) | ||
371 | #define SMU_TASK_CONTEXT_ASSIGNMENT_STARTING_MASK (0x00000FFF) | ||
372 | #define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_SHIFT (16) | ||
373 | #define SMU_TASK_CONTEXT_ASSIGNMENT_ENDING_MASK (0x0FFF0000) | ||
374 | #define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_SHIFT (31) | ||
375 | #define SMU_TASK_CONTEXT_ASSIGNMENT_RANGE_CHECK_ENABLE_MASK (0x80000000) | ||
376 | #define SMU_TASK_CONTEXT_ASSIGNMENT_RESERVED_MASK (0x7000F000) | ||
377 | |||
378 | #define SMU_TCA_GEN_VAL(name, value) \ | ||
379 | SCU_GEN_VALUE(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name, value) | ||
380 | |||
381 | #define SMU_TCA_GEN_BIT(name) \ | ||
382 | SCU_GEN_BIT(SMU_TASK_CONTEXT_ASSIGNMENT_ ## name) | ||
383 | |||
384 | /* ***************************************************************************** */ | ||
385 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_SHIFT (0) | ||
386 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_QUEUE_SIZE_MASK (0x00000FFF) | ||
387 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_RESERVED_MASK (0xFFFFF000) | ||
388 | |||
389 | #define SCU_UFQC_GEN_VAL(name, value) \ | ||
390 | SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_CONTROL_ ## name, value) | ||
391 | |||
392 | #define SCU_UFQC_QUEUE_SIZE_SET(value) \ | ||
393 | SCU_UFQC_GEN_VAL(QUEUE_SIZE, value) | ||
394 | |||
395 | /* ***************************************************************************** */ | ||
396 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_SHIFT (0) | ||
397 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_POINTER_MASK (0x00000FFF) | ||
398 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_SHIFT (12) | ||
399 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_CYCLE_BIT_MASK (0x00001000) | ||
400 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_RESERVED_MASK (0xFFFFE000) | ||
401 | |||
402 | #define SCU_UFQPP_GEN_VAL(name, value) \ | ||
403 | SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name, value) | ||
404 | |||
405 | #define SCU_UFQPP_GEN_BIT(name) \ | ||
406 | SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_PUT_ ## name) | ||
407 | |||
408 | /* | ||
409 | * ***************************************************************************** | ||
410 | * * SDMA Registers | ||
411 | * ***************************************************************************** */ | ||
412 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_SHIFT (0) | ||
413 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_POINTER_MASK (0x00000FFF) | ||
414 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_SHIFT (12) | ||
415 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_CYCLE_BIT_MASK (12) | ||
416 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_SHIFT (31) | ||
417 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ENABLE_BIT_MASK (0x80000000) | ||
418 | #define SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_RESERVED_MASK (0x7FFFE000) | ||
419 | |||
420 | #define SCU_UFQGP_GEN_VAL(name, value) \ | ||
421 | SCU_GEN_VALUE(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name, value) | ||
422 | |||
423 | #define SCU_UFQGP_GEN_BIT(name) \ | ||
424 | SCU_GEN_BIT(SCU_SDMA_UNSOLICITED_FRAME_QUEUE_GET_ ## name) | ||
425 | |||
426 | #define SCU_UFQGP_CYCLE_BIT(value) \ | ||
427 | SCU_UFQGP_GEN_BIT(CYCLE_BIT, value) | ||
428 | |||
429 | #define SCU_UFQGP_GET_POINTER(value) \ | ||
430 | SCU_UFQGP_GEN_VALUE(POINTER, value) | ||
431 | |||
432 | #define SCU_UFQGP_ENABLE(value) \ | ||
433 | (SCU_UFQGP_GEN_BIT(ENABLE) | value) | ||
434 | |||
435 | #define SCU_UFQGP_DISABLE(value) \ | ||
436 | (~SCU_UFQGP_GEN_BIT(ENABLE) & value) | ||
437 | |||
438 | #define SCU_UFQGP_VALUE(bit, value) \ | ||
439 | (SCU_UFQGP_CYCLE_BIT(bit) | SCU_UFQGP_GET_POINTER(value)) | ||
440 | |||
441 | /* ***************************************************************************** */ | ||
442 | #define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SHIFT (0) | ||
443 | #define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_MASK (0x0000FFFF) | ||
444 | #define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (16) | ||
445 | #define SCU_PDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00010000) | ||
446 | #define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_SHIFT (17) | ||
447 | #define SCU_PDMA_CONFIGURATION_PCI_NO_SNOOP_ENABLE_MASK (0x00020000) | ||
448 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_SHIFT (18) | ||
449 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_BYTE_SWAP_MASK (0x00040000) | ||
450 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_SHIFT (19) | ||
451 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_SGL_FETCH_MASK (0x00080000) | ||
452 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_SHIFT (20) | ||
453 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_RX_HEADER_RAM_WRITE_MASK (0x00100000) | ||
454 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_SHIFT (21) | ||
455 | #define SCU_PDMA_CONFIGURATION_BIG_ENDIAN_CONTROL_XPI_UF_ADDRESS_FETCH_MASK (0x00200000) | ||
456 | #define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_SHIFT (22) | ||
457 | #define SCU_PDMA_CONFIGURATION_ADDRESS_MODIFIER_SELECT_MASK (0x00400000) | ||
458 | #define SCU_PDMA_CONFIGURATION_RESERVED_MASK (0xFF800000) | ||
459 | |||
460 | #define SCU_PDMACR_GEN_VALUE(name, value) \ | ||
461 | SCU_GEN_VALUE(SCU_PDMA_CONFIGURATION_ ## name, value) | ||
462 | |||
463 | #define SCU_PDMACR_GEN_BIT(name) \ | ||
464 | SCU_GEN_BIT(SCU_PDMA_CONFIGURATION_ ## name) | ||
465 | |||
466 | #define SCU_PDMACR_BE_GEN_BIT(name) \ | ||
467 | SCU_PCMACR_GEN_BIT(BIG_ENDIAN_CONTROL_ ## name) | ||
468 | |||
469 | /* ***************************************************************************** */ | ||
470 | #define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_SHIFT (8) | ||
471 | #define SCU_CDMA_CONFIGURATION_PCI_RELAXED_ORDERING_ENABLE_MASK (0x00000100) | ||
472 | |||
473 | #define SCU_CDMACR_GEN_BIT(name) \ | ||
474 | SCU_GEN_BIT(SCU_CDMA_CONFIGURATION_ ## name) | ||
475 | |||
476 | /* | ||
477 | * ***************************************************************************** | ||
478 | * * SCU Link Layer Registers | ||
479 | * ***************************************************************************** */ | ||
480 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_SHIFT (0) | ||
481 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_TIMEOUT_MASK (0x000000FF) | ||
482 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_SHIFT (8) | ||
483 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_LOCK_TIME_MASK (0x0000FF00) | ||
484 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_SHIFT (16) | ||
485 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_RATE_CHANGE_DELAY_MASK (0x00FF0000) | ||
486 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_SHIFT (24) | ||
487 | #define SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_DWORD_SYNC_TIMEOUT_MASK (0xFF000000) | ||
488 | #define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_REQUIRED_MASK (0x00000000) | ||
489 | #define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_DEFAULT_MASK (0x7D00676F) | ||
490 | #define SCU_LINK_LAYER_SPEED_NECGOIATION_TIMER_VALUES_RESERVED_MASK (0x00FF0000) | ||
491 | |||
492 | #define SCU_SAS_SPDTOV_GEN_VALUE(name, value) \ | ||
493 | SCU_GEN_VALUE(SCU_LINK_LAYER_SPEED_NEGOTIATION_TIMER_VALUES_ ## name, value) | ||
494 | |||
495 | |||
496 | #define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_SHIFT (2) | ||
497 | #define SCU_LINK_STATUS_DWORD_SYNC_AQUIRED_MASK (0x00000004) | ||
498 | #define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_SHIFT (4) | ||
499 | #define SCU_LINK_STATUS_TRANSMIT_PORT_SELECTION_DONE_MASK (0x00000010) | ||
500 | #define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_SHIFT (5) | ||
501 | #define SCU_LINK_STATUS_RECEIVER_CREDIT_EXHAUSTED_MASK (0x00000020) | ||
502 | #define SCU_LINK_STATUS_RESERVED_MASK (0xFFFFFFCD) | ||
503 | |||
504 | #define SCU_SAS_LLSTA_GEN_BIT(name) \ | ||
505 | SCU_GEN_BIT(SCU_LINK_STATUS_ ## name) | ||
506 | |||
507 | |||
508 | /* TODO: Where is the SATA_PSELTOV register? */ | ||
509 | |||
510 | /* | ||
511 | * ***************************************************************************** | ||
512 | * * SCU SAS Maximum Arbitration Wait Time Timeout Register | ||
513 | * ***************************************************************************** */ | ||
514 | #define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_SHIFT (0) | ||
515 | #define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_VALUE_MASK (0x00007FFF) | ||
516 | #define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_SHIFT (15) | ||
517 | #define SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_SCALE_MASK (0x00008000) | ||
518 | |||
519 | #define SCU_SAS_MAWTTOV_GEN_VALUE(name, value) \ | ||
520 | SCU_GEN_VALUE(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name, value) | ||
521 | |||
522 | #define SCU_SAS_MAWTTOV_GEN_BIT(name) \ | ||
523 | SCU_GEN_BIT(SCU_SAS_MAX_ARBITRATION_WAIT_TIME_TIMEOUT_ ## name) | ||
524 | |||
525 | |||
526 | /* | ||
527 | * TODO: Where is the SAS_LNKTOV regsiter? | ||
528 | * TODO: Where is the SAS_PHYTOV register? */ | ||
529 | |||
530 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_SHIFT (1) | ||
531 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_MASK (0x00000002) | ||
532 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_SHIFT (2) | ||
533 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_TARGET_MASK (0x00000004) | ||
534 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_SHIFT (3) | ||
535 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_TARGET_MASK (0x00000008) | ||
536 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_SHIFT (8) | ||
537 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_DA_SATA_HOST_MASK (0x00000100) | ||
538 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_SHIFT (9) | ||
539 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_INITIATOR_MASK (0x00000200) | ||
540 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_SHIFT (10) | ||
541 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_STP_INITIATOR_MASK (0x00000400) | ||
542 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_SHIFT (11) | ||
543 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_SSP_INITIATOR_MASK (0x00000800) | ||
544 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_SHIFT (16) | ||
545 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_REASON_CODE_MASK (0x000F0000) | ||
546 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_SHIFT (24) | ||
547 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_ADDRESS_FRAME_TYPE_MASK (0x0F000000) | ||
548 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_SHIFT (28) | ||
549 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_DEVICE_TYPE_MASK (0x70000000) | ||
550 | #define SCU_SAS_TRANSMIT_IDENTIFICATION_RESERVED_MASK (0x80F0F1F1) | ||
551 | |||
552 | #define SCU_SAS_TIID_GEN_VAL(name, value) \ | ||
553 | SCU_GEN_VALUE(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name, value) | ||
554 | |||
555 | #define SCU_SAS_TIID_GEN_BIT(name) \ | ||
556 | SCU_GEN_BIT(SCU_SAS_TRANSMIT_IDENTIFICATION_ ## name) | ||
557 | |||
558 | /* SAS Identify Frame PHY Identifier Register */ | ||
559 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_SHIFT (16) | ||
560 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_BREAK_REPLY_CAPABLE_MASK (0x00010000) | ||
561 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_SHIFT (17) | ||
562 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_REQUESTED_INSIDE_ZPSDS_MASK (0x00020000) | ||
563 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_SHIFT (18) | ||
564 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_INSIDE_ZPSDS_PERSISTENT_MASK (0x00040000) | ||
565 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_SHIFT (24) | ||
566 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ID_MASK (0xFF000000) | ||
567 | #define SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_RESERVED_MASK (0x00F800FF) | ||
568 | |||
569 | #define SCU_SAS_TIPID_GEN_VALUE(name, value) \ | ||
570 | SCU_GEN_VALUE(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name, value) | ||
571 | |||
572 | #define SCU_SAS_TIPID_GEN_BIT(name) \ | ||
573 | SCU_GEN_BIT(SCU_LINK_LAYER_IDENTIFY_FRAME_PHY_IDENTIFIER_ ## name) | ||
574 | |||
575 | |||
576 | #define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_SHIFT (4) | ||
577 | #define SCU_SAS_PHY_CONFIGURATION_TX_PARITY_CHECK_MASK (0x00000010) | ||
578 | #define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_SHIFT (6) | ||
579 | #define SCU_SAS_PHY_CONFIGURATION_TX_BAD_CRC_MASK (0x00000040) | ||
580 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_SHIFT (7) | ||
581 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_SCRAMBLER_MASK (0x00000080) | ||
582 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_SHIFT (8) | ||
583 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_DESCRAMBLER_MASK (0x00000100) | ||
584 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_SHIFT (9) | ||
585 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_CREDIT_INSERTION_MASK (0x00000200) | ||
586 | #define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_SHIFT (11) | ||
587 | #define SCU_SAS_PHY_CONFIGURATION_SUSPEND_PROTOCOL_ENGINE_MASK (0x00000800) | ||
588 | #define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_SHIFT (12) | ||
589 | #define SCU_SAS_PHY_CONFIGURATION_SATA_SPINUP_HOLD_MASK (0x00001000) | ||
590 | #define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_SHIFT (13) | ||
591 | #define SCU_SAS_PHY_CONFIGURATION_TRANSMIT_PORT_SELECTION_SIGNAL_MASK (0x00002000) | ||
592 | #define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_SHIFT (14) | ||
593 | #define SCU_SAS_PHY_CONFIGURATION_HARD_RESET_MASK (0x00004000) | ||
594 | #define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_SHIFT (15) | ||
595 | #define SCU_SAS_PHY_CONFIGURATION_OOB_ENABLE_MASK (0x00008000) | ||
596 | #define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_SHIFT (23) | ||
597 | #define SCU_SAS_PHY_CONFIGURATION_ENABLE_FRAME_TX_INSERT_ALIGN_MASK (0x00800000) | ||
598 | #define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_SHIFT (27) | ||
599 | #define SCU_SAS_PHY_CONFIGURATION_FORWARD_IDENTIFY_FRAME_MASK (0x08000000) | ||
600 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_SHIFT (28) | ||
601 | #define SCU_SAS_PHY_CONFIGURATION_DISABLE_BYTE_TRANSPOSE_STP_FRAME_MASK (0x10000000) | ||
602 | #define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_SHIFT (29) | ||
603 | #define SCU_SAS_PHY_CONFIGURATION_OOB_RESET_MASK (0x20000000) | ||
604 | #define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_SHIFT (30) | ||
605 | #define SCU_SAS_PHY_CONFIGURATION_THREE_IAF_ENABLE_MASK (0x40000000) | ||
606 | #define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_SHIFT (31) | ||
607 | #define SCU_SAS_PHY_CONFIGURATION_OOB_ALIGN0_ENABLE_MASK (0x80000000) | ||
608 | #define SCU_SAS_PHY_CONFIGURATION_REQUIRED_MASK (0x0100000F) | ||
609 | #define SCU_SAS_PHY_CONFIGURATION_DEFAULT_MASK (0x4180100F) | ||
610 | #define SCU_SAS_PHY_CONFIGURATION_RESERVED_MASK (0x00000000) | ||
611 | |||
612 | #define SCU_SAS_PCFG_GEN_BIT(name) \ | ||
613 | SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_ ## name) | ||
614 | |||
615 | |||
616 | #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT (0) | ||
617 | #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK (0x0003FFFF) | ||
618 | #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_SHIFT (31) | ||
619 | #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ENABLE_MASK (0x80000000) | ||
620 | #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_RESERVED_MASK (0x7FFC0000) | ||
621 | |||
622 | #define SCU_ENSPINUP_GEN_VAL(name, value) \ | ||
623 | SCU_GEN_VALUE(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name, value) | ||
624 | |||
625 | #define SCU_ENSPINUP_GEN_BIT(name) \ | ||
626 | SCU_GEN_BIT(SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_ ## name) | ||
627 | |||
628 | |||
629 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_SHIFT (1) | ||
630 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_TXSSCTYPE_MASK (0x00000002) | ||
631 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_SHIFT (4) | ||
632 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_RLLRATE_MASK (0x000000F0) | ||
633 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_SHIFT (8) | ||
634 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO15GBPS_MASK (0x00000100) | ||
635 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_SHIFT (9) | ||
636 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SW15GBPS_MASK (0x00000201) | ||
637 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_SHIFT (10) | ||
638 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO30GBPS_MASK (0x00000401) | ||
639 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_SHIFT (11) | ||
640 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SW30GBPS_MASK (0x00000801) | ||
641 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_SHIFT (12) | ||
642 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SWO60GBPS_MASK (0x00001001) | ||
643 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_SHIFT (13) | ||
644 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_SW60GBPS_MASK (0x00002001) | ||
645 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_SHIFT (31) | ||
646 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_EVEN_PARITY_MASK (0x80000000) | ||
647 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_DEFAULT_MASK (0x00003F01) | ||
648 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_REQUIRED_MASK (0x00000001) | ||
649 | #define SCU_LINK_LAYER_PHY_CAPABILITIES_RESERVED_MASK (0x7FFFC00D) | ||
650 | |||
651 | #define SCU_SAS_PHYCAP_GEN_VAL(name, value) \ | ||
652 | SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name, value) | ||
653 | |||
654 | #define SCU_SAS_PHYCAP_GEN_BIT(name) \ | ||
655 | SCU_GEN_BIT(SCU_LINK_LAYER_PHY_CAPABILITIES_ ## name) | ||
656 | |||
657 | |||
658 | #define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_SHIFT (0) | ||
659 | #define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_VIRTUAL_EXPANDER_PHY_ZONE_GROUP_MASK (0x000000FF) | ||
660 | #define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_SHIFT (31) | ||
661 | #define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_INSIDE_SOURCE_ZONE_GROUP_MASK (0x80000000) | ||
662 | #define SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_RESERVED_MASK (0x7FFFFF00) | ||
663 | |||
664 | #define SCU_PSZGCR_GEN_VAL(name, value) \ | ||
665 | SCU_GEN_VALUE(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name, value) | ||
666 | |||
667 | #define SCU_PSZGCR_GEN_BIT(name) \ | ||
668 | SCU_GEN_BIT(SCU_LINK_LAYER_PHY_SOURCE_ZONE_GROUP_CONTROL_ ## name) | ||
669 | |||
670 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_SHIFT (1) | ||
671 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_LOCKED_MASK (0x00000002) | ||
672 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_SHIFT (2) | ||
673 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE0_UPDATING_MASK (0x00000004) | ||
674 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_SHIFT (4) | ||
675 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_LOCKED_MASK (0x00000010) | ||
676 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_SHIFT (5) | ||
677 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZONE1_UPDATING_MASK (0x00000020) | ||
678 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_SHIFT (16) | ||
679 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE0_MASK (0x00030000) | ||
680 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_SHIFT (19) | ||
681 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE0_MASK (0x00080000) | ||
682 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_SHIFT (20) | ||
683 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE1_MASK (0x00300000) | ||
684 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_SHIFT (23) | ||
685 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE1_MASK (0x00800000) | ||
686 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_SHIFT (24) | ||
687 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE2_MASK (0x03000000) | ||
688 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_SHIFT (27) | ||
689 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE2_MASK (0x08000000) | ||
690 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_SHIFT (28) | ||
691 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ZPT_ASSOCIATION_PE3_MASK (0x30000000) | ||
692 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_SHIFT (31) | ||
693 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_AIP_ENABLE_PE3_MASK (0x80000000) | ||
694 | #define SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_RESERVED_MASK (0x4444FFC9) | ||
695 | |||
696 | #define SCU_PEG_SCUVZECR_GEN_VAL(name, val) \ | ||
697 | SCU_GEN_VALUE(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name, val) | ||
698 | |||
699 | #define SCU_PEG_SCUVZECR_GEN_BIT(name) \ | ||
700 | SCU_GEN_BIT(SCU_PROTOCOL_ENGINE_GROUP_VIRTUAL_ZONING_EXPANDER_CONTROL_ ## name) | ||
701 | |||
702 | |||
703 | /* | ||
704 | * ***************************************************************************** | ||
705 | * * Port Task Scheduler registers shift and mask values | ||
706 | * ***************************************************************************** */ | ||
707 | #define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_SHIFT (0) | ||
708 | #define SCU_PTSG_CONTROL_IT_NEXUS_TIMEOUT_MASK (0x0000FFFF) | ||
709 | #define SCU_PTSG_CONTROL_TASK_TIMEOUT_SHIFT (16) | ||
710 | #define SCU_PTSG_CONTROL_TASK_TIMEOUT_MASK (0x00FF0000) | ||
711 | #define SCU_PTSG_CONTROL_PTSG_ENABLE_SHIFT (24) | ||
712 | #define SCU_PTSG_CONTROL_PTSG_ENABLE_MASK (0x01000000) | ||
713 | #define SCU_PTSG_CONTROL_ETM_ENABLE_SHIFT (25) | ||
714 | #define SCU_PTSG_CONTROL_ETM_ENABLE_MASK (0x02000000) | ||
715 | #define SCU_PTSG_CONTROL_DEFAULT_MASK (0x00020002) | ||
716 | #define SCU_PTSG_CONTROL_REQUIRED_MASK (0x00000000) | ||
717 | #define SCU_PTSG_CONTROL_RESERVED_MASK (0xFC000000) | ||
718 | |||
719 | #define SCU_PTSGCR_GEN_VAL(name, val) \ | ||
720 | SCU_GEN_VALUE(SCU_PTSG_CONTROL_ ## name, val) | ||
721 | |||
722 | #define SCU_PTSGCR_GEN_BIT(name) \ | ||
723 | SCU_GEN_BIT(SCU_PTSG_CONTROL_ ## name) | ||
724 | |||
725 | |||
726 | /* ***************************************************************************** */ | ||
727 | #define SCU_PTSG_REAL_TIME_CLOCK_SHIFT (0) | ||
728 | #define SCU_PTSG_REAL_TIME_CLOCK_MASK (0x0000FFFF) | ||
729 | #define SCU_PTSG_REAL_TIME_CLOCK_RESERVED_MASK (0xFFFF0000) | ||
730 | |||
731 | #define SCU_RTCR_GEN_VAL(name, val) \ | ||
732 | SCU_GEN_VALUE(SCU_PTSG_ ## name, val) | ||
733 | |||
734 | |||
735 | #define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_SHIFT (0) | ||
736 | #define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_PRESCALER_VALUE_MASK (0x00FFFFFF) | ||
737 | #define SCU_PTSG_REAL_TIME_CLOCK_CONTROL_RESERVED_MASK (0xFF000000) | ||
738 | |||
739 | #define SCU_RTCCR_GEN_VAL(name, val) \ | ||
740 | SCU_GEN_VALUE(SCU_PTSG_REAL_TIME_CLOCK_CONTROL_ ## name, val) | ||
741 | |||
742 | |||
743 | #define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_SHIFT (0) | ||
744 | #define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_SUSPEND_MASK (0x00000001) | ||
745 | #define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_SHIFT (1) | ||
746 | #define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ENABLE_MASK (0x00000002) | ||
747 | #define SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_RESERVED_MASK (0xFFFFFFFC) | ||
748 | |||
749 | #define SCU_PTSxCR_GEN_BIT(name) \ | ||
750 | SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_CONTROL_ ## name) | ||
751 | |||
752 | |||
753 | #define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_SHIFT (0) | ||
754 | #define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_NEXT_RN_VALID_MASK (0x00000001) | ||
755 | #define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_SHIFT (1) | ||
756 | #define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ACTIVE_RNSC_LIST_VALID_MASK (0x00000002) | ||
757 | #define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_SHIFT (2) | ||
758 | #define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_PTS_SUSPENDED_MASK (0x00000004) | ||
759 | #define SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_RESERVED_MASK (0xFFFFFFF8) | ||
760 | |||
761 | #define SCU_PTSxSR_GEN_BIT(name) \ | ||
762 | SCU_GEN_BIT(SCU_PTSG_PORT_TASK_SCHEDULER_STATUS_ ## name) | ||
763 | |||
764 | |||
765 | /* | ||
766 | * ***************************************************************************** | ||
767 | * * SGPIO Register shift and mask values | ||
768 | * ***************************************************************************** */ | ||
769 | #define SCU_SGPIO_CONTROL_SGPIO_ENABLE_SHIFT (0) | ||
770 | #define SCU_SGPIO_CONTROL_SGPIO_ENABLE_MASK (0x00000001) | ||
771 | #define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_SHIFT (1) | ||
772 | #define SCU_SGPIO_CONTROL_SGPIO_SERIAL_CLOCK_SELECT_MASK (0x00000002) | ||
773 | #define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_SHIFT (2) | ||
774 | #define SCU_SGPIO_CONTROL_SGPIO_SERIAL_SHIFT_WIDTH_SELECT_MASK (0x00000004) | ||
775 | #define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_SHIFT (15) | ||
776 | #define SCU_SGPIO_CONTROL_SGPIO_TEST_BIT_MASK (0x00008000) | ||
777 | #define SCU_SGPIO_CONTROL_SGPIO_RESERVED_MASK (0xFFFF7FF8) | ||
778 | |||
779 | #define SCU_SGICRx_GEN_BIT(name) \ | ||
780 | SCU_GEN_BIT(SCU_SGPIO_CONTROL_SGPIO_ ## name) | ||
781 | |||
782 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_SHIFT (0) | ||
783 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R0_MASK (0x0000000F) | ||
784 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_SHIFT (4) | ||
785 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R1_MASK (0x000000F0) | ||
786 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_SHIFT (8) | ||
787 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R2_MASK (0x00000F00) | ||
788 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_SHIFT (12) | ||
789 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_R3_MASK (0x0000F000) | ||
790 | #define SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_RESERVED_MASK (0xFFFF0000) | ||
791 | |||
792 | #define SCU_SGPBRx_GEN_VAL(name, value) \ | ||
793 | SCU_GEN_VALUE(SCU_SGPIO_PROGRAMMABLE_BLINK_REGISTER_ ## name, value) | ||
794 | |||
795 | #define SCU_SGPIO_START_DRIVE_LOWER_R0_SHIFT (0) | ||
796 | #define SCU_SGPIO_START_DRIVE_LOWER_R0_MASK (0x00000003) | ||
797 | #define SCU_SGPIO_START_DRIVE_LOWER_R1_SHIFT (4) | ||
798 | #define SCU_SGPIO_START_DRIVE_LOWER_R1_MASK (0x00000030) | ||
799 | #define SCU_SGPIO_START_DRIVE_LOWER_R2_SHIFT (8) | ||
800 | #define SCU_SGPIO_START_DRIVE_LOWER_R2_MASK (0x00000300) | ||
801 | #define SCU_SGPIO_START_DRIVE_LOWER_R3_SHIFT (12) | ||
802 | #define SCU_SGPIO_START_DRIVE_LOWER_R3_MASK (0x00003000) | ||
803 | #define SCU_SGPIO_START_DRIVE_LOWER_RESERVED_MASK (0xFFFF8888) | ||
804 | |||
805 | #define SCU_SGSDLRx_GEN_VAL(name, value) \ | ||
806 | SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) | ||
807 | |||
808 | #define SCU_SGPIO_START_DRIVE_UPPER_R0_SHIFT (0) | ||
809 | #define SCU_SGPIO_START_DRIVE_UPPER_R0_MASK (0x00000003) | ||
810 | #define SCU_SGPIO_START_DRIVE_UPPER_R1_SHIFT (4) | ||
811 | #define SCU_SGPIO_START_DRIVE_UPPER_R1_MASK (0x00000030) | ||
812 | #define SCU_SGPIO_START_DRIVE_UPPER_R2_SHIFT (8) | ||
813 | #define SCU_SGPIO_START_DRIVE_UPPER_R2_MASK (0x00000300) | ||
814 | #define SCU_SGPIO_START_DRIVE_UPPER_R3_SHIFT (12) | ||
815 | #define SCU_SGPIO_START_DRIVE_UPPER_R3_MASK (0x00003000) | ||
816 | #define SCU_SGPIO_START_DRIVE_UPPER_RESERVED_MASK (0xFFFF8888) | ||
817 | |||
818 | #define SCU_SGSDURx_GEN_VAL(name, value) \ | ||
819 | SCU_GEN_VALUE(SCU_SGPIO_START_DRIVE_LOWER_ ## name, value) | ||
820 | |||
821 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_SHIFT (0) | ||
822 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D0_MASK (0x00000003) | ||
823 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_SHIFT (4) | ||
824 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D1_MASK (0x00000030) | ||
825 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_SHIFT (8) | ||
826 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D2_MASK (0x00000300) | ||
827 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_SHIFT (12) | ||
828 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_D3_MASK (0x00003000) | ||
829 | #define SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_RESERVED_MASK (0xFFFF8888) | ||
830 | |||
831 | #define SCU_SGSIDLRx_GEN_VAL(name, value) \ | ||
832 | SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) | ||
833 | |||
834 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_SHIFT (0) | ||
835 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D0_MASK (0x00000003) | ||
836 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_SHIFT (4) | ||
837 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D1_MASK (0x00000030) | ||
838 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_SHIFT (8) | ||
839 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D2_MASK (0x00000300) | ||
840 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_SHIFT (12) | ||
841 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_D3_MASK (0x00003000) | ||
842 | #define SCU_SGPIO_SERIAL_INPUT_DATA_UPPER_RESERVED_MASK (0xFFFF8888) | ||
843 | |||
844 | #define SCU_SGSIDURx_GEN_VAL(name, value) \ | ||
845 | SCU_GEN_VALUE(SCU_SGPIO_SERIAL_INPUT_DATA_LOWER_ ## name, value) | ||
846 | |||
847 | #define SCU_SGPIO_VENDOR_SPECIFIC_CODE_SHIFT (0) | ||
848 | #define SCU_SGPIO_VENDOR_SPECIFIC_CODE_MASK (0x0000000F) | ||
849 | #define SCU_SGPIO_VENDOR_SPECIFIC_CODE_RESERVED_MASK (0xFFFFFFF0) | ||
850 | |||
851 | #define SCU_SGVSCR_GEN_VAL(value) \ | ||
852 | SCU_GEN_VALUE(SCU_SGPIO_VENDOR_SPECIFIC_CODE ## name, value) | ||
853 | |||
854 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_SHIFT (0) | ||
855 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA0_MASK (0x00000003) | ||
856 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_SHIFT (2) | ||
857 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA0_MASK (0x00000004) | ||
858 | #define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_SHIFT (3) | ||
859 | #define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA0_MASK (0x00000008) | ||
860 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_SHIFT (4) | ||
861 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA1_MASK (0x00000030) | ||
862 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_SHIFT (6) | ||
863 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA1_MASK (0x00000040) | ||
864 | #define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_SHIFT (7) | ||
865 | #define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA1_MASK (0x00000080) | ||
866 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_SHIFT (8) | ||
867 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INPUT_DATA2_MASK (0x00000300) | ||
868 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_SHIFT (10) | ||
869 | #define SCU_SGPIO_OUPUT_DATA_SELECT_INVERT_INPUT_DATA2_MASK (0x00000400) | ||
870 | #define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_SHIFT (11) | ||
871 | #define SCU_SGPIO_OUPUT_DATA_SELECT_JOG_ENABLE_DATA2_MASK (0x00000800) | ||
872 | #define SCU_SGPIO_OUPUT_DATA_SELECT_RESERVED_MASK (0xFFFFF000) | ||
873 | |||
874 | #define SCU_SGODSR_GEN_VAL(name, value) \ | ||
875 | SCU_GEN_VALUE(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name, value) | ||
876 | |||
877 | #define SCU_SGODSR_GEN_BIT(name) \ | ||
878 | SCU_GEN_BIT(SCU_SGPIO_OUPUT_DATA_SELECT_ ## name) | ||
879 | |||
880 | /* | ||
881 | * ***************************************************************************** | ||
882 | * * SMU Registers | ||
883 | * ***************************************************************************** */ | ||
884 | |||
885 | /* | ||
886 | * ---------------------------------------------------------------------------- | ||
887 | * SMU Registers | ||
888 | * These registers are based off of BAR0 | ||
889 | * | ||
890 | * To calculate the offset for other functions use | ||
891 | * BAR0 + FN# * SystemPageSize * 2 | ||
892 | * | ||
893 | * The TCA is only accessable from FN#0 (Physical Function) and each | ||
894 | * is programmed by (BAR0 + SCU_SMU_TCA_OFFSET + (FN# * 0x04)) or | ||
895 | * TCA0 for FN#0 is at BAR0 + 0x0400 | ||
896 | * TCA1 for FN#1 is at BAR0 + 0x0404 | ||
897 | * etc. | ||
898 | * ---------------------------------------------------------------------------- | ||
899 | * Accessable to all FN#s */ | ||
900 | #define SCU_SMU_PCP_OFFSET 0x0000 | ||
901 | #define SCU_SMU_AMR_OFFSET 0x0004 | ||
902 | #define SCU_SMU_ISR_OFFSET 0x0010 | ||
903 | #define SCU_SMU_IMR_OFFSET 0x0014 | ||
904 | #define SCU_SMU_ICC_OFFSET 0x0018 | ||
905 | #define SCU_SMU_HTTLBAR_OFFSET 0x0020 | ||
906 | #define SCU_SMU_HTTUBAR_OFFSET 0x0024 | ||
907 | #define SCU_SMU_TCR_OFFSET 0x0028 | ||
908 | #define SCU_SMU_CQLBAR_OFFSET 0x0030 | ||
909 | #define SCU_SMU_CQUBAR_OFFSET 0x0034 | ||
910 | #define SCU_SMU_CQPR_OFFSET 0x0040 | ||
911 | #define SCU_SMU_CQGR_OFFSET 0x0044 | ||
912 | #define SCU_SMU_CQC_OFFSET 0x0048 | ||
913 | /* Accessable to FN#0 only */ | ||
914 | #define SCU_SMU_RNCLBAR_OFFSET 0x0080 | ||
915 | #define SCU_SMU_RNCUBAR_OFFSET 0x0084 | ||
916 | #define SCU_SMU_DCC_OFFSET 0x0090 | ||
917 | #define SCU_SMU_DFC_OFFSET 0x0094 | ||
918 | #define SCU_SMU_SMUCSR_OFFSET 0x0098 | ||
919 | #define SCU_SMU_SCUSRCR_OFFSET 0x009C | ||
920 | #define SCU_SMU_SMAW_OFFSET 0x00A0 | ||
921 | #define SCU_SMU_SMDW_OFFSET 0x00A4 | ||
922 | /* Accessable to FN#0 only */ | ||
923 | #define SCU_SMU_TCA_OFFSET 0x0400 | ||
924 | /* Accessable to all FN#s */ | ||
925 | #define SCU_SMU_MT_MLAR0_OFFSET 0x2000 | ||
926 | #define SCU_SMU_MT_MUAR0_OFFSET 0x2004 | ||
927 | #define SCU_SMU_MT_MDR0_OFFSET 0x2008 | ||
928 | #define SCU_SMU_MT_VCR0_OFFSET 0x200C | ||
929 | #define SCU_SMU_MT_MLAR1_OFFSET 0x2010 | ||
930 | #define SCU_SMU_MT_MUAR1_OFFSET 0x2014 | ||
931 | #define SCU_SMU_MT_MDR1_OFFSET 0x2018 | ||
932 | #define SCU_SMU_MT_VCR1_OFFSET 0x201C | ||
933 | #define SCU_SMU_MPBA_OFFSET 0x3000 | ||
934 | |||
935 | /** | ||
936 | * struct smu_registers - These are the SMU registers | ||
937 | * | ||
938 | * | ||
939 | */ | ||
940 | struct smu_registers { | ||
941 | /* 0x0000 PCP */ | ||
942 | u32 post_context_port; | ||
943 | /* 0x0004 AMR */ | ||
944 | u32 address_modifier; | ||
945 | u32 reserved_08; | ||
946 | u32 reserved_0C; | ||
947 | /* 0x0010 ISR */ | ||
948 | u32 interrupt_status; | ||
949 | /* 0x0014 IMR */ | ||
950 | u32 interrupt_mask; | ||
951 | /* 0x0018 ICC */ | ||
952 | u32 interrupt_coalesce_control; | ||
953 | u32 reserved_1C; | ||
954 | /* 0x0020 HTTLBAR */ | ||
955 | u32 host_task_table_lower; | ||
956 | /* 0x0024 HTTUBAR */ | ||
957 | u32 host_task_table_upper; | ||
958 | /* 0x0028 TCR */ | ||
959 | u32 task_context_range; | ||
960 | u32 reserved_2C; | ||
961 | /* 0x0030 CQLBAR */ | ||
962 | u32 completion_queue_lower; | ||
963 | /* 0x0034 CQUBAR */ | ||
964 | u32 completion_queue_upper; | ||
965 | u32 reserved_38; | ||
966 | u32 reserved_3C; | ||
967 | /* 0x0040 CQPR */ | ||
968 | u32 completion_queue_put; | ||
969 | /* 0x0044 CQGR */ | ||
970 | u32 completion_queue_get; | ||
971 | /* 0x0048 CQC */ | ||
972 | u32 completion_queue_control; | ||
973 | u32 reserved_4C; | ||
974 | u32 reserved_5x[4]; | ||
975 | u32 reserved_6x[4]; | ||
976 | u32 reserved_7x[4]; | ||
977 | /* | ||
978 | * Accessable to FN#0 only | ||
979 | * 0x0080 RNCLBAR */ | ||
980 | u32 remote_node_context_lower; | ||
981 | /* 0x0084 RNCUBAR */ | ||
982 | u32 remote_node_context_upper; | ||
983 | u32 reserved_88; | ||
984 | u32 reserved_8C; | ||
985 | /* 0x0090 DCC */ | ||
986 | u32 device_context_capacity; | ||
987 | /* 0x0094 DFC */ | ||
988 | u32 device_function_capacity; | ||
989 | /* 0x0098 SMUCSR */ | ||
990 | u32 control_status; | ||
991 | /* 0x009C SCUSRCR */ | ||
992 | u32 soft_reset_control; | ||
993 | /* 0x00A0 SMAW */ | ||
994 | u32 mmr_address_window; | ||
995 | /* 0x00A4 SMDW */ | ||
996 | u32 mmr_data_window; | ||
997 | u32 reserved_A8; | ||
998 | u32 reserved_AC; | ||
999 | /* A whole bunch of reserved space */ | ||
1000 | u32 reserved_Bx[4]; | ||
1001 | u32 reserved_Cx[4]; | ||
1002 | u32 reserved_Dx[4]; | ||
1003 | u32 reserved_Ex[4]; | ||
1004 | u32 reserved_Fx[4]; | ||
1005 | u32 reserved_1xx[64]; | ||
1006 | u32 reserved_2xx[64]; | ||
1007 | u32 reserved_3xx[64]; | ||
1008 | /* | ||
1009 | * Accessable to FN#0 only | ||
1010 | * 0x0400 TCA */ | ||
1011 | u32 task_context_assignment[256]; | ||
1012 | /* MSI-X registers not included */ | ||
1013 | }; | ||
1014 | |||
1015 | /* | ||
1016 | * ***************************************************************************** | ||
1017 | * SDMA Registers | ||
1018 | * ***************************************************************************** */ | ||
1019 | #define SCU_SDMA_BASE 0x6000 | ||
1020 | #define SCU_SDMA_PUFATLHAR_OFFSET 0x0000 | ||
1021 | #define SCU_SDMA_PUFATUHAR_OFFSET 0x0004 | ||
1022 | #define SCU_SDMA_UFLHBAR_OFFSET 0x0008 | ||
1023 | #define SCU_SDMA_UFUHBAR_OFFSET 0x000C | ||
1024 | #define SCU_SDMA_UFQC_OFFSET 0x0010 | ||
1025 | #define SCU_SDMA_UFQPP_OFFSET 0x0014 | ||
1026 | #define SCU_SDMA_UFQGP_OFFSET 0x0018 | ||
1027 | #define SCU_SDMA_PDMACR_OFFSET 0x001C | ||
1028 | #define SCU_SDMA_CDMACR_OFFSET 0x0080 | ||
1029 | |||
1030 | /** | ||
1031 | * struct scu_sdma_registers - These are the SCU SDMA Registers | ||
1032 | * | ||
1033 | * | ||
1034 | */ | ||
1035 | struct scu_sdma_registers { | ||
1036 | /* 0x0000 PUFATLHAR */ | ||
1037 | u32 uf_address_table_lower; | ||
1038 | /* 0x0004 PUFATUHAR */ | ||
1039 | u32 uf_address_table_upper; | ||
1040 | /* 0x0008 UFLHBAR */ | ||
1041 | u32 uf_header_base_address_lower; | ||
1042 | /* 0x000C UFUHBAR */ | ||
1043 | u32 uf_header_base_address_upper; | ||
1044 | /* 0x0010 UFQC */ | ||
1045 | u32 unsolicited_frame_queue_control; | ||
1046 | /* 0x0014 UFQPP */ | ||
1047 | u32 unsolicited_frame_put_pointer; | ||
1048 | /* 0x0018 UFQGP */ | ||
1049 | u32 unsolicited_frame_get_pointer; | ||
1050 | /* 0x001C PDMACR */ | ||
1051 | u32 pdma_configuration; | ||
1052 | /* Reserved until offset 0x80 */ | ||
1053 | u32 reserved_0020_007C[0x18]; | ||
1054 | /* 0x0080 CDMACR */ | ||
1055 | u32 cdma_configuration; | ||
1056 | /* Remainder SDMA register space */ | ||
1057 | u32 reserved_0084_0400[0xDF]; | ||
1058 | |||
1059 | }; | ||
1060 | |||
1061 | /* | ||
1062 | * ***************************************************************************** | ||
1063 | * * SCU Link Registers | ||
1064 | * ***************************************************************************** */ | ||
1065 | #define SCU_PEG0_OFFSET 0x0000 | ||
1066 | #define SCU_PEG1_OFFSET 0x8000 | ||
1067 | |||
1068 | #define SCU_TL0_OFFSET 0x0000 | ||
1069 | #define SCU_TL1_OFFSET 0x0400 | ||
1070 | #define SCU_TL2_OFFSET 0x0800 | ||
1071 | #define SCU_TL3_OFFSET 0x0C00 | ||
1072 | |||
1073 | #define SCU_LL_OFFSET 0x0080 | ||
1074 | #define SCU_LL0_OFFSET (SCU_TL0_OFFSET + SCU_LL_OFFSET) | ||
1075 | #define SCU_LL1_OFFSET (SCU_TL1_OFFSET + SCU_LL_OFFSET) | ||
1076 | #define SCU_LL2_OFFSET (SCU_TL2_OFFSET + SCU_LL_OFFSET) | ||
1077 | #define SCU_LL3_OFFSET (SCU_TL3_OFFSET + SCU_LL_OFFSET) | ||
1078 | |||
1079 | /* Transport Layer Offsets (PEG + TL) */ | ||
1080 | #define SCU_TLCR_OFFSET 0x0000 | ||
1081 | #define SCU_TLADTR_OFFSET 0x0004 | ||
1082 | #define SCU_TLTTMR_OFFSET 0x0008 | ||
1083 | #define SCU_TLEECR0_OFFSET 0x000C | ||
1084 | #define SCU_STPTLDARNI_OFFSET 0x0010 | ||
1085 | |||
1086 | |||
1087 | #define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_SHIFT (0) | ||
1088 | #define SCU_TLCR_HASH_SAS_CHECKING_ENABLE_MASK (0x00000001) | ||
1089 | #define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_SHIFT (1) | ||
1090 | #define SCU_TLCR_CLEAR_TCI_NCQ_MAPPING_TABLE_MASK (0x00000002) | ||
1091 | #define SCU_TLCR_STP_WRITE_DATA_PREFETCH_SHIFT (3) | ||
1092 | #define SCU_TLCR_STP_WRITE_DATA_PREFETCH_MASK (0x00000008) | ||
1093 | #define SCU_TLCR_CMD_NAK_STATUS_CODE_SHIFT (4) | ||
1094 | #define SCU_TLCR_CMD_NAK_STATUS_CODE_MASK (0x00000010) | ||
1095 | #define SCU_TLCR_RESERVED_MASK (0xFFFFFFEB) | ||
1096 | |||
1097 | #define SCU_TLCR_GEN_BIT(name) \ | ||
1098 | SCU_GEN_BIT(SCU_TLCR_ ## name) | ||
1099 | |||
1100 | /** | ||
1101 | * struct scu_transport_layer_registers - These are the SCU Transport Layer | ||
1102 | * registers | ||
1103 | * | ||
1104 | * | ||
1105 | */ | ||
1106 | struct scu_transport_layer_registers { | ||
1107 | /* 0x0000 TLCR */ | ||
1108 | u32 control; | ||
1109 | /* 0x0004 TLADTR */ | ||
1110 | u32 arbitration_delay_timer; | ||
1111 | /* 0x0008 TLTTMR */ | ||
1112 | u32 timer_test_mode; | ||
1113 | /* 0x000C reserved */ | ||
1114 | u32 reserved_0C; | ||
1115 | /* 0x0010 STPTLDARNI */ | ||
1116 | u32 stp_rni; | ||
1117 | /* 0x0014 TLFEWPORCTRL */ | ||
1118 | u32 tlfe_wpo_read_control; | ||
1119 | /* 0x0018 TLFEWPORDATA */ | ||
1120 | u32 tlfe_wpo_read_data; | ||
1121 | /* 0x001C RXTLSSCSR1 */ | ||
1122 | u32 rxtl_single_step_control_status_1; | ||
1123 | /* 0x0020 RXTLSSCSR2 */ | ||
1124 | u32 rxtl_single_step_control_status_2; | ||
1125 | /* 0x0024 AWTRDDCR */ | ||
1126 | u32 tlfe_awt_retry_delay_debug_control; | ||
1127 | /* Remainder of TL memory space */ | ||
1128 | u32 reserved_0028_007F[0x16]; | ||
1129 | |||
1130 | }; | ||
1131 | |||
1132 | /* Protocol Engine Group Registers */ | ||
1133 | #define SCU_SCUVZECRx_OFFSET 0x1080 | ||
1134 | |||
1135 | /* Link Layer Offsets (PEG + TL + LL) */ | ||
1136 | #define SCU_SAS_SPDTOV_OFFSET 0x0000 | ||
1137 | #define SCU_SAS_LLSTA_OFFSET 0x0004 | ||
1138 | #define SCU_SATA_PSELTOV_OFFSET 0x0008 | ||
1139 | #define SCU_SAS_TIMETOV_OFFSET 0x0010 | ||
1140 | #define SCU_SAS_LOSTOT_OFFSET 0x0014 | ||
1141 | #define SCU_SAS_LNKTOV_OFFSET 0x0018 | ||
1142 | #define SCU_SAS_PHYTOV_OFFSET 0x001C | ||
1143 | #define SCU_SAS_AFERCNT_OFFSET 0x0020 | ||
1144 | #define SCU_SAS_WERCNT_OFFSET 0x0024 | ||
1145 | #define SCU_SAS_TIID_OFFSET 0x0028 | ||
1146 | #define SCU_SAS_TIDNH_OFFSET 0x002C | ||
1147 | #define SCU_SAS_TIDNL_OFFSET 0x0030 | ||
1148 | #define SCU_SAS_TISSAH_OFFSET 0x0034 | ||
1149 | #define SCU_SAS_TISSAL_OFFSET 0x0038 | ||
1150 | #define SCU_SAS_TIPID_OFFSET 0x003C | ||
1151 | #define SCU_SAS_TIRES2_OFFSET 0x0040 | ||
1152 | #define SCU_SAS_ADRSTA_OFFSET 0x0044 | ||
1153 | #define SCU_SAS_MAWTTOV_OFFSET 0x0048 | ||
1154 | #define SCU_SAS_FRPLDFIL_OFFSET 0x0054 | ||
1155 | #define SCU_SAS_RFCNT_OFFSET 0x0060 | ||
1156 | #define SCU_SAS_TFCNT_OFFSET 0x0064 | ||
1157 | #define SCU_SAS_RFDCNT_OFFSET 0x0068 | ||
1158 | #define SCU_SAS_TFDCNT_OFFSET 0x006C | ||
1159 | #define SCU_SAS_LERCNT_OFFSET 0x0070 | ||
1160 | #define SCU_SAS_RDISERRCNT_OFFSET 0x0074 | ||
1161 | #define SCU_SAS_CRERCNT_OFFSET 0x0078 | ||
1162 | #define SCU_STPCTL_OFFSET 0x007C | ||
1163 | #define SCU_SAS_PCFG_OFFSET 0x0080 | ||
1164 | #define SCU_SAS_CLKSM_OFFSET 0x0084 | ||
1165 | #define SCU_SAS_TXCOMWAKE_OFFSET 0x0088 | ||
1166 | #define SCU_SAS_TXCOMINIT_OFFSET 0x008C | ||
1167 | #define SCU_SAS_TXCOMSAS_OFFSET 0x0090 | ||
1168 | #define SCU_SAS_COMINIT_OFFSET 0x0094 | ||
1169 | #define SCU_SAS_COMWAKE_OFFSET 0x0098 | ||
1170 | #define SCU_SAS_COMSAS_OFFSET 0x009C | ||
1171 | #define SCU_SAS_SFERCNT_OFFSET 0x00A0 | ||
1172 | #define SCU_SAS_CDFERCNT_OFFSET 0x00A4 | ||
1173 | #define SCU_SAS_DNFERCNT_OFFSET 0x00A8 | ||
1174 | #define SCU_SAS_PRSTERCNT_OFFSET 0x00AC | ||
1175 | #define SCU_SAS_CNTCTL_OFFSET 0x00B0 | ||
1176 | #define SCU_SAS_SSPTOV_OFFSET 0x00B4 | ||
1177 | #define SCU_FTCTL_OFFSET 0x00B8 | ||
1178 | #define SCU_FRCTL_OFFSET 0x00BC | ||
1179 | #define SCU_FTWMRK_OFFSET 0x00C0 | ||
1180 | #define SCU_ENSPINUP_OFFSET 0x00C4 | ||
1181 | #define SCU_SAS_TRNTOV_OFFSET 0x00C8 | ||
1182 | #define SCU_SAS_PHYCAP_OFFSET 0x00CC | ||
1183 | #define SCU_SAS_PHYCTL_OFFSET 0x00D0 | ||
1184 | #define SCU_SAS_LLCTL_OFFSET 0x00D8 | ||
1185 | #define SCU_AFE_XCVRCR_OFFSET 0x00DC | ||
1186 | #define SCU_AFE_LUTCR_OFFSET 0x00E0 | ||
1187 | |||
1188 | #define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_SHIFT (0) | ||
1189 | #define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_MASK (0x00000003) | ||
1190 | #define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1 (0) | ||
1191 | #define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2 (1) | ||
1192 | #define SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3 (2) | ||
1193 | #define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_SHIFT (2) | ||
1194 | #define SCU_SAS_LINK_LAYER_CONTROL_BROADCAST_PRIMITIVE_MASK (0x000003FC) | ||
1195 | #define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_SHIFT (16) | ||
1196 | #define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_ACTIVE_TASK_DISABLE_MASK (0x00010000) | ||
1197 | #define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_SHIFT (17) | ||
1198 | #define SCU_SAS_LINK_LAYER_CONTROL_CLOSE_NO_OUTBOUND_TASK_DISABLE_MASK (0x00020000) | ||
1199 | #define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_SHIFT (24) | ||
1200 | #define SCU_SAS_LINK_LAYER_CONTROL_NO_OUTBOUND_TASK_TIMEOUT_MASK (0xFF000000) | ||
1201 | #define SCU_SAS_LINK_LAYER_CONTROL_RESERVED (0x00FCFC00) | ||
1202 | |||
1203 | #define SCU_SAS_LLCTL_GEN_VAL(name, value) \ | ||
1204 | SCU_GEN_VALUE(SCU_SAS_LINK_LAYER_CONTROL_ ## name, value) | ||
1205 | |||
1206 | #define SCU_SAS_LLCTL_GEN_BIT(name) \ | ||
1207 | SCU_GEN_BIT(SCU_SAS_LINK_LAYER_CONTROL_ ## name) | ||
1208 | |||
1209 | |||
1210 | /* #define SCU_FRXHECR_DCNT_OFFSET 0x00B0 */ | ||
1211 | #define SCU_PSZGCR_OFFSET 0x00E4 | ||
1212 | #define SCU_SAS_RECPHYCAP_OFFSET 0x00E8 | ||
1213 | /* #define SCU_TX_LUTSEL_OFFSET 0x00B8 */ | ||
1214 | |||
1215 | #define SCU_SAS_PTxC_OFFSET 0x00D4 /* Same offset as SAS_TCTSTM */ | ||
1216 | |||
1217 | /** | ||
1218 | * struct scu_link_layer_registers - SCU Link Layer Registers | ||
1219 | * | ||
1220 | * | ||
1221 | */ | ||
1222 | struct scu_link_layer_registers { | ||
1223 | /* 0x0000 SAS_SPDTOV */ | ||
1224 | u32 speed_negotiation_timers; | ||
1225 | /* 0x0004 SAS_LLSTA */ | ||
1226 | u32 link_layer_status; | ||
1227 | /* 0x0008 SATA_PSELTOV */ | ||
1228 | u32 port_selector_timeout; | ||
1229 | u32 reserved0C; | ||
1230 | /* 0x0010 SAS_TIMETOV */ | ||
1231 | u32 timeout_unit_value; | ||
1232 | /* 0x0014 SAS_RCDTOV */ | ||
1233 | u32 rcd_timeout; | ||
1234 | /* 0x0018 SAS_LNKTOV */ | ||
1235 | u32 link_timer_timeouts; | ||
1236 | /* 0x001C SAS_PHYTOV */ | ||
1237 | u32 sas_phy_timeouts; | ||
1238 | /* 0x0020 SAS_AFERCNT */ | ||
1239 | u32 received_address_frame_error_counter; | ||
1240 | /* 0x0024 SAS_WERCNT */ | ||
1241 | u32 invalid_dword_counter; | ||
1242 | /* 0x0028 SAS_TIID */ | ||
1243 | u32 transmit_identification; | ||
1244 | /* 0x002C SAS_TIDNH */ | ||
1245 | u32 sas_device_name_high; | ||
1246 | /* 0x0030 SAS_TIDNL */ | ||
1247 | u32 sas_device_name_low; | ||
1248 | /* 0x0034 SAS_TISSAH */ | ||
1249 | u32 source_sas_address_high; | ||
1250 | /* 0x0038 SAS_TISSAL */ | ||
1251 | u32 source_sas_address_low; | ||
1252 | /* 0x003C SAS_TIPID */ | ||
1253 | u32 identify_frame_phy_id; | ||
1254 | /* 0x0040 SAS_TIRES2 */ | ||
1255 | u32 identify_frame_reserved; | ||
1256 | /* 0x0044 SAS_ADRSTA */ | ||
1257 | u32 received_address_frame; | ||
1258 | /* 0x0048 SAS_MAWTTOV */ | ||
1259 | u32 maximum_arbitration_wait_timer_timeout; | ||
1260 | /* 0x004C SAS_PTxC */ | ||
1261 | u32 transmit_primitive; | ||
1262 | /* 0x0050 SAS_RORES */ | ||
1263 | u32 error_counter_event_notification_control; | ||
1264 | /* 0x0054 SAS_FRPLDFIL */ | ||
1265 | u32 frxq_payload_fill_threshold; | ||
1266 | /* 0x0058 SAS_LLHANG_TOT */ | ||
1267 | u32 link_layer_hang_detection_timeout; | ||
1268 | u32 reserved_5C; | ||
1269 | /* 0x0060 SAS_RFCNT */ | ||
1270 | u32 received_frame_count; | ||
1271 | /* 0x0064 SAS_TFCNT */ | ||
1272 | u32 transmit_frame_count; | ||
1273 | /* 0x0068 SAS_RFDCNT */ | ||
1274 | u32 received_dword_count; | ||
1275 | /* 0x006C SAS_TFDCNT */ | ||
1276 | u32 transmit_dword_count; | ||
1277 | /* 0x0070 SAS_LERCNT */ | ||
1278 | u32 loss_of_sync_error_count; | ||
1279 | /* 0x0074 SAS_RDISERRCNT */ | ||
1280 | u32 running_disparity_error_count; | ||
1281 | /* 0x0078 SAS_CRERCNT */ | ||
1282 | u32 received_frame_crc_error_count; | ||
1283 | /* 0x007C STPCTL */ | ||
1284 | u32 stp_control; | ||
1285 | /* 0x0080 SAS_PCFG */ | ||
1286 | u32 phy_configuration; | ||
1287 | /* 0x0084 SAS_CLKSM */ | ||
1288 | u32 clock_skew_management; | ||
1289 | /* 0x0088 SAS_TXCOMWAKE */ | ||
1290 | u32 transmit_comwake_signal; | ||
1291 | /* 0x008C SAS_TXCOMINIT */ | ||
1292 | u32 transmit_cominit_signal; | ||
1293 | /* 0x0090 SAS_TXCOMSAS */ | ||
1294 | u32 transmit_comsas_signal; | ||
1295 | /* 0x0094 SAS_COMINIT */ | ||
1296 | u32 cominit_control; | ||
1297 | /* 0x0098 SAS_COMWAKE */ | ||
1298 | u32 comwake_control; | ||
1299 | /* 0x009C SAS_COMSAS */ | ||
1300 | u32 comsas_control; | ||
1301 | /* 0x00A0 SAS_SFERCNT */ | ||
1302 | u32 received_short_frame_count; | ||
1303 | /* 0x00A4 SAS_CDFERCNT */ | ||
1304 | u32 received_frame_without_credit_count; | ||
1305 | /* 0x00A8 SAS_DNFERCNT */ | ||
1306 | u32 received_frame_after_done_count; | ||
1307 | /* 0x00AC SAS_PRSTERCNT */ | ||
1308 | u32 phy_reset_problem_count; | ||
1309 | /* 0x00B0 SAS_CNTCTL */ | ||
1310 | u32 counter_control; | ||
1311 | /* 0x00B4 SAS_SSPTOV */ | ||
1312 | u32 ssp_timer_timeout_values; | ||
1313 | /* 0x00B8 FTCTL */ | ||
1314 | u32 ftx_control; | ||
1315 | /* 0x00BC FRCTL */ | ||
1316 | u32 frx_control; | ||
1317 | /* 0x00C0 FTWMRK */ | ||
1318 | u32 ftx_watermark; | ||
1319 | /* 0x00C4 ENSPINUP */ | ||
1320 | u32 notify_enable_spinup_control; | ||
1321 | /* 0x00C8 SAS_TRNTOV */ | ||
1322 | u32 sas_training_sequence_timer_values; | ||
1323 | /* 0x00CC SAS_PHYCAP */ | ||
1324 | u32 phy_capabilities; | ||
1325 | /* 0x00D0 SAS_PHYCTL */ | ||
1326 | u32 phy_control; | ||
1327 | u32 reserved_d4; | ||
1328 | /* 0x00D8 LLCTL */ | ||
1329 | u32 link_layer_control; | ||
1330 | /* 0x00DC AFE_XCVRCR */ | ||
1331 | u32 afe_xcvr_control; | ||
1332 | /* 0x00E0 AFE_LUTCR */ | ||
1333 | u32 afe_lookup_table_control; | ||
1334 | /* 0x00E4 PSZGCR */ | ||
1335 | u32 phy_source_zone_group_control; | ||
1336 | /* 0x00E8 SAS_RECPHYCAP */ | ||
1337 | u32 receive_phycap; | ||
1338 | u32 reserved_ec; | ||
1339 | /* 0x00F0 SNAFERXRSTCTL */ | ||
1340 | u32 speed_negotiation_afe_rx_reset_control; | ||
1341 | /* 0x00F4 SAS_SSIPMCTL */ | ||
1342 | u32 power_management_control; | ||
1343 | /* 0x00F8 SAS_PSPREQ_PRIM */ | ||
1344 | u32 sas_pm_partial_request_primitive; | ||
1345 | /* 0x00FC SAS_PSSREQ_PRIM */ | ||
1346 | u32 sas_pm_slumber_request_primitive; | ||
1347 | /* 0x0100 SAS_PPSACK_PRIM */ | ||
1348 | u32 sas_pm_ack_primitive_register; | ||
1349 | /* 0x0104 SAS_PSNAK_PRIM */ | ||
1350 | u32 sas_pm_nak_primitive_register; | ||
1351 | /* 0x0108 SAS_SSIPMTOV */ | ||
1352 | u32 sas_primitive_timeout; | ||
1353 | u32 reserved_10c; | ||
1354 | /* 0x0110 - 0x011C PLAPRDCTRLxREG */ | ||
1355 | u32 pla_product_control[4]; | ||
1356 | /* 0x0120 PLAPRDSUMREG */ | ||
1357 | u32 pla_product_sum; | ||
1358 | /* 0x0124 PLACONTROLREG */ | ||
1359 | u32 pla_control; | ||
1360 | /* Remainder of memory space 896 bytes */ | ||
1361 | u32 reserved_0128_037f[0x96]; | ||
1362 | |||
1363 | }; | ||
1364 | |||
1365 | /* | ||
1366 | * 0x00D4 // Same offset as SAS_TCTSTM SAS_PTxC | ||
1367 | * u32 primitive_transmit_control; */ | ||
1368 | |||
1369 | /* | ||
1370 | * ---------------------------------------------------------------------------- | ||
1371 | * SGPIO | ||
1372 | * ---------------------------------------------------------------------------- */ | ||
1373 | #define SCU_SGPIO_OFFSET 0x1400 | ||
1374 | |||
1375 | /* #define SCU_SGPIO_OFFSET 0x6000 // later moves to 0x1400 see HSD 652625 */ | ||
1376 | #define SCU_SGPIO_SGICR_OFFSET 0x0000 | ||
1377 | #define SCU_SGPIO_SGPBR_OFFSET 0x0004 | ||
1378 | #define SCU_SGPIO_SGSDLR_OFFSET 0x0008 | ||
1379 | #define SCU_SGPIO_SGSDUR_OFFSET 0x000C | ||
1380 | #define SCU_SGPIO_SGSIDLR_OFFSET 0x0010 | ||
1381 | #define SCU_SGPIO_SGSIDUR_OFFSET 0x0014 | ||
1382 | #define SCU_SGPIO_SGVSCR_OFFSET 0x0018 | ||
1383 | /* Address from 0x0820 to 0x083C */ | ||
1384 | #define SCU_SGPIO_SGODSR_OFFSET 0x0020 | ||
1385 | |||
1386 | /** | ||
1387 | * struct scu_sgpio_registers - SCU SGPIO Registers | ||
1388 | * | ||
1389 | * | ||
1390 | */ | ||
1391 | struct scu_sgpio_registers { | ||
1392 | /* 0x0000 SGPIO_SGICR */ | ||
1393 | u32 interface_control; | ||
1394 | /* 0x0004 SGPIO_SGPBR */ | ||
1395 | u32 blink_rate; | ||
1396 | /* 0x0008 SGPIO_SGSDLR */ | ||
1397 | u32 start_drive_lower; | ||
1398 | /* 0x000C SGPIO_SGSDUR */ | ||
1399 | u32 start_drive_upper; | ||
1400 | /* 0x0010 SGPIO_SGSIDLR */ | ||
1401 | u32 serial_input_lower; | ||
1402 | /* 0x0014 SGPIO_SGSIDUR */ | ||
1403 | u32 serial_input_upper; | ||
1404 | /* 0x0018 SGPIO_SGVSCR */ | ||
1405 | u32 vendor_specific_code; | ||
1406 | /* 0x0020 SGPIO_SGODSR */ | ||
1407 | u32 ouput_data_select[8]; | ||
1408 | /* Remainder of memory space 256 bytes */ | ||
1409 | u32 reserved_1444_14ff[0x31]; | ||
1410 | |||
1411 | }; | ||
1412 | |||
1413 | /* | ||
1414 | * ***************************************************************************** | ||
1415 | * * Defines for VIIT entry offsets | ||
1416 | * * Access additional entries by SCU_VIIT_BASE + index * 0x10 | ||
1417 | * ***************************************************************************** */ | ||
1418 | #define SCU_VIIT_BASE 0x1c00 | ||
1419 | |||
1420 | struct SCU_VIIT_REGISTERS { | ||
1421 | u32 registers[256]; | ||
1422 | }; | ||
1423 | |||
1424 | /* | ||
1425 | * ***************************************************************************** | ||
1426 | * * SCU PORT TASK SCHEDULER REGISTERS | ||
1427 | * ***************************************************************************** */ | ||
1428 | |||
1429 | #define SCU_PTSG_BASE 0x1000 | ||
1430 | |||
1431 | #define SCU_PTSG_PTSGCR_OFFSET 0x0000 | ||
1432 | #define SCU_PTSG_RTCR_OFFSET 0x0004 | ||
1433 | #define SCU_PTSG_RTCCR_OFFSET 0x0008 | ||
1434 | #define SCU_PTSG_PTS0CR_OFFSET 0x0010 | ||
1435 | #define SCU_PTSG_PTS0SR_OFFSET 0x0014 | ||
1436 | #define SCU_PTSG_PTS1CR_OFFSET 0x0018 | ||
1437 | #define SCU_PTSG_PTS1SR_OFFSET 0x001C | ||
1438 | #define SCU_PTSG_PTS2CR_OFFSET 0x0020 | ||
1439 | #define SCU_PTSG_PTS2SR_OFFSET 0x0024 | ||
1440 | #define SCU_PTSG_PTS3CR_OFFSET 0x0028 | ||
1441 | #define SCU_PTSG_PTS3SR_OFFSET 0x002C | ||
1442 | #define SCU_PTSG_PCSPE0CR_OFFSET 0x0030 | ||
1443 | #define SCU_PTSG_PCSPE1CR_OFFSET 0x0034 | ||
1444 | #define SCU_PTSG_PCSPE2CR_OFFSET 0x0038 | ||
1445 | #define SCU_PTSG_PCSPE3CR_OFFSET 0x003C | ||
1446 | #define SCU_PTSG_ETMTSCCR_OFFSET 0x0040 | ||
1447 | #define SCU_PTSG_ETMRNSCCR_OFFSET 0x0044 | ||
1448 | |||
1449 | /** | ||
1450 | * struct scu_port_task_scheduler_registers - These are the control/stats pairs | ||
1451 | * for each Port Task Scheduler. | ||
1452 | * | ||
1453 | * | ||
1454 | */ | ||
1455 | struct scu_port_task_scheduler_registers { | ||
1456 | u32 control; | ||
1457 | u32 status; | ||
1458 | }; | ||
1459 | |||
1460 | typedef u32 SCU_PORT_PE_CONFIGURATION_REGISTER_T; | ||
1461 | |||
1462 | /** | ||
1463 | * struct scu_port_task_scheduler_group_registers - These are the PORT Task | ||
1464 | * Scheduler registers | ||
1465 | * | ||
1466 | * | ||
1467 | */ | ||
1468 | struct scu_port_task_scheduler_group_registers { | ||
1469 | /* 0x0000 PTSGCR */ | ||
1470 | u32 control; | ||
1471 | /* 0x0004 RTCR */ | ||
1472 | u32 real_time_clock; | ||
1473 | /* 0x0008 RTCCR */ | ||
1474 | u32 real_time_clock_control; | ||
1475 | /* 0x000C */ | ||
1476 | u32 reserved_0C; | ||
1477 | /* | ||
1478 | * 0x0010 PTS0CR | ||
1479 | * 0x0014 PTS0SR | ||
1480 | * 0x0018 PTS1CR | ||
1481 | * 0x001C PTS1SR | ||
1482 | * 0x0020 PTS2CR | ||
1483 | * 0x0024 PTS2SR | ||
1484 | * 0x0028 PTS3CR | ||
1485 | * 0x002C PTS3SR */ | ||
1486 | struct scu_port_task_scheduler_registers port[4]; | ||
1487 | /* | ||
1488 | * 0x0030 PCSPE0CR | ||
1489 | * 0x0034 PCSPE1CR | ||
1490 | * 0x0038 PCSPE2CR | ||
1491 | * 0x003C PCSPE3CR */ | ||
1492 | SCU_PORT_PE_CONFIGURATION_REGISTER_T protocol_engine[4]; | ||
1493 | /* 0x0040 ETMTSCCR */ | ||
1494 | u32 tc_scanning_interval_control; | ||
1495 | /* 0x0044 ETMRNSCCR */ | ||
1496 | u32 rnc_scanning_interval_control; | ||
1497 | /* Remainder of memory space 128 bytes */ | ||
1498 | u32 reserved_1048_107f[0x0E]; | ||
1499 | |||
1500 | }; | ||
1501 | |||
1502 | #define SCU_PTSG_SCUVZECR_OFFSET 0x003C | ||
1503 | |||
1504 | /* | ||
1505 | * ***************************************************************************** | ||
1506 | * * AFE REGISTERS | ||
1507 | * ***************************************************************************** */ | ||
1508 | #define SCU_AFE_MMR_BASE 0xE000 | ||
1509 | |||
1510 | /* | ||
1511 | * AFE 0 is at offset 0x0800 | ||
1512 | * AFE 1 is at offset 0x0900 | ||
1513 | * AFE 2 is at offset 0x0a00 | ||
1514 | * AFE 3 is at offset 0x0b00 */ | ||
1515 | struct scu_afe_transceiver { | ||
1516 | /* 0x0000 AFE_XCVR_CTRL0 */ | ||
1517 | u32 afe_xcvr_control0; | ||
1518 | /* 0x0004 AFE_XCVR_CTRL1 */ | ||
1519 | u32 afe_xcvr_control1; | ||
1520 | /* 0x0008 */ | ||
1521 | u32 reserved_0008; | ||
1522 | /* 0x000c afe_dfx_rx_control0 */ | ||
1523 | u32 afe_dfx_rx_control0; | ||
1524 | /* 0x0010 AFE_DFX_RX_CTRL1 */ | ||
1525 | u32 afe_dfx_rx_control1; | ||
1526 | /* 0x0014 */ | ||
1527 | u32 reserved_0014; | ||
1528 | /* 0x0018 AFE_DFX_RX_STS0 */ | ||
1529 | u32 afe_dfx_rx_status0; | ||
1530 | /* 0x001c AFE_DFX_RX_STS1 */ | ||
1531 | u32 afe_dfx_rx_status1; | ||
1532 | /* 0x0020 */ | ||
1533 | u32 reserved_0020; | ||
1534 | /* 0x0024 AFE_TX_CTRL */ | ||
1535 | u32 afe_tx_control; | ||
1536 | /* 0x0028 AFE_TX_AMP_CTRL0 */ | ||
1537 | u32 afe_tx_amp_control0; | ||
1538 | /* 0x002c AFE_TX_AMP_CTRL1 */ | ||
1539 | u32 afe_tx_amp_control1; | ||
1540 | /* 0x0030 AFE_TX_AMP_CTRL2 */ | ||
1541 | u32 afe_tx_amp_control2; | ||
1542 | /* 0x0034 AFE_TX_AMP_CTRL3 */ | ||
1543 | u32 afe_tx_amp_control3; | ||
1544 | /* 0x0038 afe_tx_ssc_control */ | ||
1545 | u32 afe_tx_ssc_control; | ||
1546 | /* 0x003c */ | ||
1547 | u32 reserved_003c; | ||
1548 | /* 0x0040 AFE_RX_SSC_CTRL0 */ | ||
1549 | u32 afe_rx_ssc_control0; | ||
1550 | /* 0x0044 AFE_RX_SSC_CTRL1 */ | ||
1551 | u32 afe_rx_ssc_control1; | ||
1552 | /* 0x0048 AFE_RX_SSC_CTRL2 */ | ||
1553 | u32 afe_rx_ssc_control2; | ||
1554 | /* 0x004c AFE_RX_EQ_STS0 */ | ||
1555 | u32 afe_rx_eq_status0; | ||
1556 | /* 0x0050 AFE_RX_EQ_STS1 */ | ||
1557 | u32 afe_rx_eq_status1; | ||
1558 | /* 0x0054 AFE_RX_CDR_STS */ | ||
1559 | u32 afe_rx_cdr_status; | ||
1560 | /* 0x0058 */ | ||
1561 | u32 reserved_0058; | ||
1562 | /* 0x005c AFE_CHAN_CTRL */ | ||
1563 | u32 afe_channel_control; | ||
1564 | /* 0x0060-0x006c */ | ||
1565 | u32 reserved_0060_006c[0x04]; | ||
1566 | /* 0x0070 AFE_XCVR_EC_STS0 */ | ||
1567 | u32 afe_xcvr_error_capture_status0; | ||
1568 | /* 0x0074 AFE_XCVR_EC_STS1 */ | ||
1569 | u32 afe_xcvr_error_capture_status1; | ||
1570 | /* 0x0078 AFE_XCVR_EC_STS2 */ | ||
1571 | u32 afe_xcvr_error_capture_status2; | ||
1572 | /* 0x007c afe_xcvr_ec_status3 */ | ||
1573 | u32 afe_xcvr_error_capture_status3; | ||
1574 | /* 0x0080 AFE_XCVR_EC_STS4 */ | ||
1575 | u32 afe_xcvr_error_capture_status4; | ||
1576 | /* 0x0084 AFE_XCVR_EC_STS5 */ | ||
1577 | u32 afe_xcvr_error_capture_status5; | ||
1578 | /* 0x0088-0x00fc */ | ||
1579 | u32 reserved_008c_00fc[0x1e]; | ||
1580 | }; | ||
1581 | |||
1582 | /** | ||
1583 | * struct scu_afe_registers - AFE Regsiters | ||
1584 | * | ||
1585 | * | ||
1586 | */ | ||
1587 | /* Uaoa AFE registers */ | ||
1588 | struct scu_afe_registers { | ||
1589 | /* 0Xe000 AFE_BIAS_CTRL */ | ||
1590 | u32 afe_bias_control; | ||
1591 | u32 reserved_0004; | ||
1592 | /* 0x0008 AFE_PLL_CTRL0 */ | ||
1593 | u32 afe_pll_control0; | ||
1594 | /* 0x000c AFE_PLL_CTRL1 */ | ||
1595 | u32 afe_pll_control1; | ||
1596 | /* 0x0010 AFE_PLL_CTRL2 */ | ||
1597 | u32 afe_pll_control2; | ||
1598 | /* 0x0014 AFE_CB_STS */ | ||
1599 | u32 afe_common_block_status; | ||
1600 | /* 0x0018-0x007c */ | ||
1601 | u32 reserved_18_7c[0x1a]; | ||
1602 | /* 0x0080 AFE_PMSN_MCTRL0 */ | ||
1603 | u32 afe_pmsn_master_control0; | ||
1604 | /* 0x0084 AFE_PMSN_MCTRL1 */ | ||
1605 | u32 afe_pmsn_master_control1; | ||
1606 | /* 0x0088 AFE_PMSN_MCTRL2 */ | ||
1607 | u32 afe_pmsn_master_control2; | ||
1608 | /* 0x008C-0x00fc */ | ||
1609 | u32 reserved_008c_00fc[0x1D]; | ||
1610 | /* 0x0100 AFE_DFX_MST_CTRL0 */ | ||
1611 | u32 afe_dfx_master_control0; | ||
1612 | /* 0x0104 AFE_DFX_MST_CTRL1 */ | ||
1613 | u32 afe_dfx_master_control1; | ||
1614 | /* 0x0108 AFE_DFX_DCL_CTRL */ | ||
1615 | u32 afe_dfx_dcl_control; | ||
1616 | /* 0x010c AFE_DFX_DMON_CTRL */ | ||
1617 | u32 afe_dfx_digital_monitor_control; | ||
1618 | /* 0x0110 AFE_DFX_AMONP_CTRL */ | ||
1619 | u32 afe_dfx_analog_p_monitor_control; | ||
1620 | /* 0x0114 AFE_DFX_AMONN_CTRL */ | ||
1621 | u32 afe_dfx_analog_n_monitor_control; | ||
1622 | /* 0x0118 AFE_DFX_NTL_STS */ | ||
1623 | u32 afe_dfx_ntl_status; | ||
1624 | /* 0x011c AFE_DFX_FIFO_STS0 */ | ||
1625 | u32 afe_dfx_fifo_status0; | ||
1626 | /* 0x0120 AFE_DFX_FIFO_STS1 */ | ||
1627 | u32 afe_dfx_fifo_status1; | ||
1628 | /* 0x0124 AFE_DFX_MPAT_CTRL */ | ||
1629 | u32 afe_dfx_master_pattern_control; | ||
1630 | /* 0x0128 AFE_DFX_P0_CTRL */ | ||
1631 | u32 afe_dfx_p0_control; | ||
1632 | /* 0x012c-0x01a8 AFE_DFX_P0_DRx */ | ||
1633 | u32 afe_dfx_p0_data[32]; | ||
1634 | /* 0x01ac */ | ||
1635 | u32 reserved_01ac; | ||
1636 | /* 0x01b0-0x020c AFE_DFX_P0_IRx */ | ||
1637 | u32 afe_dfx_p0_instruction[24]; | ||
1638 | /* 0x0210 */ | ||
1639 | u32 reserved_0210; | ||
1640 | /* 0x0214 AFE_DFX_P1_CTRL */ | ||
1641 | u32 afe_dfx_p1_control; | ||
1642 | /* 0x0218-0x245 AFE_DFX_P1_DRx */ | ||
1643 | u32 afe_dfx_p1_data[16]; | ||
1644 | /* 0x0258-0x029c */ | ||
1645 | u32 reserved_0258_029c[0x12]; | ||
1646 | /* 0x02a0-0x02bc AFE_DFX_P1_IRx */ | ||
1647 | u32 afe_dfx_p1_instruction[8]; | ||
1648 | /* 0x02c0-0x2fc */ | ||
1649 | u32 reserved_02c0_02fc[0x10]; | ||
1650 | /* 0x0300 AFE_DFX_TX_PMSN_CTRL */ | ||
1651 | u32 afe_dfx_tx_pmsn_control; | ||
1652 | /* 0x0304 AFE_DFX_RX_PMSN_CTRL */ | ||
1653 | u32 afe_dfx_rx_pmsn_control; | ||
1654 | u32 reserved_0308; | ||
1655 | /* 0x030c AFE_DFX_NOA_CTRL0 */ | ||
1656 | u32 afe_dfx_noa_control0; | ||
1657 | /* 0x0310 AFE_DFX_NOA_CTRL1 */ | ||
1658 | u32 afe_dfx_noa_control1; | ||
1659 | /* 0x0314 AFE_DFX_NOA_CTRL2 */ | ||
1660 | u32 afe_dfx_noa_control2; | ||
1661 | /* 0x0318 AFE_DFX_NOA_CTRL3 */ | ||
1662 | u32 afe_dfx_noa_control3; | ||
1663 | /* 0x031c AFE_DFX_NOA_CTRL4 */ | ||
1664 | u32 afe_dfx_noa_control4; | ||
1665 | /* 0x0320 AFE_DFX_NOA_CTRL5 */ | ||
1666 | u32 afe_dfx_noa_control5; | ||
1667 | /* 0x0324 AFE_DFX_NOA_CTRL6 */ | ||
1668 | u32 afe_dfx_noa_control6; | ||
1669 | /* 0x0328 AFE_DFX_NOA_CTRL7 */ | ||
1670 | u32 afe_dfx_noa_control7; | ||
1671 | /* 0x032c-0x07fc */ | ||
1672 | u32 reserved_032c_07fc[0x135]; | ||
1673 | |||
1674 | /* 0x0800-0x0bfc */ | ||
1675 | struct scu_afe_transceiver scu_afe_xcvr[4]; | ||
1676 | |||
1677 | /* 0x0c00-0x0ffc */ | ||
1678 | u32 reserved_0c00_0ffc[0x0100]; | ||
1679 | }; | ||
1680 | |||
1681 | struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS { | ||
1682 | u32 table[0xE0]; | ||
1683 | }; | ||
1684 | |||
1685 | |||
1686 | struct SCU_VIIT_IIT { | ||
1687 | u32 table[256]; | ||
1688 | }; | ||
1689 | |||
1690 | /** | ||
1691 | * Placeholder for the ZONE Partition Table information ZONING will not be | ||
1692 | * included in the 1.1 release. | ||
1693 | * | ||
1694 | * | ||
1695 | */ | ||
1696 | struct SCU_ZONE_PARTITION_TABLE { | ||
1697 | u32 table[2048]; | ||
1698 | }; | ||
1699 | |||
1700 | /** | ||
1701 | * Placeholder for the CRAM register since I am not sure if we need to | ||
1702 | * read/write to these registers as yet. | ||
1703 | * | ||
1704 | * | ||
1705 | */ | ||
1706 | struct SCU_COMPLETION_RAM { | ||
1707 | u32 ram[128]; | ||
1708 | }; | ||
1709 | |||
1710 | /** | ||
1711 | * Placeholder for the FBRAM registers since I am not sure if we need to | ||
1712 | * read/write to these registers as yet. | ||
1713 | * | ||
1714 | * | ||
1715 | */ | ||
1716 | struct SCU_FRAME_BUFFER_RAM { | ||
1717 | u32 ram[128]; | ||
1718 | }; | ||
1719 | |||
1720 | #define SCU_SCRATCH_RAM_SIZE_IN_DWORDS 256 | ||
1721 | |||
1722 | /** | ||
1723 | * Placeholder for the scratch RAM registers. | ||
1724 | * | ||
1725 | * | ||
1726 | */ | ||
1727 | struct SCU_SCRATCH_RAM { | ||
1728 | u32 ram[SCU_SCRATCH_RAM_SIZE_IN_DWORDS]; | ||
1729 | }; | ||
1730 | |||
1731 | /** | ||
1732 | * Placeholder since I am not yet sure what these registers are here for. | ||
1733 | * | ||
1734 | * | ||
1735 | */ | ||
1736 | struct NOA_PROTOCOL_ENGINE_PARTITION { | ||
1737 | u32 reserved[64]; | ||
1738 | }; | ||
1739 | |||
1740 | /** | ||
1741 | * Placeholder since I am not yet sure what these registers are here for. | ||
1742 | * | ||
1743 | * | ||
1744 | */ | ||
1745 | struct NOA_HUB_PARTITION { | ||
1746 | u32 reserved[64]; | ||
1747 | }; | ||
1748 | |||
1749 | /** | ||
1750 | * Placeholder since I am not yet sure what these registers are here for. | ||
1751 | * | ||
1752 | * | ||
1753 | */ | ||
1754 | struct NOA_HOST_INTERFACE_PARTITION { | ||
1755 | u32 reserved[64]; | ||
1756 | }; | ||
1757 | |||
1758 | /** | ||
1759 | * struct TRANSPORT_LINK_LAYER_PAIR - The SCU Hardware pairs up the TL | ||
1760 | * registers with the LL registers so we must place them adjcent to make the | ||
1761 | * array of registers in the PEG. | ||
1762 | * | ||
1763 | * | ||
1764 | */ | ||
1765 | struct TRANSPORT_LINK_LAYER_PAIR { | ||
1766 | struct scu_transport_layer_registers tl; | ||
1767 | struct scu_link_layer_registers ll; | ||
1768 | }; | ||
1769 | |||
1770 | /** | ||
1771 | * struct SCU_PEG_REGISTERS - SCU Protocol Engine Memory mapped register space. | ||
1772 | * These registers are unique to each protocol engine group. There can be | ||
1773 | * at most two PEG for a single SCU part. | ||
1774 | * | ||
1775 | * | ||
1776 | */ | ||
1777 | struct SCU_PEG_REGISTERS { | ||
1778 | struct TRANSPORT_LINK_LAYER_PAIR pe[4]; | ||
1779 | struct scu_port_task_scheduler_group_registers ptsg; | ||
1780 | struct SCU_PROTOCOL_ENGINE_GROUP_REGISTERS peg; | ||
1781 | struct scu_sgpio_registers sgpio; | ||
1782 | u32 reserved_01500_1BFF[0x1C0]; | ||
1783 | struct scu_viit_entry viit[64]; | ||
1784 | struct SCU_ZONE_PARTITION_TABLE zpt0; | ||
1785 | struct SCU_ZONE_PARTITION_TABLE zpt1; | ||
1786 | }; | ||
1787 | |||
1788 | /** | ||
1789 | * struct scu_registers - SCU regsiters including both PEG registers if we turn | ||
1790 | * on that compile option. All of these registers are in the memory mapped | ||
1791 | * space returned from BAR1. | ||
1792 | * | ||
1793 | * | ||
1794 | */ | ||
1795 | struct scu_registers { | ||
1796 | /* 0x0000 - PEG 0 */ | ||
1797 | struct SCU_PEG_REGISTERS peg0; | ||
1798 | |||
1799 | /* 0x6000 - SDMA and Miscellaneous */ | ||
1800 | struct scu_sdma_registers sdma; | ||
1801 | struct SCU_COMPLETION_RAM cram; | ||
1802 | struct SCU_FRAME_BUFFER_RAM fbram; | ||
1803 | u32 reserved_6800_69FF[0x80]; | ||
1804 | struct NOA_PROTOCOL_ENGINE_PARTITION noa_pe; | ||
1805 | struct NOA_HUB_PARTITION noa_hub; | ||
1806 | struct NOA_HOST_INTERFACE_PARTITION noa_if; | ||
1807 | u32 reserved_6d00_7fff[0x4c0]; | ||
1808 | |||
1809 | /* 0x8000 - PEG 1 */ | ||
1810 | struct SCU_PEG_REGISTERS peg1; | ||
1811 | |||
1812 | /* 0xE000 - AFE Registers */ | ||
1813 | struct scu_afe_registers afe; | ||
1814 | |||
1815 | /* 0xF000 - reserved */ | ||
1816 | u32 reserved_f000_211fff[0x80c00]; | ||
1817 | |||
1818 | /* 0x212000 - scratch RAM */ | ||
1819 | struct SCU_SCRATCH_RAM scratch_ram; | ||
1820 | |||
1821 | }; | ||
1822 | |||
1823 | |||
1824 | #endif /* _SCU_REGISTERS_HEADER_ */ | ||
diff --git a/drivers/scsi/isci/core/scu_remote_node_context.h b/drivers/scsi/isci/core/scu_remote_node_context.h new file mode 100644 index 000000000000..8006f2ee2d1d --- /dev/null +++ b/drivers/scsi/isci/core/scu_remote_node_context.h | |||
@@ -0,0 +1,230 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__ | ||
57 | #define __SCU_REMOTE_NODE_CONTEXT_HEADER__ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures and constatns used by the SCU hardware to | ||
61 | * describe a remote node context. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | #include "sci_types.h" | ||
66 | |||
67 | /** | ||
68 | * struct ssp_remote_node_context - This structure contains the SCU hardware | ||
69 | * definition for an SSP remote node. | ||
70 | * | ||
71 | * | ||
72 | */ | ||
73 | struct ssp_remote_node_context { | ||
74 | /* WORD 0 */ | ||
75 | |||
76 | /** | ||
77 | * This field is the remote node index assigned for this remote node. All | ||
78 | * remote nodes must have a unique remote node index. The value of the remote | ||
79 | * node index can not exceed the maximum number of remote nodes reported in | ||
80 | * the SCU device context capacity register. | ||
81 | */ | ||
82 | u32 remote_node_index:12; | ||
83 | u32 reserved0_1:4; | ||
84 | |||
85 | /** | ||
86 | * This field tells the SCU hardware how many simultaneous connections that | ||
87 | * this remote node will support. | ||
88 | */ | ||
89 | u32 remote_node_port_width:4; | ||
90 | |||
91 | /** | ||
92 | * This field tells the SCU hardware which logical port to associate with this | ||
93 | * remote node. | ||
94 | */ | ||
95 | u32 logical_port_index:3; | ||
96 | u32 reserved0_2:5; | ||
97 | |||
98 | /** | ||
99 | * This field will enable the I_T nexus loss timer for this remote node. | ||
100 | */ | ||
101 | u32 nexus_loss_timer_enable:1; | ||
102 | |||
103 | /** | ||
104 | * This field is the for driver debug only and is not used. | ||
105 | */ | ||
106 | u32 check_bit:1; | ||
107 | |||
108 | /** | ||
109 | * This field must be set to true when the hardware DMAs the remote node | ||
110 | * context to the hardware SRAM. When the remote node is being invalidated | ||
111 | * this field must be set to false. | ||
112 | */ | ||
113 | u32 is_valid:1; | ||
114 | |||
115 | /** | ||
116 | * This field must be set to true. | ||
117 | */ | ||
118 | u32 is_remote_node_context:1; | ||
119 | |||
120 | /* WORD 1 - 2 */ | ||
121 | |||
122 | /** | ||
123 | * This is the low word of the remote device SAS Address | ||
124 | */ | ||
125 | u32 remote_sas_address_lo; | ||
126 | |||
127 | /** | ||
128 | * This field is the high word of the remote device SAS Address | ||
129 | */ | ||
130 | u32 remote_sas_address_hi; | ||
131 | |||
132 | /* WORD 3 */ | ||
133 | /** | ||
134 | * This field reprensets the function number assigned to this remote device. | ||
135 | * This value must match the virtual function number that is being used to | ||
136 | * communicate to the device. | ||
137 | */ | ||
138 | u32 function_number:8; | ||
139 | u32 reserved3_1:8; | ||
140 | |||
141 | /** | ||
142 | * This field provides the driver a way to cheat on the arbitration wait time | ||
143 | * for this remote node. | ||
144 | */ | ||
145 | u32 arbitration_wait_time:16; | ||
146 | |||
147 | /* WORD 4 */ | ||
148 | /** | ||
149 | * This field tells the SCU hardware how long this device may occupy the | ||
150 | * connection before it must be closed. | ||
151 | */ | ||
152 | u32 connection_occupancy_timeout:16; | ||
153 | |||
154 | /** | ||
155 | * This field tells the SCU hardware how long to maintain a connection when | ||
156 | * there are no frames being transmitted on the link. | ||
157 | */ | ||
158 | u32 connection_inactivity_timeout:16; | ||
159 | |||
160 | /* WORD 5 */ | ||
161 | /** | ||
162 | * This field allows the driver to cheat on the arbitration wait time for this | ||
163 | * remote node. | ||
164 | */ | ||
165 | u32 initial_arbitration_wait_time:16; | ||
166 | |||
167 | /** | ||
168 | * This field is tells the hardware what to program for the connection rate in | ||
169 | * the open address frame. See the SAS spec for valid values. | ||
170 | */ | ||
171 | u32 oaf_connection_rate:4; | ||
172 | |||
173 | /** | ||
174 | * This field tells the SCU hardware what to program for the features in the | ||
175 | * open address frame. See the SAS spec for valid values. | ||
176 | */ | ||
177 | u32 oaf_features:4; | ||
178 | |||
179 | /** | ||
180 | * This field tells the SCU hardware what to use for the source zone group in | ||
181 | * the open address frame. See the SAS spec for more details on zoning. | ||
182 | */ | ||
183 | u32 oaf_source_zone_group:8; | ||
184 | |||
185 | /* WORD 6 */ | ||
186 | /** | ||
187 | * This field tells the SCU hardware what to use as the more capibilities in | ||
188 | * the open address frame. See the SAS Spec for details. | ||
189 | */ | ||
190 | u32 oaf_more_compatibility_features; | ||
191 | |||
192 | /* WORD 7 */ | ||
193 | u32 reserved7; | ||
194 | |||
195 | }; | ||
196 | |||
197 | /** | ||
198 | * struct stp_remote_node_context - This structure contains the SCU hardware | ||
199 | * definition for a STP remote node. | ||
200 | * | ||
201 | * STP Targets are not yet supported so this definition is a placeholder until | ||
202 | * we do support them. | ||
203 | */ | ||
204 | struct stp_remote_node_context { | ||
205 | /** | ||
206 | * Placeholder data for the STP remote node. | ||
207 | */ | ||
208 | u32 data[8]; | ||
209 | |||
210 | }; | ||
211 | |||
212 | /** | ||
213 | * This union combines the SAS and SATA remote node definitions. | ||
214 | * | ||
215 | * union scu_remote_node_context | ||
216 | */ | ||
217 | union scu_remote_node_context { | ||
218 | /** | ||
219 | * SSP Remote Node | ||
220 | */ | ||
221 | struct ssp_remote_node_context ssp; | ||
222 | |||
223 | /** | ||
224 | * STP Remote Node | ||
225 | */ | ||
226 | struct stp_remote_node_context stp; | ||
227 | |||
228 | }; | ||
229 | |||
230 | #endif /* __SCU_REMOTE_NODE_CONTEXT_HEADER__ */ | ||
diff --git a/drivers/scsi/isci/core/scu_task_context.h b/drivers/scsi/isci/core/scu_task_context.h new file mode 100644 index 000000000000..d08c51bb2262 --- /dev/null +++ b/drivers/scsi/isci/core/scu_task_context.h | |||
@@ -0,0 +1,943 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCU_TASK_CONTEXT_H_ | ||
57 | #define _SCU_TASK_CONTEXT_H_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the structures and constants for the SCU hardware task | ||
61 | * context. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_types.h" | ||
67 | |||
68 | /** | ||
69 | * enum SCU_SSP_TASK_TYPE - This enumberation defines the various SSP task | ||
70 | * types the SCU hardware will accept. The definition for the various task | ||
71 | * types the SCU hardware will accept can be found in the DS specification. | ||
72 | * | ||
73 | * | ||
74 | */ | ||
75 | typedef enum { | ||
76 | SCU_TASK_TYPE_IOREAD, /* /< IO READ direction or no direction */ | ||
77 | SCU_TASK_TYPE_IOWRITE, /* /< IO Write direction */ | ||
78 | SCU_TASK_TYPE_SMP_REQUEST, /* /< SMP Request type */ | ||
79 | SCU_TASK_TYPE_RESPONSE, /* /< Driver generated response frame (targt mode) */ | ||
80 | SCU_TASK_TYPE_RAW_FRAME, /* /< Raw frame request type */ | ||
81 | SCU_TASK_TYPE_PRIMITIVE /* /< Request for a primitive to be transmitted */ | ||
82 | } SCU_SSP_TASK_TYPE; | ||
83 | |||
84 | /** | ||
85 | * enum SCU_SATA_TASK_TYPE - This enumeration defines the various SATA task | ||
86 | * types the SCU hardware will accept. The definition for the various task | ||
87 | * types the SCU hardware will accept can be found in the DS specification. | ||
88 | * | ||
89 | * | ||
90 | */ | ||
91 | typedef enum { | ||
92 | SCU_TASK_TYPE_DMA_IN, /* /< Read request */ | ||
93 | SCU_TASK_TYPE_FPDMAQ_READ, /* /< NCQ read request */ | ||
94 | SCU_TASK_TYPE_PACKET_DMA_IN, /* /< Packet read request */ | ||
95 | SCU_TASK_TYPE_SATA_RAW_FRAME, /* /< Raw frame request */ | ||
96 | RESERVED_4, | ||
97 | RESERVED_5, | ||
98 | RESERVED_6, | ||
99 | RESERVED_7, | ||
100 | SCU_TASK_TYPE_DMA_OUT, /* /< Write request */ | ||
101 | SCU_TASK_TYPE_FPDMAQ_WRITE, /* /< NCQ write Request */ | ||
102 | SCU_TASK_TYPE_PACKET_DMA_OUT /* /< Packet write request */ | ||
103 | } SCU_SATA_TASK_TYPE; | ||
104 | |||
105 | |||
106 | /** | ||
107 | * | ||
108 | * | ||
109 | * SCU_CONTEXT_TYPE | ||
110 | */ | ||
111 | #define SCU_TASK_CONTEXT_TYPE 0 | ||
112 | #define SCU_RNC_CONTEXT_TYPE 1 | ||
113 | |||
114 | /** | ||
115 | * | ||
116 | * | ||
117 | * SCU_TASK_CONTEXT_VALIDITY | ||
118 | */ | ||
119 | #define SCU_TASK_CONTEXT_INVALID 0 | ||
120 | #define SCU_TASK_CONTEXT_VALID 1 | ||
121 | |||
122 | /** | ||
123 | * | ||
124 | * | ||
125 | * SCU_COMMAND_CODE | ||
126 | */ | ||
127 | #define SCU_COMMAND_CODE_INITIATOR_NEW_TASK 0 | ||
128 | #define SCU_COMMAND_CODE_ACTIVE_TASK 1 | ||
129 | #define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK 2 | ||
130 | #define SCU_COMMAND_CODE_TARGET_RAW_FRAMES 3 | ||
131 | |||
132 | /** | ||
133 | * | ||
134 | * | ||
135 | * SCU_TASK_PRIORITY | ||
136 | */ | ||
137 | /** | ||
138 | * | ||
139 | * | ||
140 | * This priority is used when there is no priority request for this request. | ||
141 | */ | ||
142 | #define SCU_TASK_PRIORITY_NORMAL 0 | ||
143 | |||
144 | /** | ||
145 | * | ||
146 | * | ||
147 | * This priority indicates that the task should be scheduled to the head of the | ||
148 | * queue. The task will NOT be executed if the TX is suspended for the remote | ||
149 | * node. | ||
150 | */ | ||
151 | #define SCU_TASK_PRIORITY_HEAD_OF_Q 1 | ||
152 | |||
153 | /** | ||
154 | * | ||
155 | * | ||
156 | * This priority indicates that the task will be executed before all | ||
157 | * SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks. The task | ||
158 | * WILL be executed if the TX is suspended for the remote node. | ||
159 | */ | ||
160 | #define SCU_TASK_PRIORITY_HIGH 2 | ||
161 | |||
162 | /** | ||
163 | * | ||
164 | * | ||
165 | * This task priority is reserved and should not be used. | ||
166 | */ | ||
167 | #define SCU_TASK_PRIORITY_RESERVED 3 | ||
168 | |||
169 | #define SCU_TASK_INITIATOR_MODE 1 | ||
170 | #define SCU_TASK_TARGET_MODE 0 | ||
171 | |||
172 | #define SCU_TASK_REGULAR 0 | ||
173 | #define SCU_TASK_ABORTED 1 | ||
174 | |||
175 | /* direction bit defintion */ | ||
176 | /** | ||
177 | * | ||
178 | * | ||
179 | * SATA_DIRECTION | ||
180 | */ | ||
181 | #define SCU_SATA_WRITE_DATA_DIRECTION 0 | ||
182 | #define SCU_SATA_READ_DATA_DIRECTION 1 | ||
183 | |||
184 | /** | ||
185 | * | ||
186 | * | ||
187 | * SCU_COMMAND_CONTEXT_MACROS These macros provide the mask and shift | ||
188 | * operations to construct the various SCU commands | ||
189 | */ | ||
190 | #define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT 21 | ||
191 | #define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK 0x00E00000 | ||
192 | #define scu_get_command_request_type(x) \ | ||
193 | ((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK) | ||
194 | |||
195 | #define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT 18 | ||
196 | #define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK 0x001C0000 | ||
197 | #define scu_get_command_request_subtype(x) \ | ||
198 | ((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK) | ||
199 | |||
200 | #define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK \ | ||
201 | (\ | ||
202 | SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK \ | ||
203 | | SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK \ | ||
204 | ) | ||
205 | #define scu_get_command_request_full_type(x) \ | ||
206 | ((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK) | ||
207 | |||
208 | #define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 16 | ||
209 | #define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK 0x00010000 | ||
210 | #define scu_get_command_protocl_engine_group(x) \ | ||
211 | ((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK) | ||
212 | |||
213 | #define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 12 | ||
214 | #define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK 0x00007000 | ||
215 | #define scu_get_command_reqeust_logical_port(x) \ | ||
216 | ((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK) | ||
217 | |||
218 | |||
219 | #define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \ | ||
220 | ((u32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT) | ||
221 | |||
222 | /** | ||
223 | * MAKE_SCU_CONTEXT_COMMAND_TYPE() - | ||
224 | * | ||
225 | * SCU_COMMAND_TYPES These constants provide the grouping of the different SCU | ||
226 | * command types. | ||
227 | */ | ||
228 | #define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(0) | ||
229 | #define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(1) | ||
230 | #define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(2) | ||
231 | #define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(3) | ||
232 | #define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(6) | ||
233 | |||
234 | #define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command) \ | ||
235 | ((type) | ((command) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT)) | ||
236 | |||
237 | /** | ||
238 | * | ||
239 | * | ||
240 | * SCU_REQUEST_TYPES These constants are the various request types that can be | ||
241 | * posted to the SCU hardware. | ||
242 | */ | ||
243 | #define SCU_CONTEXT_COMMAND_REQUST_POST_TC \ | ||
244 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0)) | ||
245 | |||
246 | #define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \ | ||
247 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1)) | ||
248 | |||
249 | #define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \ | ||
250 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0)) | ||
251 | |||
252 | #define SCU_CONTEXT_COMMAND_POST_RNC_32 \ | ||
253 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0)) | ||
254 | |||
255 | #define SCU_CONTEXT_COMMAND_POST_RNC_96 \ | ||
256 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1)) | ||
257 | |||
258 | #define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE \ | ||
259 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2)) | ||
260 | |||
261 | #define SCU_CONTEXT_COMMAND_DUMP_RNC_32 \ | ||
262 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0)) | ||
263 | |||
264 | #define SCU_CONTEXT_COMMAND_DUMP_RNC_96 \ | ||
265 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1)) | ||
266 | |||
267 | #define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX \ | ||
268 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0)) | ||
269 | |||
270 | #define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \ | ||
271 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1)) | ||
272 | |||
273 | #define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \ | ||
274 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2)) | ||
275 | |||
276 | #define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \ | ||
277 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3)) | ||
278 | |||
279 | #define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE \ | ||
280 | (MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4)) | ||
281 | |||
282 | /** | ||
283 | * | ||
284 | * | ||
285 | * SCU_TASK_CONTEXT_PROTOCOL SCU Task context protocol types this is uesd to | ||
286 | * program the SCU Task context protocol field in word 0x00. | ||
287 | */ | ||
288 | #define SCU_TASK_CONTEXT_PROTOCOL_SMP 0x00 | ||
289 | #define SCU_TASK_CONTEXT_PROTOCOL_SSP 0x01 | ||
290 | #define SCU_TASK_CONTEXT_PROTOCOL_STP 0x02 | ||
291 | #define SCU_TASK_CONTEXT_PROTOCOL_NONE 0x07 | ||
292 | |||
293 | /** | ||
294 | * struct SSP_TASK_CONTEXT - This is the SCU hardware definition for an SSP | ||
295 | * request. | ||
296 | * | ||
297 | * | ||
298 | */ | ||
299 | struct SSP_TASK_CONTEXT { | ||
300 | /* OFFSET 0x18 */ | ||
301 | u32 reserved00:24; | ||
302 | u32 frame_type:8; | ||
303 | |||
304 | /* OFFSET 0x1C */ | ||
305 | u32 reserved01; | ||
306 | |||
307 | /* OFFSET 0x20 */ | ||
308 | u32 fill_bytes:2; | ||
309 | u32 reserved02:6; | ||
310 | u32 changing_data_pointer:1; | ||
311 | u32 retransmit:1; | ||
312 | u32 retry_data_frame:1; | ||
313 | u32 tlr_control:2; | ||
314 | u32 reserved03:19; | ||
315 | |||
316 | /* OFFSET 0x24 */ | ||
317 | u32 uiRsvd4; | ||
318 | |||
319 | /* OFFSET 0x28 */ | ||
320 | u32 target_port_transfer_tag:16; | ||
321 | u32 tag:16; | ||
322 | |||
323 | /* OFFSET 0x2C */ | ||
324 | u32 data_offset; | ||
325 | }; | ||
326 | |||
327 | /** | ||
328 | * struct STP_TASK_CONTEXT - This is the SCU hardware definition for an STP | ||
329 | * request. | ||
330 | * | ||
331 | * | ||
332 | */ | ||
333 | struct STP_TASK_CONTEXT { | ||
334 | /* OFFSET 0x18 */ | ||
335 | u32 fis_type:8; | ||
336 | u32 pm_port:4; | ||
337 | u32 reserved0:3; | ||
338 | u32 control:1; | ||
339 | u32 command:8; | ||
340 | u32 features:8; | ||
341 | |||
342 | /* OFFSET 0x1C */ | ||
343 | u32 reserved1; | ||
344 | |||
345 | /* OFFSET 0x20 */ | ||
346 | u32 reserved2; | ||
347 | |||
348 | /* OFFSET 0x24 */ | ||
349 | u32 reserved3; | ||
350 | |||
351 | /* OFFSET 0x28 */ | ||
352 | u32 ncq_tag:5; | ||
353 | u32 reserved4:27; | ||
354 | |||
355 | /* OFFSET 0x2C */ | ||
356 | u32 data_offset; /* TODO: What is this used for? */ | ||
357 | }; | ||
358 | |||
359 | /** | ||
360 | * struct SMP_TASK_CONTEXT - This is the SCU hardware definition for an SMP | ||
361 | * request. | ||
362 | * | ||
363 | * | ||
364 | */ | ||
365 | struct SMP_TASK_CONTEXT { | ||
366 | /* OFFSET 0x18 */ | ||
367 | u32 response_length:8; | ||
368 | u32 function_result:8; | ||
369 | u32 function:8; | ||
370 | u32 frame_type:8; | ||
371 | |||
372 | /* OFFSET 0x1C */ | ||
373 | u32 smp_response_ufi:12; | ||
374 | u32 reserved1:20; | ||
375 | |||
376 | /* OFFSET 0x20 */ | ||
377 | u32 reserved2; | ||
378 | |||
379 | /* OFFSET 0x24 */ | ||
380 | u32 reserved3; | ||
381 | |||
382 | /* OFFSET 0x28 */ | ||
383 | u32 reserved4; | ||
384 | |||
385 | /* OFFSET 0x2C */ | ||
386 | u32 reserved5; | ||
387 | }; | ||
388 | |||
389 | /** | ||
390 | * struct PRIMITIVE_TASK_CONTEXT - This is the SCU hardware definition used | ||
391 | * when the driver wants to send a primitive on the link. | ||
392 | * | ||
393 | * | ||
394 | */ | ||
395 | struct PRIMITIVE_TASK_CONTEXT { | ||
396 | /* OFFSET 0x18 */ | ||
397 | /** | ||
398 | * This field is the control word and it must be 0. | ||
399 | */ | ||
400 | u32 control; /* /< must be set to 0 */ | ||
401 | |||
402 | /* OFFSET 0x1C */ | ||
403 | /** | ||
404 | * This field specifies the primitive that is to be transmitted. | ||
405 | */ | ||
406 | u32 sequence; | ||
407 | |||
408 | /* OFFSET 0x20 */ | ||
409 | u32 reserved0; | ||
410 | |||
411 | /* OFFSET 0x24 */ | ||
412 | u32 reserved1; | ||
413 | |||
414 | /* OFFSET 0x28 */ | ||
415 | u32 reserved2; | ||
416 | |||
417 | /* OFFSET 0x2C */ | ||
418 | u32 reserved3; | ||
419 | }; | ||
420 | |||
421 | /** | ||
422 | * The union of the protocols that can be selected in the SCU task context | ||
423 | * field. | ||
424 | * | ||
425 | * PROTOCOL_CONTEXT | ||
426 | */ | ||
427 | union PROTOCOL_CONTEXT { | ||
428 | struct SSP_TASK_CONTEXT ssp; | ||
429 | struct STP_TASK_CONTEXT stp; | ||
430 | struct SMP_TASK_CONTEXT smp; | ||
431 | struct PRIMITIVE_TASK_CONTEXT primitive; | ||
432 | u32 words[6]; | ||
433 | }; | ||
434 | |||
435 | /** | ||
436 | * struct scu_sgl_element - This structure represents a single SCU defined SGL | ||
437 | * element. SCU SGLs contain a 64 bit address with the maximum data transfer | ||
438 | * being 24 bits in size. The SGL can not cross a 4GB boundary. | ||
439 | * | ||
440 | * struct scu_sgl_element | ||
441 | */ | ||
442 | struct scu_sgl_element { | ||
443 | /** | ||
444 | * This field is the upper 32 bits of the 64 bit physical address. | ||
445 | */ | ||
446 | u32 address_upper; | ||
447 | |||
448 | /** | ||
449 | * This field is the lower 32 bits of the 64 bit physical address. | ||
450 | */ | ||
451 | u32 address_lower; | ||
452 | |||
453 | /** | ||
454 | * This field is the number of bytes to transfer. | ||
455 | */ | ||
456 | u32 length:24; | ||
457 | |||
458 | /** | ||
459 | * This field is the address modifier to be used when a virtual function is | ||
460 | * requesting a data transfer. | ||
461 | */ | ||
462 | u32 address_modifier:8; | ||
463 | |||
464 | }; | ||
465 | |||
466 | #define SCU_SGL_ELEMENT_PAIR_A 0 | ||
467 | #define SCU_SGL_ELEMENT_PAIR_B 1 | ||
468 | |||
469 | /** | ||
470 | * struct scu_sgl_element_pair - This structure is the SCU hardware definition | ||
471 | * of a pair of SGL elements. The SCU hardware always works on SGL pairs. | ||
472 | * They are refered to in the DS specification as SGL A and SGL B. Each SGL | ||
473 | * pair is followed by the address of the next pair. | ||
474 | * | ||
475 | * | ||
476 | */ | ||
477 | struct scu_sgl_element_pair { | ||
478 | /* OFFSET 0x60-0x68 */ | ||
479 | /** | ||
480 | * This field is the SGL element A of the SGL pair. | ||
481 | */ | ||
482 | struct scu_sgl_element A; | ||
483 | |||
484 | /* OFFSET 0x6C-0x74 */ | ||
485 | /** | ||
486 | * This field is the SGL element B of the SGL pair. | ||
487 | */ | ||
488 | struct scu_sgl_element B; | ||
489 | |||
490 | /* OFFSET 0x78-0x7C */ | ||
491 | /** | ||
492 | * This field is the upper 32 bits of the 64 bit address to the next SGL | ||
493 | * element pair. | ||
494 | */ | ||
495 | u32 next_pair_upper; | ||
496 | |||
497 | /** | ||
498 | * This field is the lower 32 bits of the 64 bit address to the next SGL | ||
499 | * element pair. | ||
500 | */ | ||
501 | u32 next_pair_lower; | ||
502 | |||
503 | }; | ||
504 | |||
505 | /** | ||
506 | * struct TRANSPORT_SNAPSHOT - This structure is the SCU hardware scratch area | ||
507 | * for the task context. This is set to 0 by the driver but can be read by | ||
508 | * issuing a dump TC request to the SCU. | ||
509 | * | ||
510 | * | ||
511 | */ | ||
512 | struct TRANSPORT_SNAPSHOT { | ||
513 | /* OFFSET 0x48 */ | ||
514 | u32 xfer_rdy_write_data_length; | ||
515 | |||
516 | /* OFFSET 0x4C */ | ||
517 | u32 data_offset; | ||
518 | |||
519 | /* OFFSET 0x50 */ | ||
520 | u32 data_transfer_size:24; | ||
521 | u32 reserved_50_0:8; | ||
522 | |||
523 | /* OFFSET 0x54 */ | ||
524 | u32 next_initiator_write_data_offset; | ||
525 | |||
526 | /* OFFSET 0x58 */ | ||
527 | u32 next_initiator_write_data_xfer_size:24; | ||
528 | u32 reserved_58_0:8; | ||
529 | }; | ||
530 | |||
531 | /** | ||
532 | * struct scu_task_context - This structure defines the contents of the SCU | ||
533 | * silicon task context. It lays out all of the fields according to the | ||
534 | * expected order and location for the Storage Controller unit. | ||
535 | * | ||
536 | * | ||
537 | */ | ||
538 | struct scu_task_context { | ||
539 | /* OFFSET 0x00 ------ */ | ||
540 | /** | ||
541 | * This field must be encoded to one of the valid SCU task priority values | ||
542 | * - SCU_TASK_PRIORITY_NORMAL | ||
543 | * - SCU_TASK_PRIORITY_HEAD_OF_Q | ||
544 | * - SCU_TASK_PRIORITY_HIGH | ||
545 | */ | ||
546 | u32 priority:2; | ||
547 | |||
548 | /** | ||
549 | * This field must be set to true if this is an initiator generated request. | ||
550 | * Until target mode is supported all task requests are initiator requests. | ||
551 | */ | ||
552 | u32 initiator_request:1; | ||
553 | |||
554 | /** | ||
555 | * This field must be set to one of the valid connection rates valid values | ||
556 | * are 0x8, 0x9, and 0xA. | ||
557 | */ | ||
558 | u32 connection_rate:4; | ||
559 | |||
560 | /** | ||
561 | * This field muse be programed when generating an SMP response since the SMP | ||
562 | * connection remains open until the SMP response is generated. | ||
563 | */ | ||
564 | u32 protocol_engine_index:3; | ||
565 | |||
566 | /** | ||
567 | * This field must contain the logical port for the task request. | ||
568 | */ | ||
569 | u32 logical_port_index:3; | ||
570 | |||
571 | /** | ||
572 | * This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values | ||
573 | * - SCU_TASK_CONTEXT_PROTOCOL_SMP | ||
574 | * - SCU_TASK_CONTEXT_PROTOCOL_SSP | ||
575 | * - SCU_TASK_CONTEXT_PROTOCOL_STP | ||
576 | * - SCU_TASK_CONTEXT_PROTOCOL_NONE | ||
577 | */ | ||
578 | u32 protocol_type:3; | ||
579 | |||
580 | /** | ||
581 | * This filed must be set to the TCi allocated for this task | ||
582 | */ | ||
583 | u32 task_index:12; | ||
584 | |||
585 | /** | ||
586 | * This field is reserved and must be set to 0x00 | ||
587 | */ | ||
588 | u32 reserved_00_0:1; | ||
589 | |||
590 | /** | ||
591 | * For a normal task request this must be set to 0. If this is an abort of | ||
592 | * this task request it must be set to 1. | ||
593 | */ | ||
594 | u32 abort:1; | ||
595 | |||
596 | /** | ||
597 | * This field must be set to true for the SCU hardware to process the task. | ||
598 | */ | ||
599 | u32 valid:1; | ||
600 | |||
601 | /** | ||
602 | * This field must be set to SCU_TASK_CONTEXT_TYPE | ||
603 | */ | ||
604 | u32 context_type:1; | ||
605 | |||
606 | /* OFFSET 0x04 */ | ||
607 | /** | ||
608 | * This field contains the RNi that is the target of this request. | ||
609 | */ | ||
610 | u32 remote_node_index:12; | ||
611 | |||
612 | /** | ||
613 | * This field is programmed if this is a mirrored request, which we are not | ||
614 | * using, in which case it is the RNi for the mirrored target. | ||
615 | */ | ||
616 | u32 mirrored_node_index:12; | ||
617 | |||
618 | /** | ||
619 | * This field is programmed with the direction of the SATA reqeust | ||
620 | * - SCU_SATA_WRITE_DATA_DIRECTION | ||
621 | * - SCU_SATA_READ_DATA_DIRECTION | ||
622 | */ | ||
623 | u32 sata_direction:1; | ||
624 | |||
625 | /** | ||
626 | * This field is programmsed with one of the following SCU_COMMAND_CODE | ||
627 | * - SCU_COMMAND_CODE_INITIATOR_NEW_TASK | ||
628 | * - SCU_COMMAND_CODE_ACTIVE_TASK | ||
629 | * - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK | ||
630 | * - SCU_COMMAND_CODE_TARGET_RAW_FRAMES | ||
631 | */ | ||
632 | u32 command_code:2; | ||
633 | |||
634 | /** | ||
635 | * This field is set to true if the remote node should be suspended. | ||
636 | * This bit is only valid for SSP & SMP target devices. | ||
637 | */ | ||
638 | u32 suspend_node:1; | ||
639 | |||
640 | /** | ||
641 | * This field is programmed with one of the following command type codes | ||
642 | * | ||
643 | * For SAS requests use the SCU_SSP_TASK_TYPE | ||
644 | * - SCU_TASK_TYPE_IOREAD | ||
645 | * - SCU_TASK_TYPE_IOWRITE | ||
646 | * - SCU_TASK_TYPE_SMP_REQUEST | ||
647 | * - SCU_TASK_TYPE_RESPONSE | ||
648 | * - SCU_TASK_TYPE_RAW_FRAME | ||
649 | * - SCU_TASK_TYPE_PRIMITIVE | ||
650 | * | ||
651 | * For SATA requests use the SCU_SATA_TASK_TYPE | ||
652 | * - SCU_TASK_TYPE_DMA_IN | ||
653 | * - SCU_TASK_TYPE_FPDMAQ_READ | ||
654 | * - SCU_TASK_TYPE_PACKET_DMA_IN | ||
655 | * - SCU_TASK_TYPE_SATA_RAW_FRAME | ||
656 | * - SCU_TASK_TYPE_DMA_OUT | ||
657 | * - SCU_TASK_TYPE_FPDMAQ_WRITE | ||
658 | * - SCU_TASK_TYPE_PACKET_DMA_OUT | ||
659 | */ | ||
660 | u32 task_type:4; | ||
661 | |||
662 | /* OFFSET 0x08 */ | ||
663 | /** | ||
664 | * This field is reserved and the must be set to 0x00 | ||
665 | */ | ||
666 | u32 link_layer_control:8; /* presently all reserved */ | ||
667 | |||
668 | /** | ||
669 | * This field is set to true when TLR is to be enabled | ||
670 | */ | ||
671 | u32 ssp_tlr_enable:1; | ||
672 | |||
673 | /** | ||
674 | * This is field specifies if the SCU DMAs a response frame to host | ||
675 | * memory for good response frames when operating in target mode. | ||
676 | */ | ||
677 | u32 dma_ssp_target_good_response:1; | ||
678 | |||
679 | /** | ||
680 | * This field indicates if the SCU should DMA the response frame to | ||
681 | * host memory. | ||
682 | */ | ||
683 | u32 do_not_dma_ssp_good_response:1; | ||
684 | |||
685 | /** | ||
686 | * This field is set to true when strict ordering is to be enabled | ||
687 | */ | ||
688 | u32 strict_ordering:1; | ||
689 | |||
690 | /** | ||
691 | * This field indicates the type of endianess to be utilized for the | ||
692 | * frame. command, task, and response frames utilized control_frame | ||
693 | * set to 1. | ||
694 | */ | ||
695 | u32 control_frame:1; | ||
696 | |||
697 | /** | ||
698 | * This field is reserved and the driver should set to 0x00 | ||
699 | */ | ||
700 | u32 tl_control_reserved:3; | ||
701 | |||
702 | /** | ||
703 | * This field is set to true when the SCU hardware task timeout control is to | ||
704 | * be enabled | ||
705 | */ | ||
706 | u32 timeout_enable:1; | ||
707 | |||
708 | /** | ||
709 | * This field is reserved and the driver should set it to 0x00 | ||
710 | */ | ||
711 | u32 pts_control_reserved:7; | ||
712 | |||
713 | /** | ||
714 | * This field should be set to true when block guard is to be enabled | ||
715 | */ | ||
716 | u32 block_guard_enable:1; | ||
717 | |||
718 | /** | ||
719 | * This field is reserved and the driver should set to 0x00 | ||
720 | */ | ||
721 | u32 sdma_control_reserved:7; | ||
722 | |||
723 | /* OFFSET 0x0C */ | ||
724 | /** | ||
725 | * This field is the address modifier for this io request it should be | ||
726 | * programmed with the virtual function that is making the request. | ||
727 | */ | ||
728 | u32 address_modifier:16; | ||
729 | |||
730 | /** | ||
731 | * @todo What we support mirrored SMP response frame? | ||
732 | */ | ||
733 | u32 mirrored_protocol_engine:3; /* mirrored protocol Engine Index */ | ||
734 | |||
735 | /** | ||
736 | * If this is a mirrored request the logical port index for the mirrored RNi | ||
737 | * must be programmed. | ||
738 | */ | ||
739 | u32 mirrored_logical_port:4; /* mirrored local port index */ | ||
740 | |||
741 | /** | ||
742 | * This field is reserved and the driver must set it to 0x00 | ||
743 | */ | ||
744 | u32 reserved_0C_0:8; | ||
745 | |||
746 | /** | ||
747 | * This field must be set to true if the mirrored request processing is to be | ||
748 | * enabled. | ||
749 | */ | ||
750 | u32 mirror_request_enable:1; /* Mirrored request Enable */ | ||
751 | |||
752 | /* OFFSET 0x10 */ | ||
753 | /** | ||
754 | * This field is the command iu length in dwords | ||
755 | */ | ||
756 | u32 ssp_command_iu_length:8; | ||
757 | |||
758 | /** | ||
759 | * This is the target TLR enable bit it must be set to 0 when creatning the | ||
760 | * task context. | ||
761 | */ | ||
762 | u32 xfer_ready_tlr_enable:1; | ||
763 | |||
764 | /** | ||
765 | * This field is reserved and the driver must set it to 0x00 | ||
766 | */ | ||
767 | u32 reserved_10_0:7; | ||
768 | |||
769 | /** | ||
770 | * This is the maximum burst size that the SCU hardware will send in one | ||
771 | * connection its value is (N x 512) and N must be a multiple of 2. If the | ||
772 | * value is 0x00 then maximum burst size is disabled. | ||
773 | */ | ||
774 | u32 ssp_max_burst_size:16; | ||
775 | |||
776 | /* OFFSET 0x14 */ | ||
777 | /** | ||
778 | * This filed is set to the number of bytes to be transfered in the request. | ||
779 | */ | ||
780 | u32 transfer_length_bytes:24; /* In terms of bytes */ | ||
781 | |||
782 | /** | ||
783 | * This field is reserved and the driver should set it to 0x00 | ||
784 | */ | ||
785 | u32 reserved_14_0:8; | ||
786 | |||
787 | /* OFFSET 0x18-0x2C */ | ||
788 | /** | ||
789 | * This union provides for the protocol specif part of the SCU Task Context. | ||
790 | */ | ||
791 | union PROTOCOL_CONTEXT type; | ||
792 | |||
793 | /* OFFSET 0x30-0x34 */ | ||
794 | /** | ||
795 | * This field is the upper 32 bits of the 64 bit physical address of the | ||
796 | * command iu buffer | ||
797 | */ | ||
798 | u32 command_iu_upper; | ||
799 | |||
800 | /** | ||
801 | * This field is the lower 32 bits of the 64 bit physical address of the | ||
802 | * command iu buffer | ||
803 | */ | ||
804 | u32 command_iu_lower; | ||
805 | |||
806 | /* OFFSET 0x38-0x3C */ | ||
807 | /** | ||
808 | * This field is the upper 32 bits of the 64 bit physical address of the | ||
809 | * response iu buffer | ||
810 | */ | ||
811 | u32 response_iu_upper; | ||
812 | |||
813 | /** | ||
814 | * This field is the lower 32 bits of the 64 bit physical address of the | ||
815 | * response iu buffer | ||
816 | */ | ||
817 | u32 response_iu_lower; | ||
818 | |||
819 | /* OFFSET 0x40 */ | ||
820 | /** | ||
821 | * This field is set to the task phase of the SCU hardware. The driver must | ||
822 | * set this to 0x01 | ||
823 | */ | ||
824 | u32 task_phase:8; | ||
825 | |||
826 | /** | ||
827 | * This field is set to the transport layer task status. The driver must set | ||
828 | * this to 0x00 | ||
829 | */ | ||
830 | u32 task_status:8; | ||
831 | |||
832 | /** | ||
833 | * This field is used during initiator write TLR | ||
834 | */ | ||
835 | u32 previous_extended_tag:4; | ||
836 | |||
837 | /** | ||
838 | * This field is set the maximum number of retries for a STP non-data FIS | ||
839 | */ | ||
840 | u32 stp_retry_count:2; | ||
841 | |||
842 | /** | ||
843 | * This field is reserved and the driver must set it to 0x00 | ||
844 | */ | ||
845 | u32 reserved_40_1:2; | ||
846 | |||
847 | /** | ||
848 | * This field is used by the SCU TL to determine when to take a snapshot when | ||
849 | * tranmitting read data frames. | ||
850 | * - 0x00 The entire IO | ||
851 | * - 0x01 32k | ||
852 | * - 0x02 64k | ||
853 | * - 0x04 128k | ||
854 | * - 0x08 256k | ||
855 | */ | ||
856 | u32 ssp_tlr_threshold:4; | ||
857 | |||
858 | /** | ||
859 | * This field is reserved and the driver must set it to 0x00 | ||
860 | */ | ||
861 | u32 reserved_40_2:4; | ||
862 | |||
863 | /* OFFSET 0x44 */ | ||
864 | u32 write_data_length; /* read only set to 0 */ | ||
865 | |||
866 | /* OFFSET 0x48-0x58 */ | ||
867 | struct TRANSPORT_SNAPSHOT snapshot; /* read only set to 0 */ | ||
868 | |||
869 | /* OFFSET 0x5C */ | ||
870 | u32 block_protection_enable:1; | ||
871 | u32 block_size:2; | ||
872 | u32 block_protection_function:2; | ||
873 | u32 reserved_5C_0:9; | ||
874 | u32 active_sgl_element:2; /* read only set to 0 */ | ||
875 | u32 sgl_exhausted:1; /* read only set to 0 */ | ||
876 | u32 payload_data_transfer_error:4; /* read only set to 0 */ | ||
877 | u32 frame_buffer_offset:11; /* read only set to 0 */ | ||
878 | |||
879 | /* OFFSET 0x60-0x7C */ | ||
880 | /** | ||
881 | * This field is the first SGL element pair found in the TC data structure. | ||
882 | */ | ||
883 | struct scu_sgl_element_pair sgl_pair_ab; | ||
884 | /* OFFSET 0x80-0x9C */ | ||
885 | /** | ||
886 | * This field is the second SGL element pair found in the TC data structure. | ||
887 | */ | ||
888 | struct scu_sgl_element_pair sgl_pair_cd; | ||
889 | |||
890 | /* OFFSET 0xA0-BC */ | ||
891 | struct scu_sgl_element_pair sgl_snapshot_ac; | ||
892 | |||
893 | /* OFFSET 0xC0 */ | ||
894 | u32 active_sgl_element_pair; /* read only set to 0 */ | ||
895 | |||
896 | /* OFFSET 0xC4-0xCC */ | ||
897 | u32 reserved_C4_CC[3]; | ||
898 | |||
899 | /* OFFSET 0xD0 */ | ||
900 | u32 intermediate_crc_value:16; | ||
901 | u32 initial_crc_seed:16; | ||
902 | |||
903 | /* OFFSET 0xD4 */ | ||
904 | u32 application_tag_for_verify:16; | ||
905 | u32 application_tag_for_generate:16; | ||
906 | |||
907 | /* OFFSET 0xD8 */ | ||
908 | u32 reference_tag_seed_for_verify_function; | ||
909 | |||
910 | /* OFFSET 0xDC */ | ||
911 | u32 reserved_DC; | ||
912 | |||
913 | /* OFFSET 0xE0 */ | ||
914 | u32 reserved_E0_0:16; | ||
915 | u32 application_tag_mask_for_generate:16; | ||
916 | |||
917 | /* OFFSET 0xE4 */ | ||
918 | u32 block_protection_control:16; | ||
919 | u32 application_tag_mask_for_verify:16; | ||
920 | |||
921 | /* OFFSET 0xE8 */ | ||
922 | u32 block_protection_error:8; | ||
923 | u32 reserved_E8_0:24; | ||
924 | |||
925 | /* OFFSET 0xEC */ | ||
926 | u32 reference_tag_seed_for_verify; | ||
927 | |||
928 | /* OFFSET 0xF0 */ | ||
929 | u32 intermediate_crc_valid_snapshot:16; | ||
930 | u32 reserved_F0_0:16; | ||
931 | |||
932 | /* OFFSET 0xF4 */ | ||
933 | u32 reference_tag_seed_for_verify_function_snapshot; | ||
934 | |||
935 | /* OFFSET 0xF8 */ | ||
936 | u32 snapshot_of_reserved_dword_DC_of_tc; | ||
937 | |||
938 | /* OFFSET 0xFC */ | ||
939 | u32 reference_tag_seed_for_generate_function_snapshot; | ||
940 | |||
941 | }; | ||
942 | |||
943 | #endif /* _SCU_TASK_CONTEXT_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scu_unsolicited_frame.h b/drivers/scsi/isci/core/scu_unsolicited_frame.h new file mode 100644 index 000000000000..590ea02745fd --- /dev/null +++ b/drivers/scsi/isci/core/scu_unsolicited_frame.h | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This field defines the SCU format of an unsolicited frame (UF). A UF is a | ||
58 | * frame received by the SCU for which there is no known corresponding task | ||
59 | * context (TC). | ||
60 | * | ||
61 | * | ||
62 | */ | ||
63 | |||
64 | #ifndef _SCU_UNSOLICITED_FRAME_H_ | ||
65 | #define _SCU_UNSOLICITED_FRAME_H_ | ||
66 | |||
67 | #include "sci_types.h" | ||
68 | |||
69 | /** | ||
70 | * | ||
71 | * | ||
72 | * This constant defines the number of DWORDS found the unsolicited frame | ||
73 | * header data member. | ||
74 | */ | ||
75 | #define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15 | ||
76 | |||
77 | /** | ||
78 | * struct scu_unsolicited_frame_header - | ||
79 | * | ||
80 | * This structure delineates the format of an unsolicited frame header. The | ||
81 | * first DWORD are UF attributes defined by the silicon architecture. The data | ||
82 | * depicts actual header information received on the link. | ||
83 | */ | ||
84 | struct scu_unsolicited_frame_header { | ||
85 | /** | ||
86 | * This field indicates if there is an Initiator Index Table entry with | ||
87 | * which this header is associated. | ||
88 | */ | ||
89 | u32 iit_exists:1; | ||
90 | |||
91 | /** | ||
92 | * This field simply indicates the protocol type (i.e. SSP, STP, SMP). | ||
93 | */ | ||
94 | u32 protocol_type:3; | ||
95 | |||
96 | /** | ||
97 | * This field indicates if the frame is an address frame (IAF or OAF) | ||
98 | * or if it is a information unit frame. | ||
99 | */ | ||
100 | u32 is_address_frame:1; | ||
101 | |||
102 | /** | ||
103 | * This field simply indicates the connection rate at which the frame | ||
104 | * was received. | ||
105 | */ | ||
106 | u32 connection_rate:4; | ||
107 | |||
108 | u32 reserved:23; | ||
109 | |||
110 | /** | ||
111 | * This field represents the actual header data received on the link. | ||
112 | */ | ||
113 | u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS]; | ||
114 | |||
115 | }; | ||
116 | |||
117 | #endif /* _SCU_UNSOLICITED_FRAME_H_ */ | ||
diff --git a/drivers/scsi/isci/core/scu_viit_data.h b/drivers/scsi/isci/core/scu_viit_data.h new file mode 100644 index 000000000000..4601d1962ca3 --- /dev/null +++ b/drivers/scsi/isci/core/scu_viit_data.h | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCU_VIIT_DATA_HEADER_ | ||
57 | #define _SCU_VIIT_DATA_HEADER_ | ||
58 | |||
59 | /** | ||
60 | * This file contains the constants and structures for the SCU hardware VIIT | ||
61 | * table entries. | ||
62 | * | ||
63 | * | ||
64 | */ | ||
65 | |||
66 | #include "sci_types.h" | ||
67 | |||
68 | #define SCU_VIIT_ENTRY_ID_MASK (0xC0000000) | ||
69 | #define SCU_VIIT_ENTRY_ID_SHIFT (30) | ||
70 | |||
71 | #define SCU_VIIT_ENTRY_FUNCTION_MASK (0x0FF00000) | ||
72 | #define SCU_VIIT_ENTRY_FUNCTION_SHIFT (20) | ||
73 | |||
74 | #define SCU_VIIT_ENTRY_IPPTMODE_MASK (0x0001F800) | ||
75 | #define SCU_VIIT_ENTRY_IPPTMODE_SHIFT (12) | ||
76 | |||
77 | #define SCU_VIIT_ENTRY_LPVIE_MASK (0x00000F00) | ||
78 | #define SCU_VIIT_ENTRY_LPVIE_SHIFT (8) | ||
79 | |||
80 | #define SCU_VIIT_ENTRY_STATUS_MASK (0x000000FF) | ||
81 | #define SCU_VIIT_ENTRY_STATUS_SHIFT (0) | ||
82 | |||
83 | #define SCU_VIIT_ENTRY_ID_INVALID (0 << SCU_VIIT_ENTRY_ID_SHIFT) | ||
84 | #define SCU_VIIT_ENTRY_ID_VIIT (1 << SCU_VIIT_ENTRY_ID_SHIFT) | ||
85 | #define SCU_VIIT_ENTRY_ID_IIT (2 << SCU_VIIT_ENTRY_ID_SHIFT) | ||
86 | #define SCU_VIIT_ENTRY_ID_VIRT_EXP (3 << SCU_VIIT_ENTRY_ID_SHIFT) | ||
87 | |||
88 | #define SCU_VIIT_IPPT_SSP_INITIATOR (0x01 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) | ||
89 | #define SCU_VIIT_IPPT_SMP_INITIATOR (0x02 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) | ||
90 | #define SCU_VIIT_IPPT_STP_INITIATOR (0x04 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) | ||
91 | #define SCU_VIIT_IPPT_INITIATOR \ | ||
92 | (\ | ||
93 | SCU_VIIT_IPPT_SSP_INITIATOR \ | ||
94 | | SCU_VIIT_IPPT_SMP_INITIATOR \ | ||
95 | | SCU_VIIT_IPPT_STP_INITIATOR \ | ||
96 | ) | ||
97 | |||
98 | #define SCU_VIIT_STATUS_RNC_VALID (0x01 << SCU_VIIT_ENTRY_STATUS_SHIFT) | ||
99 | #define SCU_VIIT_STATUS_ADDRESS_VALID (0x02 << SCU_VIIT_ENTRY_STATUS_SHIFT) | ||
100 | #define SCU_VIIT_STATUS_RNI_VALID (0x04 << SCU_VIIT_ENTRY_STATUS_SHIFT) | ||
101 | #define SCU_VIIT_STATUS_ALL_VALID \ | ||
102 | (\ | ||
103 | SCU_VIIT_STATUS_RNC_VALID \ | ||
104 | | SCU_VIIT_STATUS_ADDRESS_VALID \ | ||
105 | | SCU_VIIT_STATUS_RNI_VALID \ | ||
106 | ) | ||
107 | |||
108 | #define SCU_VIIT_IPPT_SMP_TARGET (0x10 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT) | ||
109 | |||
110 | /** | ||
111 | * struct scu_viit_entry - This is the SCU Virtual Initiator Table Entry | ||
112 | * | ||
113 | * | ||
114 | */ | ||
115 | struct scu_viit_entry { | ||
116 | /** | ||
117 | * This must be encoded as to the type of initiator that is being constructed | ||
118 | * for this port. | ||
119 | */ | ||
120 | u32 status; | ||
121 | |||
122 | /** | ||
123 | * Virtual initiator high SAS Address | ||
124 | */ | ||
125 | u32 initiator_sas_address_hi; | ||
126 | |||
127 | /** | ||
128 | * Virtual initiator low SAS Address | ||
129 | */ | ||
130 | u32 initiator_sas_address_lo; | ||
131 | |||
132 | /** | ||
133 | * This must be 0 | ||
134 | */ | ||
135 | u32 reserved; | ||
136 | |||
137 | }; | ||
138 | |||
139 | |||
140 | /* IIT Status Defines */ | ||
141 | #define SCU_IIT_ENTRY_ID_MASK (0xC0000000) | ||
142 | #define SCU_IIT_ENTRY_ID_SHIFT (30) | ||
143 | |||
144 | #define SCU_IIT_ENTRY_STATUS_UPDATE_MASK (0x20000000) | ||
145 | #define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT (29) | ||
146 | |||
147 | #define SCU_IIT_ENTRY_LPI_MASK (0x00000F00) | ||
148 | #define SCU_IIT_ENTRY_LPI_SHIFT (8) | ||
149 | |||
150 | #define SCU_IIT_ENTRY_STATUS_MASK (0x000000FF) | ||
151 | #define SCU_IIT_ENTRY_STATUS_SHIFT (0) | ||
152 | |||
153 | /* IIT Remote Initiator Defines */ | ||
154 | #define SCU_IIT_ENTRY_REMOTE_TAG_MASK (0x0000FFFF) | ||
155 | #define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0) | ||
156 | |||
157 | #define SCU_IIT_ENTRY_REMOTE_RNC_MASK (0x0FFF0000) | ||
158 | #define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16) | ||
159 | |||
160 | #define SCU_IIT_ENTRY_ID_INVALID (0 << SCU_IIT_ENTRY_ID_SHIFT) | ||
161 | #define SCU_IIT_ENTRY_ID_VIIT (1 << SCU_IIT_ENTRY_ID_SHIFT) | ||
162 | #define SCU_IIT_ENTRY_ID_IIT (2 << SCU_IIT_ENTRY_ID_SHIFT) | ||
163 | #define SCU_IIT_ENTRY_ID_VIRT_EXP (3 << SCU_IIT_ENTRY_ID_SHIFT) | ||
164 | |||
165 | /** | ||
166 | * struct scu_iit_entry - This will be implemented later when we support | ||
167 | * virtual functions | ||
168 | * | ||
169 | * | ||
170 | */ | ||
171 | struct scu_iit_entry { | ||
172 | u32 status; | ||
173 | u32 remote_initiator_sas_address_hi; | ||
174 | u32 remote_initiator_sas_address_lo; | ||
175 | u32 remote_initiator; | ||
176 | |||
177 | }; | ||
178 | |||
179 | #endif /* _SCU_VIIT_DATA_HEADER_ */ | ||
diff --git a/drivers/scsi/isci/deprecated.c b/drivers/scsi/isci/deprecated.c new file mode 100644 index 000000000000..847e6874e1a8 --- /dev/null +++ b/drivers/scsi/isci/deprecated.c | |||
@@ -0,0 +1,491 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | |||
57 | /** | ||
58 | * This file contains isci module object implementation. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #include "isci.h" | ||
64 | #include "request.h" | ||
65 | #include "sata.h" | ||
66 | #include "task.h" | ||
67 | |||
68 | |||
69 | /** | ||
70 | * scic_cb_stall_execution() - This method is called when the core requires the | ||
71 | * OS driver to stall execution. This method is utilized during | ||
72 | * initialization or non-performance paths only. | ||
73 | * @microseconds: This parameter specifies the number of microseconds for which | ||
74 | * to stall. The operating system driver is allowed to round this value up | ||
75 | * where necessary. | ||
76 | * | ||
77 | * none. | ||
78 | */ | ||
79 | void scic_cb_stall_execution( | ||
80 | u32 microseconds) | ||
81 | { | ||
82 | udelay(microseconds); | ||
83 | } | ||
84 | |||
85 | |||
86 | /** | ||
87 | * scic_cb_io_request_get_physical_address() - This callback method asks the | ||
88 | * user to provide the physical address for the supplied virtual address | ||
89 | * when building an io request object. | ||
90 | * @controller: This parameter is the core controller object handle. | ||
91 | * @io_request: This parameter is the io request object handle for which the | ||
92 | * physical address is being requested. | ||
93 | * | ||
94 | * | ||
95 | */ | ||
96 | void scic_cb_io_request_get_physical_address( | ||
97 | struct scic_sds_controller *controller, | ||
98 | struct scic_sds_request *io_request, | ||
99 | void *virtual_address, | ||
100 | dma_addr_t *physical_address) | ||
101 | { | ||
102 | struct isci_request *request = | ||
103 | (struct isci_request *)sci_object_get_association(io_request); | ||
104 | |||
105 | char *requested_address = (char *)virtual_address; | ||
106 | char *base_address = (char *)request; | ||
107 | |||
108 | BUG_ON(requested_address < base_address); | ||
109 | BUG_ON((requested_address - base_address) >= | ||
110 | request->request_alloc_size); | ||
111 | |||
112 | *physical_address = request->request_daddr + | ||
113 | (requested_address - base_address); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * scic_cb_io_request_get_transfer_length() - This callback method asks the | ||
118 | * user to provide the number of bytes to be transfered as part of this | ||
119 | * request. | ||
120 | * @scic_user_io_request: This parameter points to the user's IO request | ||
121 | * object. It is a cookie that allows the user to provide the necessary | ||
122 | * information for this callback. | ||
123 | * | ||
124 | * This method returns the number of payload data bytes to be transfered for | ||
125 | * this IO request. | ||
126 | */ | ||
127 | u32 scic_cb_io_request_get_transfer_length( | ||
128 | void *scic_user_io_request) | ||
129 | { | ||
130 | return isci_request_io_request_get_transfer_length( | ||
131 | scic_user_io_request | ||
132 | ); | ||
133 | } | ||
134 | |||
135 | |||
136 | /** | ||
137 | * scic_cb_io_request_get_data_direction() - This callback method asks the user | ||
138 | * to provide the data direction for this request. | ||
139 | * @scic_user_io_request: This parameter points to the user's IO request | ||
140 | * object. It is a cookie that allows the user to provide the necessary | ||
141 | * information for this callback. | ||
142 | * | ||
143 | * This method returns the value of SCI_IO_REQUEST_DATA_OUT or | ||
144 | * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA. | ||
145 | */ | ||
146 | SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction( | ||
147 | void *scic_user_io_request) | ||
148 | { | ||
149 | return isci_request_io_request_get_data_direction( | ||
150 | scic_user_io_request | ||
151 | ); | ||
152 | } | ||
153 | |||
154 | |||
155 | /** | ||
156 | * scic_cb_io_request_get_next_sge() - This callback method asks the user to | ||
157 | * provide the address to where the next Scatter-Gather Element is located. | ||
158 | * @scic_user_io_request: This parameter points to the user's IO request | ||
159 | * object. It is a cookie that allows the user to provide the necessary | ||
160 | * information for this callback. | ||
161 | * @current_sge_address: This parameter specifies the address for the current | ||
162 | * SGE (i.e. the one that has just processed). | ||
163 | * | ||
164 | * An address specifying the location for the next scatter gather element to be | ||
165 | * processed. | ||
166 | */ | ||
167 | void scic_cb_io_request_get_next_sge( | ||
168 | void *scic_user_io_request, | ||
169 | void *current_sge_address, | ||
170 | void **next_sge) | ||
171 | { | ||
172 | *next_sge = isci_request_io_request_get_next_sge( | ||
173 | scic_user_io_request, | ||
174 | current_sge_address | ||
175 | ); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * scic_cb_sge_get_address_field() - This callback method asks the user to | ||
180 | * provide the contents of the "address" field in the Scatter-Gather Element. | ||
181 | * @scic_user_io_request: This parameter points to the user's IO request | ||
182 | * object. It is a cookie that allows the user to provide the necessary | ||
183 | * information for this callback. | ||
184 | * @sge_address: This parameter specifies the address for the SGE from which to | ||
185 | * retrieve the address field. | ||
186 | * | ||
187 | * A physical address specifying the contents of the SGE's address field. | ||
188 | */ | ||
189 | dma_addr_t scic_cb_sge_get_address_field( | ||
190 | void *scic_user_io_request, | ||
191 | void *sge_address) | ||
192 | { | ||
193 | return isci_request_sge_get_address_field( | ||
194 | scic_user_io_request, | ||
195 | sge_address | ||
196 | ); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * scic_cb_sge_get_length_field() - This callback method asks the user to | ||
201 | * provide the contents of the "length" field in the Scatter-Gather Element. | ||
202 | * @scic_user_io_request: This parameter points to the user's IO request | ||
203 | * object. It is a cookie that allows the user to provide the necessary | ||
204 | * information for this callback. | ||
205 | * @sge_address: This parameter specifies the address for the SGE from which to | ||
206 | * retrieve the address field. | ||
207 | * | ||
208 | * This method returns the length field specified inside the SGE referenced by | ||
209 | * the sge_address parameter. | ||
210 | */ | ||
211 | u32 scic_cb_sge_get_length_field( | ||
212 | void *scic_user_io_request, | ||
213 | void *sge_address) | ||
214 | { | ||
215 | return isci_request_sge_get_length_field( | ||
216 | scic_user_io_request, | ||
217 | sge_address | ||
218 | ); | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the | ||
223 | * user to provide the address for the command descriptor block (CDB) | ||
224 | * associated with this IO request. | ||
225 | * @scic_user_io_request: This parameter points to the user's IO request | ||
226 | * object. It is a cookie that allows the user to provide the necessary | ||
227 | * information for this callback. | ||
228 | * | ||
229 | * This method returns the virtual address of the CDB. | ||
230 | */ | ||
231 | void *scic_cb_ssp_io_request_get_cdb_address( | ||
232 | void *scic_user_io_request) | ||
233 | { | ||
234 | return isci_request_ssp_io_request_get_cdb_address( | ||
235 | scic_user_io_request | ||
236 | ); | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user | ||
241 | * to provide the length of the command descriptor block (CDB) associated | ||
242 | * with this IO request. | ||
243 | * @scic_user_io_request: This parameter points to the user's IO request | ||
244 | * object. It is a cookie that allows the user to provide the necessary | ||
245 | * information for this callback. | ||
246 | * | ||
247 | * This method returns the length of the CDB. | ||
248 | */ | ||
249 | u32 scic_cb_ssp_io_request_get_cdb_length( | ||
250 | void *scic_user_io_request) | ||
251 | { | ||
252 | return isci_request_ssp_io_request_get_cdb_length( | ||
253 | scic_user_io_request | ||
254 | ); | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * scic_cb_ssp_io_request_get_lun() - This callback method asks the user to | ||
259 | * provide the Logical Unit (LUN) associated with this IO request. | ||
260 | * @scic_user_io_request: This parameter points to the user's IO request | ||
261 | * object. It is a cookie that allows the user to provide the necessary | ||
262 | * information for this callback. | ||
263 | * | ||
264 | * This method returns the LUN associated with this request. This should be u64? | ||
265 | */ | ||
266 | u32 scic_cb_ssp_io_request_get_lun( | ||
267 | void *scic_user_io_request) | ||
268 | { | ||
269 | return isci_request_ssp_io_request_get_lun(scic_user_io_request); | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the | ||
274 | * user to provide the task attribute associated with this IO request. | ||
275 | * @scic_user_io_request: This parameter points to the user's IO request | ||
276 | * object. It is a cookie that allows the user to provide the necessary | ||
277 | * information for this callback. | ||
278 | * | ||
279 | * This method returns the task attribute associated with this IO request. | ||
280 | */ | ||
281 | u32 scic_cb_ssp_io_request_get_task_attribute( | ||
282 | void *scic_user_io_request) | ||
283 | { | ||
284 | return isci_request_ssp_io_request_get_task_attribute( | ||
285 | scic_user_io_request | ||
286 | ); | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * scic_cb_ssp_io_request_get_command_priority() - This callback method asks | ||
291 | * the user to provide the command priority associated with this IO request. | ||
292 | * @scic_user_io_request: This parameter points to the user's IO request | ||
293 | * object. It is a cookie that allows the user to provide the necessary | ||
294 | * information for this callback. | ||
295 | * | ||
296 | * This method returns the command priority associated with this IO request. | ||
297 | */ | ||
298 | u32 scic_cb_ssp_io_request_get_command_priority( | ||
299 | void *scic_user_io_request) | ||
300 | { | ||
301 | return isci_request_ssp_io_request_get_command_priority( | ||
302 | scic_user_io_request | ||
303 | ); | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to | ||
308 | * be utilized for this task management request. | ||
309 | * @scic_user_task_request: This parameter points to the user's task request | ||
310 | * object. It is a cookie that allows the user to provide the necessary | ||
311 | * information for this callback. | ||
312 | * | ||
313 | * This method returns the LUN associated with this request. This should be u64? | ||
314 | */ | ||
315 | u32 scic_cb_ssp_task_request_get_lun( | ||
316 | void *scic_user_task_request) | ||
317 | { | ||
318 | return isci_task_ssp_request_get_lun( | ||
319 | (struct isci_request *)scic_user_task_request | ||
320 | ); | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * scic_cb_ssp_task_request_get_function() - This method returns the task | ||
325 | * management function to be utilized for this task request. | ||
326 | * @scic_user_task_request: This parameter points to the user's task request | ||
327 | * object. It is a cookie that allows the user to provide the necessary | ||
328 | * information for this callback. | ||
329 | * | ||
330 | * This method returns an unsigned byte representing the task management | ||
331 | * function to be performed. | ||
332 | */ | ||
333 | u8 scic_cb_ssp_task_request_get_function( | ||
334 | void *scic_user_task_request) | ||
335 | { | ||
336 | return isci_task_ssp_request_get_function( | ||
337 | (struct isci_request *)scic_user_task_request | ||
338 | ); | ||
339 | } | ||
340 | |||
341 | /** | ||
342 | * scic_cb_ssp_task_request_get_io_tag_to_manage() - This method returns the | ||
343 | * task management IO tag to be managed. Depending upon the task management | ||
344 | * function the value returned from this method may be ignored. | ||
345 | * @scic_user_task_request: This parameter points to the user's task request | ||
346 | * object. It is a cookie that allows the user to provide the necessary | ||
347 | * information for this callback. | ||
348 | * | ||
349 | * This method returns an unsigned 16-bit word depicting the IO tag to be | ||
350 | * managed. | ||
351 | */ | ||
352 | u16 scic_cb_ssp_task_request_get_io_tag_to_manage( | ||
353 | void *scic_user_task_request) | ||
354 | { | ||
355 | return isci_task_ssp_request_get_io_tag_to_manage( | ||
356 | (struct isci_request *)scic_user_task_request | ||
357 | ); | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * scic_cb_ssp_task_request_get_response_data_address() - This callback method | ||
362 | * asks the user to provide the virtual address of the response data buffer | ||
363 | * for the supplied IO request. | ||
364 | * @scic_user_task_request: This parameter points to the user's task request | ||
365 | * object. It is a cookie that allows the user to provide the necessary | ||
366 | * information for this callback. | ||
367 | * | ||
368 | * This method returns the virtual address for the response data buffer | ||
369 | * associated with this IO request. | ||
370 | */ | ||
371 | void *scic_cb_ssp_task_request_get_response_data_address( | ||
372 | void *scic_user_task_request) | ||
373 | { | ||
374 | return isci_task_ssp_request_get_response_data_address( | ||
375 | (struct isci_request *)scic_user_task_request | ||
376 | ); | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * scic_cb_ssp_task_request_get_response_data_length() - This callback method | ||
381 | * asks the user to provide the length of the response data buffer for the | ||
382 | * supplied IO request. | ||
383 | * @scic_user_task_request: This parameter points to the user's task request | ||
384 | * object. It is a cookie that allows the user to provide the necessary | ||
385 | * information for this callback. | ||
386 | * | ||
387 | * This method returns the length of the response buffer data associated with | ||
388 | * this IO request. | ||
389 | */ | ||
390 | u32 scic_cb_ssp_task_request_get_response_data_length( | ||
391 | void *scic_user_task_request) | ||
392 | { | ||
393 | return isci_task_ssp_request_get_response_data_length( | ||
394 | (struct isci_request *)scic_user_task_request | ||
395 | ); | ||
396 | } | ||
397 | |||
398 | #if !defined(DISABLE_ATAPI) | ||
399 | /** | ||
400 | * scic_cb_stp_packet_io_request_get_cdb_address() - This user callback asks | ||
401 | * the user to provide stp packet io's the CDB address. | ||
402 | * @scic_user_io_request: | ||
403 | * | ||
404 | * The packet IO's cdb adress. | ||
405 | */ | ||
406 | void *scic_cb_stp_packet_io_request_get_cdb_address( | ||
407 | void *scic_user_io_request) | ||
408 | { | ||
409 | return isci_request_stp_packet_io_request_get_cdb_address( | ||
410 | scic_user_io_request | ||
411 | ); | ||
412 | } | ||
413 | |||
414 | |||
415 | /** | ||
416 | * scic_cb_stp_packet_io_request_get_cdb_length() - This user callback asks the | ||
417 | * user to provide stp packet io's the CDB length. | ||
418 | * @scic_user_io_request: | ||
419 | * | ||
420 | * The packet IO's cdb length. | ||
421 | */ | ||
422 | u32 scic_cb_stp_packet_io_request_get_cdb_length( | ||
423 | void *scic_user_io_request) | ||
424 | { | ||
425 | return isci_request_stp_packet_io_request_get_cdb_length( | ||
426 | scic_user_io_request | ||
427 | ); | ||
428 | } | ||
429 | #endif /* #if !defined(DISABLE_ATAPI) */ | ||
430 | |||
431 | |||
432 | /** | ||
433 | * scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user | ||
434 | * if the received RX frame data is to be copied to the SGL or should be | ||
435 | * stored by the SCI core to be retrieved later with the | ||
436 | * scic_io_request_get_rx_frame(). | ||
437 | * @scic_user_io_request: This parameter points to the user's IO request | ||
438 | * object. It is a cookie that allows the user to provide the necessary | ||
439 | * information for this callback. | ||
440 | * | ||
441 | * This method returns true if the SCI core should copy the received frame data | ||
442 | * to the SGL location or false if the SCI user wants to retrieve the frame | ||
443 | * data at a later time. | ||
444 | */ | ||
445 | bool scic_cb_io_request_do_copy_rx_frames( | ||
446 | void *scic_user_io_request) | ||
447 | { | ||
448 | struct sas_task *task | ||
449 | = isci_request_access_task( | ||
450 | (struct isci_request *)scic_user_io_request | ||
451 | ); | ||
452 | |||
453 | return (task->data_dir == DMA_NONE) ? false : true; | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * scic_cb_get_virtual_address() - This callback method asks the user to | ||
458 | * provide the virtual address for the supplied physical address. | ||
459 | * @controller: This parameter is the core controller object handle. | ||
460 | * @physical_address: This parameter is the physical address which is to be | ||
461 | * returned as a virtual address. | ||
462 | * | ||
463 | * The method returns the virtual address for the supplied physical address. | ||
464 | */ | ||
465 | void *scic_cb_get_virtual_address( | ||
466 | struct scic_sds_controller *controller, | ||
467 | dma_addr_t physical_address) | ||
468 | { | ||
469 | void *virt_addr = (void *)phys_to_virt(physical_address); | ||
470 | |||
471 | return virt_addr; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * scic_cb_request_get_sat_protocol() - This callback method asks the user to | ||
476 | * return the SAT protocol definition for this IO request. This method is | ||
477 | * only called by the SCI core if the request type constructed is SATA. | ||
478 | * @scic_user_io_request: This parameter points to the user's IO request | ||
479 | * object. It is a cookie that allows the user to provide the necessary | ||
480 | * information for this callback. | ||
481 | * | ||
482 | * This method returns one of the sat.h defined protocols for the given io | ||
483 | * request. | ||
484 | */ | ||
485 | u8 scic_cb_request_get_sat_protocol( | ||
486 | void *scic_user_io_request) | ||
487 | { | ||
488 | return isci_sata_get_sat_protocol( | ||
489 | (struct isci_request *)scic_user_io_request | ||
490 | ); | ||
491 | } | ||
diff --git a/drivers/scsi/isci/events.c b/drivers/scsi/isci/events.c new file mode 100644 index 000000000000..75f9cd551278 --- /dev/null +++ b/drivers/scsi/isci/events.c | |||
@@ -0,0 +1,619 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | |||
57 | /** | ||
58 | * This file contains isci module object implementation. | ||
59 | * | ||
60 | * | ||
61 | */ | ||
62 | |||
63 | #include "isci.h" | ||
64 | #include "request.h" | ||
65 | #include "sata.h" | ||
66 | #include "task.h" | ||
67 | |||
68 | /** | ||
69 | * scic_cb_timer_create() - This callback method asks the user to create a | ||
70 | * timer and provide a handle for this timer for use in further timer | ||
71 | * interactions. The appropriate isci timer object function is called to | ||
72 | * create a timer object. | ||
73 | * @timer_callback: This parameter specifies the callback method to be invoked | ||
74 | * whenever the timer expires. | ||
75 | * @controller: This parameter specifies the controller with which this timer | ||
76 | * is to be associated. | ||
77 | * @cookie: This parameter specifies a piece of information that the user must | ||
78 | * retain. This cookie is to be supplied by the user anytime a timeout | ||
79 | * occurs for the created timer. | ||
80 | * | ||
81 | * This method returns a handle to a timer object created by the user. The | ||
82 | * handle will be utilized for all further interactions relating to this timer. | ||
83 | */ | ||
84 | void *scic_cb_timer_create( | ||
85 | struct scic_sds_controller *controller, | ||
86 | void (*timer_callback)(void *), | ||
87 | void *cookie) | ||
88 | { | ||
89 | struct isci_host *isci_host; | ||
90 | struct isci_timer *timer = NULL; | ||
91 | |||
92 | isci_host = (struct isci_host *)sci_object_get_association(controller); | ||
93 | |||
94 | dev_dbg(&isci_host->pdev->dev, | ||
95 | "%s: isci_host = %p", | ||
96 | __func__, isci_host); | ||
97 | |||
98 | timer = isci_timer_create(&isci_host->timer_list_struct, | ||
99 | isci_host, | ||
100 | cookie, | ||
101 | timer_callback); | ||
102 | |||
103 | dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer); | ||
104 | |||
105 | return (void *)timer; | ||
106 | } | ||
107 | |||
108 | |||
109 | /** | ||
110 | * scic_cb_timer_start() - This callback method asks the user to start the | ||
111 | * supplied timer. The appropriate isci timer object function is called to | ||
112 | * start the timer. | ||
113 | * @controller: This parameter specifies the controller with which this timer | ||
114 | * is to associated. | ||
115 | * @timer: This parameter specifies the timer to be started. | ||
116 | * @milliseconds: This parameter specifies the number of milliseconds for which | ||
117 | * to stall. The operating system driver is allowed to round this value up | ||
118 | * where necessary. | ||
119 | * | ||
120 | */ | ||
121 | void scic_cb_timer_start( | ||
122 | struct scic_sds_controller *controller, | ||
123 | void *timer, | ||
124 | u32 milliseconds) | ||
125 | { | ||
126 | struct isci_host *isci_host; | ||
127 | |||
128 | isci_host = | ||
129 | (struct isci_host *)sci_object_get_association(controller); | ||
130 | |||
131 | dev_dbg(&isci_host->pdev->dev, | ||
132 | "%s: isci_host = %p, timer = %p, milliseconds = %d\n", | ||
133 | __func__, isci_host, timer, milliseconds); | ||
134 | |||
135 | isci_timer_start((struct isci_timer *)timer, milliseconds); | ||
136 | |||
137 | } | ||
138 | |||
139 | /** | ||
140 | * scic_cb_timer_stop() - This callback method asks the user to stop the | ||
141 | * supplied timer. The appropriate isci timer object function is called to | ||
142 | * stop the timer. | ||
143 | * @controller: This parameter specifies the controller with which this timer | ||
144 | * is to associated. | ||
145 | * @timer: This parameter specifies the timer to be stopped. | ||
146 | * | ||
147 | */ | ||
148 | void scic_cb_timer_stop( | ||
149 | struct scic_sds_controller *controller, | ||
150 | void *timer) | ||
151 | { | ||
152 | struct isci_host *isci_host; | ||
153 | |||
154 | isci_host = | ||
155 | (struct isci_host *)sci_object_get_association(controller); | ||
156 | |||
157 | dev_dbg(&isci_host->pdev->dev, | ||
158 | "%s: isci_host = %p, timer = %p\n", | ||
159 | __func__, isci_host, timer); | ||
160 | |||
161 | isci_timer_stop((struct isci_timer *)timer); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * scic_cb_controller_start_complete() - This user callback will inform the | ||
166 | * user that the controller has finished the start process. The associated | ||
167 | * isci host adapter's start_complete function is called. | ||
168 | * @controller: This parameter specifies the controller that was started. | ||
169 | * @completion_status: This parameter specifies the results of the start | ||
170 | * operation. SCI_SUCCESS indicates successful completion. | ||
171 | * | ||
172 | */ | ||
173 | void scic_cb_controller_start_complete( | ||
174 | struct scic_sds_controller *controller, | ||
175 | enum sci_status completion_status) | ||
176 | { | ||
177 | struct isci_host *isci_host = | ||
178 | (struct isci_host *)sci_object_get_association(controller); | ||
179 | |||
180 | dev_dbg(&isci_host->pdev->dev, | ||
181 | "%s: isci_host = %p\n", __func__, isci_host); | ||
182 | |||
183 | isci_host_start_complete(isci_host, completion_status); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * scic_cb_controller_stop_complete() - This user callback will inform the user | ||
188 | * that the controller has finished the stop process. The associated isci | ||
189 | * host adapter's start_complete function is called. | ||
190 | * @controller: This parameter specifies the controller that was stopped. | ||
191 | * @completion_status: This parameter specifies the results of the stop | ||
192 | * operation. SCI_SUCCESS indicates successful completion. | ||
193 | * | ||
194 | */ | ||
195 | void scic_cb_controller_stop_complete( | ||
196 | struct scic_sds_controller *controller, | ||
197 | enum sci_status completion_status) | ||
198 | { | ||
199 | struct isci_host *isci_host = | ||
200 | (struct isci_host *)sci_object_get_association(controller); | ||
201 | |||
202 | dev_dbg(&isci_host->pdev->dev, | ||
203 | "%s: status = 0x%x\n", __func__, completion_status); | ||
204 | isci_host_stop_complete(isci_host, completion_status); | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * scic_cb_io_request_complete() - This user callback will inform the user that | ||
209 | * an IO request has completed. | ||
210 | * @controller: This parameter specifies the controller on which the IO is | ||
211 | * completing. | ||
212 | * @remote_device: This parameter specifies the remote device on which this IO | ||
213 | * request is completing. | ||
214 | * @io_request: This parameter specifies the IO request that has completed. | ||
215 | * @completion_status: This parameter specifies the results of the IO request | ||
216 | * operation. SCI_SUCCESS indicates successful completion. | ||
217 | * | ||
218 | */ | ||
219 | void scic_cb_io_request_complete( | ||
220 | struct scic_sds_controller *controller, | ||
221 | struct scic_sds_remote_device *remote_device, | ||
222 | struct scic_sds_request *scic_io_request, | ||
223 | enum sci_io_status completion_status) | ||
224 | { | ||
225 | struct isci_request *request; | ||
226 | struct isci_host *isci_host; | ||
227 | |||
228 | isci_host = | ||
229 | (struct isci_host *)sci_object_get_association(controller); | ||
230 | |||
231 | request = | ||
232 | (struct isci_request *)sci_object_get_association( | ||
233 | scic_io_request | ||
234 | ); | ||
235 | |||
236 | isci_request_io_request_complete(isci_host, | ||
237 | request, | ||
238 | completion_status); | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * scic_cb_task_request_complete() - This user callback will inform the user | ||
243 | * that a task management request completed. | ||
244 | * @controller: This parameter specifies the controller on which the task | ||
245 | * management request is completing. | ||
246 | * @remote_device: This parameter specifies the remote device on which this | ||
247 | * task management request is completing. | ||
248 | * @task_request: This parameter specifies the task management request that has | ||
249 | * completed. | ||
250 | * @completion_status: This parameter specifies the results of the IO request | ||
251 | * operation. SCI_SUCCESS indicates successful completion. | ||
252 | * | ||
253 | */ | ||
254 | void scic_cb_task_request_complete( | ||
255 | struct scic_sds_controller *controller, | ||
256 | struct scic_sds_remote_device *remote_device, | ||
257 | struct scic_sds_request *scic_task_request, | ||
258 | enum sci_task_status completion_status) | ||
259 | { | ||
260 | struct isci_request *request; | ||
261 | struct isci_host *isci_host; | ||
262 | |||
263 | isci_host = | ||
264 | (struct isci_host *)sci_object_get_association(controller); | ||
265 | |||
266 | request = | ||
267 | (struct isci_request *)sci_object_get_association( | ||
268 | scic_task_request); | ||
269 | |||
270 | isci_task_request_complete(isci_host, request, completion_status); | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * scic_cb_port_stop_complete() - This method informs the user when a stop | ||
275 | * operation on the port has completed. | ||
276 | * @controller: This parameter represents the controller which contains the | ||
277 | * port. | ||
278 | * @port: This parameter specifies the SCI port object for which the callback | ||
279 | * is being invoked. | ||
280 | * @completion_status: This parameter specifies the status for the operation | ||
281 | * being completed. | ||
282 | * | ||
283 | */ | ||
284 | void scic_cb_port_stop_complete( | ||
285 | struct scic_sds_controller *controller, | ||
286 | struct scic_sds_port *port, | ||
287 | enum sci_status completion_status) | ||
288 | { | ||
289 | pr_warn("%s:************************************************\n", | ||
290 | __func__); | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * scic_cb_port_hard_reset_complete() - This method informs the user when a | ||
295 | * hard reset on the port has completed. This hard reset could have been | ||
296 | * initiated by the user or by the remote port. | ||
297 | * @controller: This parameter represents the controller which contains the | ||
298 | * port. | ||
299 | * @port: This parameter specifies the SCI port object for which the callback | ||
300 | * is being invoked. | ||
301 | * @completion_status: This parameter specifies the status for the operation | ||
302 | * being completed. | ||
303 | * | ||
304 | */ | ||
305 | void scic_cb_port_hard_reset_complete( | ||
306 | struct scic_sds_controller *controller, | ||
307 | struct scic_sds_port *port, | ||
308 | enum sci_status completion_status) | ||
309 | { | ||
310 | struct isci_port *isci_port | ||
311 | = (struct isci_port *)sci_object_get_association(port); | ||
312 | |||
313 | isci_port_hard_reset_complete(isci_port, completion_status); | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * scic_cb_port_ready() - This method informs the user that the port is now in | ||
318 | * a ready state and can be utilized to issue IOs. | ||
319 | * @controller: This parameter represents the controller which contains the | ||
320 | * port. | ||
321 | * @port: This parameter specifies the SCI port object for which the callback | ||
322 | * is being invoked. | ||
323 | * | ||
324 | */ | ||
325 | void scic_cb_port_ready( | ||
326 | struct scic_sds_controller *controller, | ||
327 | struct scic_sds_port *port) | ||
328 | { | ||
329 | struct isci_port *isci_port; | ||
330 | struct isci_host *isci_host; | ||
331 | |||
332 | isci_host = | ||
333 | (struct isci_host *)sci_object_get_association(controller); | ||
334 | |||
335 | isci_port = | ||
336 | (struct isci_port *)sci_object_get_association(port); | ||
337 | |||
338 | dev_dbg(&isci_host->pdev->dev, | ||
339 | "%s: isci_port = %p\n", __func__, isci_port); | ||
340 | |||
341 | isci_port_ready(isci_host, isci_port); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * scic_cb_port_not_ready() - This method informs the user that the port is now | ||
346 | * not in a ready (i.e. busy) state and can't be utilized to issue IOs. | ||
347 | * @controller: This parameter represents the controller which contains the | ||
348 | * port. | ||
349 | * @port: This parameter specifies the SCI port object for which the callback | ||
350 | * is being invoked. | ||
351 | * | ||
352 | */ | ||
353 | void scic_cb_port_not_ready( | ||
354 | struct scic_sds_controller *controller, | ||
355 | struct scic_sds_port *port, | ||
356 | u32 reason_code) | ||
357 | { | ||
358 | struct isci_port *isci_port; | ||
359 | struct isci_host *isci_host; | ||
360 | |||
361 | isci_host = | ||
362 | (struct isci_host *)sci_object_get_association(controller); | ||
363 | |||
364 | isci_port = | ||
365 | (struct isci_port *)sci_object_get_association(port); | ||
366 | |||
367 | dev_dbg(&isci_host->pdev->dev, | ||
368 | "%s: isci_port = %p\n", __func__, isci_port); | ||
369 | |||
370 | isci_port_not_ready(isci_host, isci_port); | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * scic_cb_port_invalid_link_up() - This method informs the SCI Core user that | ||
375 | * a phy/link became ready, but the phy is not allowed in the port. In some | ||
376 | * situations the underlying hardware only allows for certain phy to port | ||
377 | * mappings. If these mappings are violated, then this API is invoked. | ||
378 | * @controller: This parameter represents the controller which contains the | ||
379 | * port. | ||
380 | * @port: This parameter specifies the SCI port object for which the callback | ||
381 | * is being invoked. | ||
382 | * @phy: This parameter specifies the phy that came ready, but the phy can't be | ||
383 | * a valid member of the port. | ||
384 | * | ||
385 | */ | ||
386 | void scic_cb_port_invalid_link_up( | ||
387 | struct scic_sds_controller *controller, | ||
388 | struct scic_sds_port *port, | ||
389 | struct scic_sds_phy *phy) | ||
390 | { | ||
391 | pr_warn("%s:************************************************\n", | ||
392 | __func__); | ||
393 | } | ||
394 | |||
395 | /** | ||
396 | * scic_cb_port_bc_change_primitive_received() - This callback method informs | ||
397 | * the user that a broadcast change primitive was received. | ||
398 | * @controller: This parameter represents the controller which contains the | ||
399 | * port. | ||
400 | * @port: This parameter specifies the SCI port object for which the callback | ||
401 | * is being invoked. For instances where the phy on which the primitive was | ||
402 | * received is not part of a port, this parameter will be | ||
403 | * SCI_INVALID_HANDLE_T. | ||
404 | * @phy: This parameter specifies the phy on which the primitive was received. | ||
405 | * | ||
406 | */ | ||
407 | void scic_cb_port_bc_change_primitive_received( | ||
408 | struct scic_sds_controller *controller, | ||
409 | struct scic_sds_port *port, | ||
410 | struct scic_sds_phy *phy) | ||
411 | { | ||
412 | struct isci_host *isci_host; | ||
413 | |||
414 | isci_host = | ||
415 | (struct isci_host *)sci_object_get_association(controller); | ||
416 | |||
417 | dev_dbg(&isci_host->pdev->dev, | ||
418 | "%s: port = %p, phy = %p\n", __func__, port, phy); | ||
419 | isci_port_bc_change_received(isci_host, port, phy); | ||
420 | } | ||
421 | |||
422 | |||
423 | |||
424 | |||
425 | /** | ||
426 | * scic_cb_port_link_up() - This callback method informs the user that a phy | ||
427 | * has become operational and is capable of communicating with the remote | ||
428 | * end point. | ||
429 | * @controller: This parameter represents the controller associated with the | ||
430 | * phy. | ||
431 | * @port: This parameter specifies the port object for which the user callback | ||
432 | * is being invoked. There may be conditions where this parameter can be | ||
433 | * SCI_INVALID_HANDLE | ||
434 | * @phy: This parameter specifies the phy object for which the user callback is | ||
435 | * being invoked. | ||
436 | * | ||
437 | * none. | ||
438 | */ | ||
439 | void scic_cb_port_link_up( | ||
440 | struct scic_sds_controller *controller, | ||
441 | struct scic_sds_port *port, | ||
442 | struct scic_sds_phy *phy) | ||
443 | { | ||
444 | struct isci_host *isci_host; | ||
445 | |||
446 | isci_host = | ||
447 | (struct isci_host *)sci_object_get_association(controller); | ||
448 | |||
449 | dev_dbg(&isci_host->pdev->dev, | ||
450 | "%s: phy = %p\n", __func__, phy); | ||
451 | |||
452 | isci_port_link_up(isci_host, port, phy); | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * scic_cb_port_link_down() - This callback method informs the user that a phy | ||
457 | * is no longer operational and is not capable of communicating with the | ||
458 | * remote end point. | ||
459 | * @controller: This parameter represents the controller associated with the | ||
460 | * phy. | ||
461 | * @port: This parameter specifies the port object for which the user callback | ||
462 | * is being invoked. There may be conditions where this parameter can be | ||
463 | * SCI_INVALID_HANDLE | ||
464 | * @phy: This parameter specifies the phy object for which the user callback is | ||
465 | * being invoked. | ||
466 | * | ||
467 | * none. | ||
468 | */ | ||
469 | void scic_cb_port_link_down( | ||
470 | struct scic_sds_controller *controller, | ||
471 | struct scic_sds_port *port, | ||
472 | struct scic_sds_phy *phy) | ||
473 | { | ||
474 | struct isci_host *isci_host; | ||
475 | struct isci_phy *isci_phy; | ||
476 | struct isci_port *isci_port; | ||
477 | |||
478 | isci_host = | ||
479 | (struct isci_host *)sci_object_get_association(controller); | ||
480 | |||
481 | isci_phy = | ||
482 | (struct isci_phy *)sci_object_get_association(phy); | ||
483 | |||
484 | isci_port = | ||
485 | (struct isci_port *)sci_object_get_association(port); | ||
486 | |||
487 | dev_dbg(&isci_host->pdev->dev, | ||
488 | "%s: isci_port = %p\n", __func__, isci_port); | ||
489 | |||
490 | isci_port_link_down(isci_host, isci_phy, isci_port); | ||
491 | } | ||
492 | |||
493 | /** | ||
494 | * scic_cb_remote_device_start_complete() - This user callback method will | ||
495 | * inform the user that a start operation has completed. | ||
496 | * @controller: This parameter specifies the core controller associated with | ||
497 | * the completion callback. | ||
498 | * @remote_device: This parameter specifies the remote device associated with | ||
499 | * the completion callback. | ||
500 | * @completion_status: This parameter specifies the completion status for the | ||
501 | * operation. | ||
502 | * | ||
503 | */ | ||
504 | void scic_cb_remote_device_start_complete( | ||
505 | struct scic_sds_controller *controller, | ||
506 | struct scic_sds_remote_device *remote_device, | ||
507 | enum sci_status completion_status) | ||
508 | { | ||
509 | struct isci_host *isci_host; | ||
510 | struct isci_remote_device *isci_device; | ||
511 | |||
512 | isci_host = | ||
513 | (struct isci_host *)sci_object_get_association(controller); | ||
514 | |||
515 | isci_device = | ||
516 | (struct isci_remote_device *)sci_object_get_association( | ||
517 | remote_device | ||
518 | ); | ||
519 | |||
520 | dev_dbg(&isci_host->pdev->dev, | ||
521 | "%s: isci_device = %p\n", __func__, isci_device); | ||
522 | |||
523 | isci_remote_device_start_complete( | ||
524 | isci_host, isci_device, completion_status); | ||
525 | |||
526 | } | ||
527 | |||
528 | /** | ||
529 | * scic_cb_remote_device_stop_complete() - This user callback method will | ||
530 | * inform the user that a stop operation has completed. | ||
531 | * @controller: This parameter specifies the core controller associated with | ||
532 | * the completion callback. | ||
533 | * @remote_device: This parameter specifies the remote device associated with | ||
534 | * the completion callback. | ||
535 | * @completion_status: This parameter specifies the completion status for the | ||
536 | * operation. | ||
537 | * | ||
538 | */ | ||
539 | void scic_cb_remote_device_stop_complete( | ||
540 | struct scic_sds_controller *controller, | ||
541 | struct scic_sds_remote_device *remote_device, | ||
542 | enum sci_status completion_status) | ||
543 | { | ||
544 | struct isci_host *isci_host; | ||
545 | struct isci_remote_device *isci_device; | ||
546 | |||
547 | isci_host = | ||
548 | (struct isci_host *)sci_object_get_association(controller); | ||
549 | |||
550 | isci_device = | ||
551 | (struct isci_remote_device *)sci_object_get_association( | ||
552 | remote_device | ||
553 | ); | ||
554 | |||
555 | dev_dbg(&isci_host->pdev->dev, | ||
556 | "%s: isci_device = %p\n", __func__, isci_device); | ||
557 | |||
558 | isci_remote_device_stop_complete( | ||
559 | isci_host, isci_device, completion_status); | ||
560 | |||
561 | } | ||
562 | |||
563 | /** | ||
564 | * scic_cb_remote_device_ready() - This user callback method will inform the | ||
565 | * user that a remote device is now capable of handling IO requests. | ||
566 | * @controller: This parameter specifies the core controller associated with | ||
567 | * the completion callback. | ||
568 | * @remote_device: This parameter specifies the remote device associated with | ||
569 | * the callback. | ||
570 | * | ||
571 | */ | ||
572 | void scic_cb_remote_device_ready( | ||
573 | struct scic_sds_controller *controller, | ||
574 | struct scic_sds_remote_device *remote_device) | ||
575 | { | ||
576 | struct isci_remote_device *isci_device = | ||
577 | (struct isci_remote_device *) | ||
578 | sci_object_get_association(remote_device); | ||
579 | |||
580 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
581 | "%s: isci_device = %p\n", __func__, isci_device); | ||
582 | |||
583 | isci_remote_device_ready(isci_device); | ||
584 | } | ||
585 | |||
586 | /** | ||
587 | * scic_cb_remote_device_not_ready() - This user callback method will inform | ||
588 | * the user that a remote device is no longer capable of handling IO | ||
589 | * requests (until a ready callback is invoked). | ||
590 | * @controller: This parameter specifies the core controller associated with | ||
591 | * the completion callback. | ||
592 | * @remote_device: This parameter specifies the remote device associated with | ||
593 | * the callback. | ||
594 | * @reason_code: This parameter specifies the reason for the remote device | ||
595 | * going to a not ready state. | ||
596 | * | ||
597 | */ | ||
598 | void scic_cb_remote_device_not_ready( | ||
599 | struct scic_sds_controller *controller, | ||
600 | struct scic_sds_remote_device *remote_device, | ||
601 | u32 reason_code) | ||
602 | { | ||
603 | struct isci_remote_device *isci_device = | ||
604 | (struct isci_remote_device *) | ||
605 | sci_object_get_association(remote_device); | ||
606 | |||
607 | struct isci_host *isci_host; | ||
608 | |||
609 | isci_host = | ||
610 | (struct isci_host *)sci_object_get_association(controller); | ||
611 | |||
612 | dev_dbg(&isci_host->pdev->dev, | ||
613 | "%s: isci_device = %p, reason_code = %x\n", | ||
614 | __func__, isci_device, reason_code); | ||
615 | |||
616 | isci_remote_device_not_ready(isci_device, reason_code); | ||
617 | } | ||
618 | |||
619 | |||
diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile new file mode 100644 index 000000000000..5f54461cabc5 --- /dev/null +++ b/drivers/scsi/isci/firmware/Makefile | |||
@@ -0,0 +1,19 @@ | |||
1 | # Makefile for create_fw | ||
2 | # | ||
3 | CC=gcc | ||
4 | CFLAGS=-c -Wall -O2 -g | ||
5 | LDFLAGS= | ||
6 | SOURCES=create_fw.c | ||
7 | OBJECTS=$(SOURCES:.cpp=.o) | ||
8 | EXECUTABLE=create_fw | ||
9 | |||
10 | all: $(SOURCES) $(EXECUTABLE) | ||
11 | |||
12 | $(EXECUTABLE): $(OBJECTS) | ||
13 | $(CC) $(LDFLAGS) $(OBJECTS) -o $@ | ||
14 | |||
15 | .c.o: | ||
16 | $(CC) $(CFLAGS) $< -O $@ | ||
17 | |||
18 | clean: | ||
19 | rm -f *.o $(EXECUTABLE) | ||
diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README new file mode 100644 index 000000000000..cf7e4286e896 --- /dev/null +++ b/drivers/scsi/isci/firmware/README | |||
@@ -0,0 +1,36 @@ | |||
1 | This defines the temporary binary blow we are to pass to the SCU | ||
2 | driver to emulate the binary firmware that we will eventually be | ||
3 | able to access via NVRAM on the SCU controller. | ||
4 | |||
5 | The current size of the binary blob is expected to be 149 bytes or larger | ||
6 | |||
7 | Header Types: | ||
8 | 0x1: Phy Masks | ||
9 | 0x2: Phy Gens | ||
10 | 0x3: SAS Addrs | ||
11 | 0xff: End of Data | ||
12 | |||
13 | ID string - u8[12]: "#SCU MAGIC#\0" | ||
14 | Version - u8: 1 | ||
15 | SubVersion - u8: 0 | ||
16 | |||
17 | Header Type - u8: 0x1 | ||
18 | Size - u8: 8 | ||
19 | Phy Mask - u32[8] | ||
20 | |||
21 | Header Type - u8: 0x2 | ||
22 | Size - u8: 8 | ||
23 | Phy Gen - u32[8] | ||
24 | |||
25 | Header Type - u8: 0x3 | ||
26 | Size - u8: 8 | ||
27 | Sas Addr - u64[8] | ||
28 | |||
29 | Header Type - u8: 0xf | ||
30 | |||
31 | |||
32 | ============================================================================== | ||
33 | |||
34 | Place isci_firmware.bin in /lib/firmware | ||
35 | Be sure to recreate the initramfs image to include the firmware. | ||
36 | |||
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c new file mode 100644 index 000000000000..442caac9675d --- /dev/null +++ b/drivers/scsi/isci/firmware/create_fw.c | |||
@@ -0,0 +1,177 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <unistd.h> | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/stat.h> | ||
6 | #include <fcntl.h> | ||
7 | #include <string.h> | ||
8 | #include <errno.h> | ||
9 | |||
10 | char blob_name[] = "isci_firmware.bin"; | ||
11 | char id[] = "#SCU MAGIC#"; | ||
12 | unsigned char version = 1; | ||
13 | unsigned char sub_version = 0; | ||
14 | |||
15 | |||
16 | /* | ||
17 | * For all defined arrays: | ||
18 | * elements 0-3 are for SCU0, ports 0-3 | ||
19 | * elements 4-7 are for SCU1, ports 0-3 | ||
20 | * | ||
21 | * valid configurations for one SCU are: | ||
22 | * P0 P1 P2 P3 | ||
23 | * ---------------- | ||
24 | * 0xF,0x0,0x0,0x0 # 1 x4 port | ||
25 | * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1 | ||
26 | * # ports | ||
27 | * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2 | ||
28 | * # port | ||
29 | * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port | ||
30 | * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration) | ||
31 | * | ||
32 | * if there is a port/phy on which you do not wish to override the default | ||
33 | * values, use the value assigned to UNINIT_PARAM (255). | ||
34 | */ | ||
35 | unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 }; | ||
36 | |||
37 | |||
38 | /* denotes SAS generation. i.e. 3: SAS Gen 3 6G */ | ||
39 | unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 }; | ||
40 | |||
41 | /* | ||
42 | * if there is a port/phy on which you do not wish to override the default | ||
43 | * values, use the value "0000000000000000". SAS address of zero's is | ||
44 | * considered invalid and will not be used. | ||
45 | */ | ||
46 | unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL, | ||
47 | 0x5FCFFFFFF1000000ULL, | ||
48 | 0x5FCFFFFFF2000000ULL, | ||
49 | 0x5FCFFFFFF3000000ULL, | ||
50 | 0x5FCFFFFFF4000000ULL, | ||
51 | 0x5FCFFFFFF5000000ULL, | ||
52 | 0x5FCFFFFFF6000000ULL, | ||
53 | 0x5FCFFFFFF7000000ULL }; | ||
54 | |||
55 | int write_blob(void) | ||
56 | { | ||
57 | FILE *fd; | ||
58 | int err; | ||
59 | |||
60 | fd = fopen(blob_name, "w+"); | ||
61 | if (!fd) { | ||
62 | perror("Open file for write failed"); | ||
63 | return -EIO; | ||
64 | } | ||
65 | |||
66 | /* write id */ | ||
67 | err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd); | ||
68 | if (err == 0) { | ||
69 | perror("write id failed"); | ||
70 | return err; | ||
71 | } | ||
72 | |||
73 | /* write version */ | ||
74 | err = fwrite((void *)&version, sizeof(version), 1, fd); | ||
75 | if (err == 0) { | ||
76 | perror("write version failed"); | ||
77 | return err; | ||
78 | } | ||
79 | |||
80 | /* write sub version */ | ||
81 | err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd); | ||
82 | if (err == 0) { | ||
83 | perror("write subversion failed"); | ||
84 | return err; | ||
85 | } | ||
86 | |||
87 | /* write phy mask header */ | ||
88 | err = fputc(0x1, fd); | ||
89 | if (err == EOF) { | ||
90 | perror("write phy mask header failed"); | ||
91 | return -EIO; | ||
92 | } | ||
93 | |||
94 | /* write size */ | ||
95 | err = fputc(8, fd); | ||
96 | if (err == EOF) { | ||
97 | perror("write phy mask size failed"); | ||
98 | return -EIO; | ||
99 | } | ||
100 | |||
101 | /* write phy masks */ | ||
102 | err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd); | ||
103 | if (err == 0) { | ||
104 | perror("write phy_mask failed"); | ||
105 | return err; | ||
106 | } | ||
107 | |||
108 | /* write phy gen header */ | ||
109 | err = fputc(0x2, fd); | ||
110 | if (err == EOF) { | ||
111 | perror("write phy gen header failed"); | ||
112 | return -EIO; | ||
113 | } | ||
114 | |||
115 | /* write size */ | ||
116 | err = fputc(8, fd); | ||
117 | if (err == EOF) { | ||
118 | perror("write phy gen size failed"); | ||
119 | return -EIO; | ||
120 | } | ||
121 | |||
122 | /* write phy_gen */ | ||
123 | err = fwrite((void *)phy_gen, | ||
124 | 1, | ||
125 | sizeof(phy_gen), | ||
126 | fd); | ||
127 | if (err == 0) { | ||
128 | perror("write phy_gen failed"); | ||
129 | return err; | ||
130 | } | ||
131 | |||
132 | /* write phy gen header */ | ||
133 | err = fputc(0x3, fd); | ||
134 | if (err == EOF) { | ||
135 | perror("write sas addr header failed"); | ||
136 | return -EIO; | ||
137 | } | ||
138 | |||
139 | /* write size */ | ||
140 | err = fputc(8, fd); | ||
141 | if (err == EOF) { | ||
142 | perror("write sas addr size failed"); | ||
143 | return -EIO; | ||
144 | } | ||
145 | |||
146 | /* write sas_addr */ | ||
147 | err = fwrite((void *)sas_addr, | ||
148 | 1, | ||
149 | sizeof(sas_addr), | ||
150 | fd); | ||
151 | if (err == 0) { | ||
152 | perror("write sas_addr failed"); | ||
153 | return err; | ||
154 | } | ||
155 | |||
156 | /* write end header */ | ||
157 | err = fputc(0xff, fd); | ||
158 | if (err == EOF) { | ||
159 | perror("write end header failed"); | ||
160 | return -EIO; | ||
161 | } | ||
162 | |||
163 | fclose(fd); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | int main(void) | ||
169 | { | ||
170 | int err; | ||
171 | |||
172 | err = write_blob(); | ||
173 | if (err < 0) | ||
174 | return err; | ||
175 | |||
176 | return 0; | ||
177 | } | ||
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c new file mode 100644 index 000000000000..6f16f4d6c82b --- /dev/null +++ b/drivers/scsi/isci/host.c | |||
@@ -0,0 +1,781 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "isci.h" | ||
57 | #include "scic_io_request.h" | ||
58 | #include "scic_remote_device.h" | ||
59 | #include "scic_port.h" | ||
60 | |||
61 | #include "port.h" | ||
62 | #include "request.h" | ||
63 | #include "host.h" | ||
64 | |||
65 | /** | ||
66 | * isci_isr() - This function is the interrupt service routine for the | ||
67 | * controller. It schedules the tasklet and returns. | ||
68 | * @vec: This parameter specifies the interrupt vector. | ||
69 | * @data: This parameter specifies the ISCI host object. | ||
70 | * | ||
71 | * IRQ_HANDLED if out interrupt otherwise, IRQ_NONE | ||
72 | */ | ||
73 | irqreturn_t isci_isr(int vec, void *data) | ||
74 | { | ||
75 | struct isci_host *isci_host | ||
76 | = (struct isci_host *)data; | ||
77 | struct scic_controller_handler_methods *handlers | ||
78 | = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | ||
79 | irqreturn_t ret = IRQ_NONE; | ||
80 | |||
81 | if (isci_host_get_state(isci_host) != isci_starting | ||
82 | && handlers->interrupt_handler) { | ||
83 | |||
84 | if (handlers->interrupt_handler(isci_host->core_controller)) { | ||
85 | if (isci_host_get_state(isci_host) != isci_stopped) { | ||
86 | tasklet_schedule( | ||
87 | &isci_host->completion_tasklet); | ||
88 | } else | ||
89 | dev_dbg(&isci_host->pdev->dev, | ||
90 | "%s: controller stopped\n", | ||
91 | __func__); | ||
92 | ret = IRQ_HANDLED; | ||
93 | } | ||
94 | } else | ||
95 | dev_warn(&isci_host->pdev->dev, | ||
96 | "%s: get_handler_methods failed, " | ||
97 | "isci_host->status = 0x%x\n", | ||
98 | __func__, | ||
99 | isci_host_get_state(isci_host)); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | irqreturn_t isci_legacy_isr(int vec, void *data) | ||
105 | { | ||
106 | struct pci_dev *pdev = data; | ||
107 | struct isci_host *isci_host; | ||
108 | struct scic_controller_handler_methods *handlers; | ||
109 | irqreturn_t ret = IRQ_NONE; | ||
110 | |||
111 | /* | ||
112 | * Since this is a legacy interrupt, either or both | ||
113 | * controllers could have triggered it. Thus, we have to call | ||
114 | * the legacy interrupt handler for all controllers on the | ||
115 | * PCI function. | ||
116 | */ | ||
117 | for_each_isci_host(isci_host, pdev) { | ||
118 | handlers = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | ||
119 | |||
120 | if (isci_host_get_state(isci_host) != isci_starting | ||
121 | && handlers->interrupt_handler) { | ||
122 | |||
123 | if (handlers->interrupt_handler(isci_host->core_controller)) { | ||
124 | if (isci_host_get_state(isci_host) != isci_stopped) { | ||
125 | tasklet_schedule( | ||
126 | &isci_host->completion_tasklet); | ||
127 | } else | ||
128 | dev_dbg(&isci_host->pdev->dev, | ||
129 | "%s: controller stopped\n", | ||
130 | __func__); | ||
131 | ret = IRQ_HANDLED; | ||
132 | } | ||
133 | } else | ||
134 | dev_warn(&isci_host->pdev->dev, | ||
135 | "%s: get_handler_methods failed, " | ||
136 | "isci_host->status = 0x%x\n", | ||
137 | __func__, | ||
138 | isci_host_get_state(isci_host)); | ||
139 | } | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | |||
144 | /** | ||
145 | * isci_host_start_complete() - This function is called by the core library, | ||
146 | * through the ISCI Module, to indicate controller start status. | ||
147 | * @isci_host: This parameter specifies the ISCI host object | ||
148 | * @completion_status: This parameter specifies the completion status from the | ||
149 | * core library. | ||
150 | * | ||
151 | */ | ||
152 | void isci_host_start_complete( | ||
153 | struct isci_host *isci_host, | ||
154 | enum sci_status completion_status) | ||
155 | { | ||
156 | if (completion_status == SCI_SUCCESS) { | ||
157 | dev_dbg(&isci_host->pdev->dev, | ||
158 | "%s: completion_status: SCI_SUCCESS\n", __func__); | ||
159 | isci_host_change_state(isci_host, isci_ready); | ||
160 | complete_all(&isci_host->start_complete); | ||
161 | } else | ||
162 | dev_err(&isci_host->pdev->dev, | ||
163 | "controller start failed with " | ||
164 | "completion_status = 0x%x;", | ||
165 | completion_status); | ||
166 | |||
167 | } | ||
168 | |||
169 | |||
170 | |||
171 | /** | ||
172 | * isci_host_scan_finished() - This function is one of the SCSI Host Template | ||
173 | * functions. The SCSI midlayer calls this function during a target scan, | ||
174 | * approx. once every 10 millisecs. | ||
175 | * @shost: This parameter specifies the SCSI host being scanned | ||
176 | * @time: This parameter specifies the number of ticks since the scan started. | ||
177 | * | ||
178 | * scan status, zero indicates the SCSI midlayer should continue to poll, | ||
179 | * otherwise assume controller is ready. | ||
180 | */ | ||
181 | int isci_host_scan_finished( | ||
182 | struct Scsi_Host *shost, | ||
183 | unsigned long time) | ||
184 | { | ||
185 | struct isci_host *isci_host | ||
186 | = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); | ||
187 | |||
188 | struct scic_controller_handler_methods *handlers | ||
189 | = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | ||
190 | |||
191 | if (handlers->interrupt_handler == NULL) { | ||
192 | dev_err(&isci_host->pdev->dev, | ||
193 | "%s: scic_controller_get_handler_methods failed\n", | ||
194 | __func__); | ||
195 | return 1; | ||
196 | } | ||
197 | |||
198 | /** | ||
199 | * check interrupt_handler's status and call completion_handler if true, | ||
200 | * link_up events should be coming from the scu core lib, as phy's come | ||
201 | * online. for each link_up from the core, call | ||
202 | * get_received_identify_address_frame, copy the frame into the | ||
203 | * sas_phy object and call libsas notify_port_event(PORTE_BYTES_DMAED). | ||
204 | * continue to return zero from thee scan_finished routine until | ||
205 | * the scic_cb_controller_start_complete() call comes from the core. | ||
206 | **/ | ||
207 | if (handlers->interrupt_handler(isci_host->core_controller)) | ||
208 | handlers->completion_handler(isci_host->core_controller); | ||
209 | |||
210 | if (isci_starting == isci_host_get_state(isci_host) | ||
211 | && time < (HZ * 10)) { | ||
212 | dev_dbg(&isci_host->pdev->dev, | ||
213 | "%s: isci_host->status = %d, time = %ld\n", | ||
214 | __func__, isci_host_get_state(isci_host), time); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | |||
219 | dev_dbg(&isci_host->pdev->dev, | ||
220 | "%s: isci_host->status = %d, time = %ld\n", | ||
221 | __func__, isci_host_get_state(isci_host), time); | ||
222 | |||
223 | scic_controller_enable_interrupts(isci_host->core_controller); | ||
224 | |||
225 | return 1; | ||
226 | |||
227 | } | ||
228 | |||
229 | |||
230 | /** | ||
231 | * isci_host_scan_start() - This function is one of the SCSI Host Template | ||
232 | * function, called by the SCSI mid layer berfore a target scan begins. The | ||
233 | * core library controller start routine is called from here. | ||
234 | * @shost: This parameter specifies the SCSI host to be scanned | ||
235 | * | ||
236 | */ | ||
237 | void isci_host_scan_start(struct Scsi_Host *shost) | ||
238 | { | ||
239 | struct isci_host *isci_host; | ||
240 | |||
241 | isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost)); | ||
242 | isci_host_change_state(isci_host, isci_starting); | ||
243 | |||
244 | scic_controller_disable_interrupts(isci_host->core_controller); | ||
245 | init_completion(&isci_host->start_complete); | ||
246 | scic_controller_start( | ||
247 | isci_host->core_controller, | ||
248 | scic_controller_get_suggested_start_timeout( | ||
249 | isci_host->core_controller) | ||
250 | ); | ||
251 | } | ||
252 | |||
253 | void isci_host_stop_complete( | ||
254 | struct isci_host *isci_host, | ||
255 | enum sci_status completion_status) | ||
256 | { | ||
257 | isci_host_change_state(isci_host, isci_stopped); | ||
258 | scic_controller_disable_interrupts( | ||
259 | isci_host->core_controller | ||
260 | ); | ||
261 | complete(&isci_host->stop_complete); | ||
262 | } | ||
263 | |||
264 | static struct coherent_memory_info *isci_host_alloc_mdl_struct( | ||
265 | struct isci_host *isci_host, | ||
266 | u32 size) | ||
267 | { | ||
268 | struct coherent_memory_info *mdl_struct; | ||
269 | void *uncached_address = NULL; | ||
270 | |||
271 | |||
272 | mdl_struct = devm_kzalloc(&isci_host->pdev->dev, | ||
273 | sizeof(*mdl_struct), | ||
274 | GFP_KERNEL); | ||
275 | if (!mdl_struct) | ||
276 | return NULL; | ||
277 | |||
278 | INIT_LIST_HEAD(&mdl_struct->node); | ||
279 | |||
280 | uncached_address = dmam_alloc_coherent(&isci_host->pdev->dev, | ||
281 | size, | ||
282 | &mdl_struct->dma_handle, | ||
283 | GFP_KERNEL); | ||
284 | if (!uncached_address) | ||
285 | return NULL; | ||
286 | |||
287 | /* memset the whole memory area. */ | ||
288 | memset((char *)uncached_address, 0, size); | ||
289 | mdl_struct->vaddr = uncached_address; | ||
290 | mdl_struct->size = (size_t)size; | ||
291 | |||
292 | return mdl_struct; | ||
293 | } | ||
294 | |||
295 | static void isci_host_build_mde( | ||
296 | struct sci_physical_memory_descriptor *mde_struct, | ||
297 | struct coherent_memory_info *mdl_struct) | ||
298 | { | ||
299 | unsigned long address = 0; | ||
300 | dma_addr_t dma_addr = 0; | ||
301 | |||
302 | address = (unsigned long)mdl_struct->vaddr; | ||
303 | dma_addr = mdl_struct->dma_handle; | ||
304 | |||
305 | /* to satisfy the alignment. */ | ||
306 | if ((address % mde_struct->constant_memory_alignment) != 0) { | ||
307 | int align_offset | ||
308 | = (mde_struct->constant_memory_alignment | ||
309 | - (address % mde_struct->constant_memory_alignment)); | ||
310 | address += align_offset; | ||
311 | dma_addr += align_offset; | ||
312 | } | ||
313 | |||
314 | mde_struct->virtual_address = (void *)address; | ||
315 | mde_struct->physical_address = dma_addr; | ||
316 | mdl_struct->mde = mde_struct; | ||
317 | } | ||
318 | |||
319 | static int isci_host_mdl_allocate_coherent( | ||
320 | struct isci_host *isci_host) | ||
321 | { | ||
322 | struct sci_physical_memory_descriptor *current_mde; | ||
323 | struct coherent_memory_info *mdl_struct; | ||
324 | u32 size = 0; | ||
325 | |||
326 | struct sci_base_memory_descriptor_list *mdl_handle | ||
327 | = sci_controller_get_memory_descriptor_list_handle( | ||
328 | isci_host->core_controller); | ||
329 | |||
330 | sci_mdl_first_entry(mdl_handle); | ||
331 | |||
332 | current_mde = sci_mdl_get_current_entry(mdl_handle); | ||
333 | |||
334 | while (current_mde != NULL) { | ||
335 | |||
336 | size = (current_mde->constant_memory_size | ||
337 | + current_mde->constant_memory_alignment); | ||
338 | |||
339 | mdl_struct = isci_host_alloc_mdl_struct(isci_host, size); | ||
340 | if (!mdl_struct) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | list_add_tail(&mdl_struct->node, &isci_host->mdl_struct_list); | ||
344 | |||
345 | isci_host_build_mde(current_mde, mdl_struct); | ||
346 | |||
347 | sci_mdl_next_entry(mdl_handle); | ||
348 | current_mde = sci_mdl_get_current_entry(mdl_handle); | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | |||
355 | /** | ||
356 | * isci_host_completion_routine() - This function is the delayed service | ||
357 | * routine that calls the sci core library's completion handler. It's | ||
358 | * scheduled as a tasklet from the interrupt service routine when interrupts | ||
359 | * in use, or set as the timeout function in polled mode. | ||
360 | * @data: This parameter specifies the ISCI host object | ||
361 | * | ||
362 | */ | ||
363 | static void isci_host_completion_routine(unsigned long data) | ||
364 | { | ||
365 | struct isci_host *isci_host = (struct isci_host *)data; | ||
366 | struct scic_controller_handler_methods *handlers | ||
367 | = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR]; | ||
368 | struct list_head completed_request_list; | ||
369 | struct list_head aborted_request_list; | ||
370 | struct list_head *current_position; | ||
371 | struct list_head *next_position; | ||
372 | struct isci_request *request; | ||
373 | struct isci_request *next_request; | ||
374 | struct sas_task *task; | ||
375 | |||
376 | INIT_LIST_HEAD(&completed_request_list); | ||
377 | INIT_LIST_HEAD(&aborted_request_list); | ||
378 | |||
379 | spin_lock_irq(&isci_host->scic_lock); | ||
380 | |||
381 | if (handlers->completion_handler) { | ||
382 | handlers->completion_handler( | ||
383 | isci_host->core_controller | ||
384 | ); | ||
385 | } | ||
386 | /* Take the lists of completed I/Os from the host. */ | ||
387 | list_splice_init(&isci_host->requests_to_complete, | ||
388 | &completed_request_list); | ||
389 | |||
390 | list_splice_init(&isci_host->requests_to_abort, | ||
391 | &aborted_request_list); | ||
392 | |||
393 | spin_unlock_irq(&isci_host->scic_lock); | ||
394 | |||
395 | /* Process any completions in the lists. */ | ||
396 | list_for_each_safe(current_position, next_position, | ||
397 | &completed_request_list) { | ||
398 | |||
399 | request = list_entry(current_position, struct isci_request, | ||
400 | completed_node); | ||
401 | task = isci_request_access_task(request); | ||
402 | |||
403 | /* Normal notification (task_done) */ | ||
404 | dev_dbg(&isci_host->pdev->dev, | ||
405 | "%s: Normal - request/task = %p/%p\n", | ||
406 | __func__, | ||
407 | request, | ||
408 | task); | ||
409 | |||
410 | task->task_done(task); | ||
411 | task->lldd_task = NULL; | ||
412 | |||
413 | /* Free the request object. */ | ||
414 | isci_request_free(isci_host, request); | ||
415 | } | ||
416 | list_for_each_entry_safe(request, next_request, &aborted_request_list, | ||
417 | completed_node) { | ||
418 | |||
419 | task = isci_request_access_task(request); | ||
420 | |||
421 | /* Use sas_task_abort */ | ||
422 | dev_warn(&isci_host->pdev->dev, | ||
423 | "%s: Error - request/task = %p/%p\n", | ||
424 | __func__, | ||
425 | request, | ||
426 | task); | ||
427 | |||
428 | /* Put the task into the abort path. */ | ||
429 | sas_task_abort(task); | ||
430 | } | ||
431 | |||
432 | } | ||
433 | |||
434 | void isci_host_deinit( | ||
435 | struct isci_host *isci_host) | ||
436 | { | ||
437 | int i; | ||
438 | |||
439 | isci_host_change_state(isci_host, isci_stopping); | ||
440 | for (i = 0; i < SCI_MAX_PORTS; i++) { | ||
441 | struct isci_port *port = &isci_host->isci_ports[i]; | ||
442 | struct isci_remote_device *device, *tmpdev; | ||
443 | list_for_each_entry_safe(device, tmpdev, | ||
444 | &port->remote_dev_list, node) { | ||
445 | isci_remote_device_change_state(device, isci_stopping); | ||
446 | isci_remote_device_stop(device); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | /* stop the comtroller and wait for completion. */ | ||
451 | init_completion(&isci_host->stop_complete); | ||
452 | scic_controller_stop( | ||
453 | isci_host->core_controller, | ||
454 | SCIC_CONTROLLER_STOP_TIMEOUT | ||
455 | ); | ||
456 | wait_for_completion(&isci_host->stop_complete); | ||
457 | /* next, reset the controller. */ | ||
458 | scic_controller_reset(isci_host->core_controller); | ||
459 | } | ||
460 | |||
461 | static int isci_verify_firmware(const struct firmware *fw, | ||
462 | struct isci_firmware *isci_fw) | ||
463 | { | ||
464 | const u8 *tmp; | ||
465 | |||
466 | if (fw->size < ISCI_FIRMWARE_MIN_SIZE) | ||
467 | return -EINVAL; | ||
468 | |||
469 | tmp = fw->data; | ||
470 | |||
471 | /* 12th char should be the NULL terminate for the ID string */ | ||
472 | if (tmp[11] != '\0') | ||
473 | return -EINVAL; | ||
474 | |||
475 | if (strncmp("#SCU MAGIC#", tmp, 11) != 0) | ||
476 | return -EINVAL; | ||
477 | |||
478 | isci_fw->id = tmp; | ||
479 | isci_fw->version = fw->data[ISCI_FW_VER_OFS]; | ||
480 | isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS]; | ||
481 | |||
482 | tmp = fw->data + ISCI_FW_DATA_OFS; | ||
483 | |||
484 | while (*tmp != ISCI_FW_HDR_EOF) { | ||
485 | switch (*tmp) { | ||
486 | case ISCI_FW_HDR_PHYMASK: | ||
487 | tmp++; | ||
488 | isci_fw->phy_masks_size = *tmp; | ||
489 | tmp++; | ||
490 | isci_fw->phy_masks = (const u32 *)tmp; | ||
491 | tmp += sizeof(u32) * isci_fw->phy_masks_size; | ||
492 | break; | ||
493 | |||
494 | case ISCI_FW_HDR_PHYGEN: | ||
495 | tmp++; | ||
496 | isci_fw->phy_gens_size = *tmp; | ||
497 | tmp++; | ||
498 | isci_fw->phy_gens = (const u32 *)tmp; | ||
499 | tmp += sizeof(u32) * isci_fw->phy_gens_size; | ||
500 | break; | ||
501 | |||
502 | case ISCI_FW_HDR_SASADDR: | ||
503 | tmp++; | ||
504 | isci_fw->sas_addrs_size = *tmp; | ||
505 | tmp++; | ||
506 | isci_fw->sas_addrs = (const u64 *)tmp; | ||
507 | tmp += sizeof(u64) * isci_fw->sas_addrs_size; | ||
508 | break; | ||
509 | |||
510 | default: | ||
511 | pr_err("bad field in firmware binary blob\n"); | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | pr_info("isci firmware v%u.%u loaded.\n", | ||
517 | isci_fw->version, isci_fw->subversion); | ||
518 | |||
519 | return SCI_SUCCESS; | ||
520 | } | ||
521 | |||
522 | static void __iomem *scu_base(struct isci_host *isci_host) | ||
523 | { | ||
524 | struct pci_dev *pdev = isci_host->pdev; | ||
525 | int id = isci_host->id; | ||
526 | |||
527 | return pcim_iomap_table(pdev)[SCI_SCU_BAR * 2] + SCI_SCU_BAR_SIZE * id; | ||
528 | } | ||
529 | |||
530 | static void __iomem *smu_base(struct isci_host *isci_host) | ||
531 | { | ||
532 | struct pci_dev *pdev = isci_host->pdev; | ||
533 | int id = isci_host->id; | ||
534 | |||
535 | return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id; | ||
536 | } | ||
537 | |||
538 | #define SCI_MAX_TIMER_COUNT 25 | ||
539 | |||
540 | int isci_host_init(struct isci_host *isci_host) | ||
541 | { | ||
542 | int err = 0; | ||
543 | int index = 0; | ||
544 | enum sci_status status; | ||
545 | struct scic_sds_controller *controller; | ||
546 | struct scic_sds_port *scic_port; | ||
547 | struct scic_controller_handler_methods *handlers | ||
548 | = &isci_host->scic_irq_handlers[0]; | ||
549 | union scic_oem_parameters scic_oem_params; | ||
550 | union scic_user_parameters scic_user_params; | ||
551 | const struct firmware *fw = NULL; | ||
552 | struct isci_firmware *isci_fw = NULL; | ||
553 | |||
554 | INIT_LIST_HEAD(&isci_host->timer_list_struct.timers); | ||
555 | isci_timer_list_construct( | ||
556 | &isci_host->timer_list_struct, | ||
557 | SCI_MAX_TIMER_COUNT | ||
558 | ); | ||
559 | |||
560 | controller = scic_controller_alloc(&isci_host->pdev->dev); | ||
561 | |||
562 | if (!controller) { | ||
563 | err = -ENOMEM; | ||
564 | dev_err(&isci_host->pdev->dev, "%s: failed (%d)\n", __func__, err); | ||
565 | goto out; | ||
566 | } | ||
567 | |||
568 | isci_host->core_controller = controller; | ||
569 | spin_lock_init(&isci_host->state_lock); | ||
570 | spin_lock_init(&isci_host->scic_lock); | ||
571 | spin_lock_init(&isci_host->queue_lock); | ||
572 | |||
573 | isci_host_change_state(isci_host, isci_starting); | ||
574 | isci_host->can_queue = ISCI_CAN_QUEUE_VAL; | ||
575 | |||
576 | status = scic_controller_construct(controller, scu_base(isci_host), | ||
577 | smu_base(isci_host)); | ||
578 | |||
579 | if (status != SCI_SUCCESS) { | ||
580 | dev_err(&isci_host->pdev->dev, | ||
581 | "%s: scic_controller_construct failed - status = %x\n", | ||
582 | __func__, | ||
583 | status); | ||
584 | err = -ENODEV; | ||
585 | goto out; | ||
586 | } | ||
587 | |||
588 | isci_host->sas_ha.dev = &isci_host->pdev->dev; | ||
589 | isci_host->sas_ha.lldd_ha = isci_host; | ||
590 | |||
591 | /*----------- SCIC controller Initialization Stuff ------------------ | ||
592 | * set association host adapter struct in core controller. | ||
593 | */ | ||
594 | sci_object_set_association(isci_host->core_controller, | ||
595 | (void *)isci_host | ||
596 | ); | ||
597 | |||
598 | /* grab initial values stored in the controller object for OEM and USER | ||
599 | * parameters */ | ||
600 | scic_oem_parameters_get(controller, &scic_oem_params); | ||
601 | scic_user_parameters_get(controller, &scic_user_params); | ||
602 | |||
603 | isci_fw = devm_kzalloc(&isci_host->pdev->dev, | ||
604 | sizeof(struct isci_firmware), | ||
605 | GFP_KERNEL); | ||
606 | if (!isci_fw) { | ||
607 | dev_warn(&isci_host->pdev->dev, | ||
608 | "allocating firmware struct failed\n"); | ||
609 | dev_warn(&isci_host->pdev->dev, | ||
610 | "Default OEM configuration being used:" | ||
611 | " 4 narrow ports, and default SAS Addresses\n"); | ||
612 | goto set_default_params; | ||
613 | } | ||
614 | |||
615 | status = request_firmware(&fw, ISCI_FW_NAME, &isci_host->pdev->dev); | ||
616 | if (status) { | ||
617 | dev_warn(&isci_host->pdev->dev, | ||
618 | "Loading firmware failed, using default values\n"); | ||
619 | dev_warn(&isci_host->pdev->dev, | ||
620 | "Default OEM configuration being used:" | ||
621 | " 4 narrow ports, and default SAS Addresses\n"); | ||
622 | goto set_default_params; | ||
623 | } | ||
624 | else { | ||
625 | status = isci_verify_firmware(fw, isci_fw); | ||
626 | if (status != SCI_SUCCESS) { | ||
627 | dev_warn(&isci_host->pdev->dev, | ||
628 | "firmware verification failed\n"); | ||
629 | dev_warn(&isci_host->pdev->dev, | ||
630 | "Default OEM configuration being used:" | ||
631 | " 4 narrow ports, and default SAS " | ||
632 | "Addresses\n"); | ||
633 | goto set_default_params; | ||
634 | } | ||
635 | |||
636 | /* grab any OEM and USER parameters specified at module load */ | ||
637 | status = isci_parse_oem_parameters(&scic_oem_params, | ||
638 | isci_host->id, isci_fw); | ||
639 | if (status != SCI_SUCCESS) { | ||
640 | dev_warn(&isci_host->pdev->dev, | ||
641 | "parsing firmware oem parameters failed\n"); | ||
642 | err = -EINVAL; | ||
643 | goto out; | ||
644 | } | ||
645 | |||
646 | status = isci_parse_user_parameters(&scic_user_params, | ||
647 | isci_host->id, isci_fw); | ||
648 | if (status != SCI_SUCCESS) { | ||
649 | dev_warn(&isci_host->pdev->dev, | ||
650 | "%s: isci_parse_user_parameters" | ||
651 | " failed\n", __func__); | ||
652 | err = -EINVAL; | ||
653 | goto out; | ||
654 | } | ||
655 | } | ||
656 | |||
657 | set_default_params: | ||
658 | |||
659 | status = scic_oem_parameters_set(isci_host->core_controller, | ||
660 | &scic_oem_params | ||
661 | ); | ||
662 | |||
663 | if (status != SCI_SUCCESS) { | ||
664 | dev_warn(&isci_host->pdev->dev, | ||
665 | "%s: scic_oem_parameters_set failed\n", | ||
666 | __func__); | ||
667 | err = -ENODEV; | ||
668 | goto out; | ||
669 | } | ||
670 | |||
671 | |||
672 | status = scic_user_parameters_set(isci_host->core_controller, | ||
673 | &scic_user_params | ||
674 | ); | ||
675 | |||
676 | if (status != SCI_SUCCESS) { | ||
677 | dev_warn(&isci_host->pdev->dev, | ||
678 | "%s: scic_user_parameters_set failed\n", | ||
679 | __func__); | ||
680 | err = -ENODEV; | ||
681 | goto out; | ||
682 | } | ||
683 | |||
684 | status = scic_controller_initialize(isci_host->core_controller); | ||
685 | if (status != SCI_SUCCESS) { | ||
686 | dev_warn(&isci_host->pdev->dev, | ||
687 | "%s: scic_controller_initialize failed -" | ||
688 | " status = 0x%x\n", | ||
689 | __func__, status); | ||
690 | err = -ENODEV; | ||
691 | goto out; | ||
692 | } | ||
693 | |||
694 | /* @todo: use both MSI-X interrupts, and don't do indirect | ||
695 | * calls to the handlers just register direct calls | ||
696 | */ | ||
697 | if (isci_host->pdev->msix_enabled) { | ||
698 | status = scic_controller_get_handler_methods( | ||
699 | SCIC_MSIX_INTERRUPT_TYPE, | ||
700 | SCI_MSIX_DOUBLE_VECTOR, | ||
701 | handlers | ||
702 | ); | ||
703 | } else { | ||
704 | status = scic_controller_get_handler_methods( | ||
705 | SCIC_LEGACY_LINE_INTERRUPT_TYPE, | ||
706 | 0, | ||
707 | handlers | ||
708 | ); | ||
709 | } | ||
710 | |||
711 | if (status != SCI_SUCCESS) { | ||
712 | handlers->interrupt_handler = NULL; | ||
713 | handlers->completion_handler = NULL; | ||
714 | dev_err(&isci_host->pdev->dev, | ||
715 | "%s: scic_controller_get_handler_methods failed\n", | ||
716 | __func__); | ||
717 | } | ||
718 | |||
719 | tasklet_init(&isci_host->completion_tasklet, | ||
720 | isci_host_completion_routine, | ||
721 | (unsigned long)isci_host | ||
722 | ); | ||
723 | |||
724 | INIT_LIST_HEAD(&(isci_host->mdl_struct_list)); | ||
725 | |||
726 | INIT_LIST_HEAD(&isci_host->requests_to_complete); | ||
727 | INIT_LIST_HEAD(&isci_host->requests_to_abort); | ||
728 | |||
729 | /* populate mdl with dma memory. scu_mdl_allocate_coherent() */ | ||
730 | err = isci_host_mdl_allocate_coherent(isci_host); | ||
731 | |||
732 | if (err) | ||
733 | goto err_out; | ||
734 | |||
735 | /* | ||
736 | * keep the pool alloc size around, will use it for a bounds checking | ||
737 | * when trying to convert virtual addresses to physical addresses | ||
738 | */ | ||
739 | isci_host->dma_pool_alloc_size = sizeof(struct isci_request) + | ||
740 | scic_io_request_get_object_size(); | ||
741 | isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev, | ||
742 | isci_host->dma_pool_alloc_size, | ||
743 | SLAB_HWCACHE_ALIGN, 0); | ||
744 | |||
745 | if (!isci_host->dma_pool) { | ||
746 | err = -ENOMEM; | ||
747 | goto req_obj_err_out; | ||
748 | } | ||
749 | |||
750 | for (index = 0; index < SCI_MAX_PORTS; index++) { | ||
751 | isci_port_init(&isci_host->isci_ports[index], | ||
752 | isci_host, index); | ||
753 | } | ||
754 | |||
755 | for (index = 0; index < SCI_MAX_PHYS; index++) | ||
756 | isci_phy_init(&isci_host->phys[index], isci_host, index); | ||
757 | |||
758 | /* Why are we doing this? Is this even necessary? */ | ||
759 | memcpy(&isci_host->sas_addr[0], &isci_host->phys[0].sas_addr[0], | ||
760 | SAS_ADDR_SIZE); | ||
761 | |||
762 | /* Start the ports */ | ||
763 | for (index = 0; index < SCI_MAX_PORTS; index++) { | ||
764 | |||
765 | scic_controller_get_port_handle(controller, index, &scic_port); | ||
766 | scic_port_start(scic_port); | ||
767 | } | ||
768 | |||
769 | goto out; | ||
770 | |||
771 | /* SPB_Debug: destroy request object cache */ | ||
772 | req_obj_err_out: | ||
773 | /* SPB_Debug: destroy remote object cache */ | ||
774 | err_out: | ||
775 | /* SPB_Debug: undo controller init, construct and alloc, remove from parent | ||
776 | * controller list. */ | ||
777 | out: | ||
778 | if (fw) | ||
779 | release_firmware(fw); | ||
780 | return err; | ||
781 | } | ||
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h new file mode 100644 index 000000000000..3530076d6107 --- /dev/null +++ b/drivers/scsi/isci/host.h | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the isci_module initialization routines. | ||
58 | * | ||
59 | * host.h | ||
60 | */ | ||
61 | |||
62 | |||
63 | |||
64 | #if !defined(_SCI_HOST_H_) | ||
65 | #define _SCI_HOST_H_ | ||
66 | |||
67 | #include "phy.h" | ||
68 | /*#include "task.h"*/ | ||
69 | #include "timers.h" | ||
70 | #include "remote_device.h" | ||
71 | #include "scic_user_callback.h" | ||
72 | |||
73 | #define DRV_NAME "isci" | ||
74 | #define SCI_PCI_BAR_COUNT 2 | ||
75 | #define SCI_NUM_MSI_X_INT 2 | ||
76 | #define SCI_SMU_BAR 0 | ||
77 | #define SCI_SMU_BAR_SIZE (16*1024) | ||
78 | #define SCI_SCU_BAR 1 | ||
79 | #define SCI_SCU_BAR_SIZE (4*1024*1024) | ||
80 | #define SCI_IO_SPACE_BAR0 2 | ||
81 | #define SCI_IO_SPACE_BAR1 3 | ||
82 | #define SCI_MSIX_NORMAL_VECTOR 0 | ||
83 | #define SCI_MSIX_ERROR_VECTOR 1 | ||
84 | #define SCI_MSIX_SINGLE_VECTOR 1 | ||
85 | #define SCI_MSIX_DOUBLE_VECTOR 2 | ||
86 | #define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */ | ||
87 | #define SCIC_CONTROLLER_STOP_TIMEOUT 5000 | ||
88 | |||
89 | struct coherent_memory_info { | ||
90 | struct list_head node; | ||
91 | dma_addr_t dma_handle; | ||
92 | void *vaddr; | ||
93 | size_t size; | ||
94 | struct sci_physical_memory_descriptor *mde; | ||
95 | }; | ||
96 | |||
97 | struct isci_host { | ||
98 | struct scic_sds_controller *core_controller; | ||
99 | struct scic_controller_handler_methods scic_irq_handlers[SCI_NUM_MSI_X_INT]; | ||
100 | union scic_oem_parameters oem_parameters; | ||
101 | |||
102 | int id; /* unique within a given pci device */ | ||
103 | struct isci_timer_list timer_list_struct; | ||
104 | void *core_ctrl_memory; | ||
105 | struct dma_pool *dma_pool; | ||
106 | unsigned int dma_pool_alloc_size; | ||
107 | struct isci_phy phys[SCI_MAX_PHYS]; | ||
108 | |||
109 | /* isci_ports and sas_ports are implicitly parallel to the | ||
110 | * ports maintained by the core | ||
111 | */ | ||
112 | struct isci_port isci_ports[SCI_MAX_PORTS]; | ||
113 | struct asd_sas_port sas_ports[SCI_MAX_PORTS]; | ||
114 | struct sas_ha_struct sas_ha; | ||
115 | |||
116 | int can_queue; | ||
117 | spinlock_t queue_lock; | ||
118 | spinlock_t state_lock; | ||
119 | |||
120 | struct pci_dev *pdev; | ||
121 | u8 sas_addr[SAS_ADDR_SIZE]; | ||
122 | |||
123 | enum isci_status status; | ||
124 | struct Scsi_Host *shost; | ||
125 | struct tasklet_struct completion_tasklet; | ||
126 | struct list_head mdl_struct_list; | ||
127 | struct list_head requests_to_complete; | ||
128 | struct list_head requests_to_abort; | ||
129 | struct completion stop_complete; | ||
130 | struct completion start_complete; | ||
131 | spinlock_t scic_lock; | ||
132 | struct isci_host *next; | ||
133 | }; | ||
134 | |||
135 | |||
136 | /** | ||
137 | * struct isci_pci_info - This class represents the pci function containing the | ||
138 | * controllers. Depending on PCI SKU, there could be up to 2 controllers in | ||
139 | * the PCI function. | ||
140 | */ | ||
141 | #define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS) | ||
142 | |||
143 | struct isci_pci_info { | ||
144 | struct msix_entry msix_entries[SCI_MAX_MSIX_INT]; | ||
145 | int core_lib_array_index; | ||
146 | SCI_LIBRARY_HANDLE_T core_lib_handle; | ||
147 | struct isci_host *hosts; | ||
148 | }; | ||
149 | |||
150 | static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev) | ||
151 | { | ||
152 | return pci_get_drvdata(pdev); | ||
153 | } | ||
154 | |||
155 | #define for_each_isci_host(isci_host, pdev) \ | ||
156 | for (isci_host = to_pci_info(pdev)->hosts;\ | ||
157 | isci_host; isci_host = isci_host->next) | ||
158 | |||
159 | static inline | ||
160 | enum isci_status isci_host_get_state( | ||
161 | struct isci_host *isci_host) | ||
162 | { | ||
163 | return isci_host->status; | ||
164 | } | ||
165 | |||
166 | |||
167 | static inline void isci_host_change_state( | ||
168 | struct isci_host *isci_host, | ||
169 | enum isci_status status) | ||
170 | { | ||
171 | unsigned long flags; | ||
172 | |||
173 | dev_dbg(&isci_host->pdev->dev, | ||
174 | "%s: isci_host = %p, state = 0x%x", | ||
175 | __func__, | ||
176 | isci_host, | ||
177 | status); | ||
178 | spin_lock_irqsave(&isci_host->state_lock, flags); | ||
179 | isci_host->status = status; | ||
180 | spin_unlock_irqrestore(&isci_host->state_lock, flags); | ||
181 | |||
182 | } | ||
183 | |||
184 | static inline int isci_host_can_queue( | ||
185 | struct isci_host *isci_host, | ||
186 | int num) | ||
187 | { | ||
188 | int ret = 0; | ||
189 | unsigned long flags; | ||
190 | |||
191 | spin_lock_irqsave(&isci_host->queue_lock, flags); | ||
192 | if ((isci_host->can_queue - num) < 0) { | ||
193 | dev_dbg(&isci_host->pdev->dev, | ||
194 | "%s: isci_host->can_queue = %d\n", | ||
195 | __func__, | ||
196 | isci_host->can_queue); | ||
197 | ret = -SAS_QUEUE_FULL; | ||
198 | |||
199 | } else | ||
200 | isci_host->can_queue -= num; | ||
201 | |||
202 | spin_unlock_irqrestore(&isci_host->queue_lock, flags); | ||
203 | |||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | static inline void isci_host_can_dequeue( | ||
208 | struct isci_host *isci_host, | ||
209 | int num) | ||
210 | { | ||
211 | unsigned long flags; | ||
212 | |||
213 | spin_lock_irqsave(&isci_host->queue_lock, flags); | ||
214 | isci_host->can_queue += num; | ||
215 | spin_unlock_irqrestore(&isci_host->queue_lock, flags); | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * isci_host_from_sas_ha() - This accessor retrieves the isci_host object | ||
220 | * reference from the Linux sas_ha_struct reference. | ||
221 | * @ha_struct,: This parameter points to the Linux sas_ha_struct object | ||
222 | * | ||
223 | * A reference to the associated isci_host structure. | ||
224 | */ | ||
225 | #define isci_host_from_sas_ha(ha_struct) \ | ||
226 | ((struct isci_host *)(ha_struct)->lldd_ha) | ||
227 | |||
228 | /** | ||
229 | * isci_host_scan_finished() - | ||
230 | * | ||
231 | * This function is one of the SCSI Host Template functions. The SCSI midlayer | ||
232 | * calls this function during a target scan, approx. once every 10 millisecs. | ||
233 | */ | ||
234 | int isci_host_scan_finished( | ||
235 | struct Scsi_Host *, | ||
236 | unsigned long); | ||
237 | |||
238 | |||
239 | /** | ||
240 | * isci_host_scan_start() - | ||
241 | * | ||
242 | * This function is one of the SCSI Host Template function, called by the SCSI | ||
243 | * mid layer berfore a target scan begins. The core library controller start | ||
244 | * routine is called from here. | ||
245 | */ | ||
246 | void isci_host_scan_start( | ||
247 | struct Scsi_Host *); | ||
248 | |||
249 | /** | ||
250 | * isci_host_start_complete() - | ||
251 | * | ||
252 | * This function is called by the core library, through the ISCI Module, to | ||
253 | * indicate controller start status. | ||
254 | */ | ||
255 | void isci_host_start_complete( | ||
256 | struct isci_host *, | ||
257 | enum sci_status); | ||
258 | |||
259 | void isci_host_stop_complete( | ||
260 | struct isci_host *isci_host, | ||
261 | enum sci_status completion_status); | ||
262 | |||
263 | int isci_host_init(struct isci_host *); | ||
264 | |||
265 | void isci_host_init_controller_names( | ||
266 | struct isci_host *isci_host, | ||
267 | unsigned int controller_idx); | ||
268 | |||
269 | void isci_host_deinit( | ||
270 | struct isci_host *); | ||
271 | |||
272 | void isci_host_port_link_up( | ||
273 | struct isci_host *, | ||
274 | struct scic_sds_port *, | ||
275 | struct scic_sds_phy *); | ||
276 | int isci_host_dev_found(struct domain_device *); | ||
277 | |||
278 | void isci_host_remote_device_start_complete( | ||
279 | struct isci_host *, | ||
280 | struct isci_remote_device *, | ||
281 | enum sci_status); | ||
282 | |||
283 | #endif /* !defined(_SCI_HOST_H_) */ | ||
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c new file mode 100644 index 000000000000..07b072f3004d --- /dev/null +++ b/drivers/scsi/isci/init.c | |||
@@ -0,0 +1,613 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include <linux/kernel.h> | ||
57 | #include <linux/init.h> | ||
58 | #include <linux/module.h> | ||
59 | #include <asm/string.h> | ||
60 | #include "isci.h" | ||
61 | #include "task.h" | ||
62 | #include "sci_controller_constants.h" | ||
63 | #include "scic_remote_device.h" | ||
64 | #include "sci_environment.h" | ||
65 | |||
66 | static struct scsi_transport_template *isci_transport_template; | ||
67 | struct kmem_cache *isci_kmem_cache; | ||
68 | |||
69 | static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = { | ||
70 | { PCI_VDEVICE(INTEL, 0x1D61),}, | ||
71 | { PCI_VDEVICE(INTEL, 0x1D63),}, | ||
72 | { PCI_VDEVICE(INTEL, 0x1D65),}, | ||
73 | { PCI_VDEVICE(INTEL, 0x1D67),}, | ||
74 | { PCI_VDEVICE(INTEL, 0x1D69),}, | ||
75 | { PCI_VDEVICE(INTEL, 0x1D6B),}, | ||
76 | { PCI_VDEVICE(INTEL, 0x1D60),}, | ||
77 | { PCI_VDEVICE(INTEL, 0x1D62),}, | ||
78 | { PCI_VDEVICE(INTEL, 0x1D64),}, | ||
79 | { PCI_VDEVICE(INTEL, 0x1D66),}, | ||
80 | { PCI_VDEVICE(INTEL, 0x1D68),}, | ||
81 | { PCI_VDEVICE(INTEL, 0x1D6A),}, | ||
82 | {} | ||
83 | }; | ||
84 | |||
85 | static int __devinit isci_pci_probe( | ||
86 | struct pci_dev *pdev, | ||
87 | const struct pci_device_id *device_id_p); | ||
88 | |||
89 | static void __devexit isci_pci_remove(struct pci_dev *pdev); | ||
90 | |||
91 | MODULE_DEVICE_TABLE(pci, isci_id_table); | ||
92 | |||
93 | static struct pci_driver isci_pci_driver = { | ||
94 | .name = DRV_NAME, | ||
95 | .id_table = isci_id_table, | ||
96 | .probe = isci_pci_probe, | ||
97 | .remove = __devexit_p(isci_pci_remove), | ||
98 | }; | ||
99 | |||
100 | /* linux isci specific settings */ | ||
101 | int loglevel = 3; | ||
102 | module_param(loglevel, int, S_IRUGO | S_IWUSR); | ||
103 | |||
104 | #if defined(CONFIG_PBG_HBA_A0) | ||
105 | int isci_si_rev = ISCI_SI_REVA0; | ||
106 | #elif defined(CONFIG_PBG_HBA_A2) | ||
107 | int isci_si_rev = ISCI_SI_REVA2; | ||
108 | #else | ||
109 | int isci_si_rev = ISCI_SI_REVB0; | ||
110 | #endif | ||
111 | module_param(isci_si_rev, int, S_IRUGO | S_IWUSR); | ||
112 | MODULE_PARM_DESC(isci_si_rev, "override default si rev (0: A0 1: A2 2: B0)"); | ||
113 | |||
114 | static struct scsi_host_template isci_sht = { | ||
115 | |||
116 | .module = THIS_MODULE, | ||
117 | .name = DRV_NAME, | ||
118 | .queuecommand = sas_queuecommand, | ||
119 | .target_alloc = sas_target_alloc, | ||
120 | .slave_configure = sas_slave_configure, | ||
121 | .slave_destroy = sas_slave_destroy, | ||
122 | .scan_finished = isci_host_scan_finished, | ||
123 | .scan_start = isci_host_scan_start, | ||
124 | .change_queue_depth = sas_change_queue_depth, | ||
125 | .change_queue_type = sas_change_queue_type, | ||
126 | .bios_param = sas_bios_param, | ||
127 | .can_queue = ISCI_CAN_QUEUE_VAL, | ||
128 | .cmd_per_lun = 1, | ||
129 | .this_id = -1, | ||
130 | .sg_tablesize = SG_ALL, | ||
131 | .max_sectors = SCSI_DEFAULT_MAX_SECTORS, | ||
132 | .use_clustering = ENABLE_CLUSTERING, | ||
133 | .eh_device_reset_handler = sas_eh_device_reset_handler, | ||
134 | .eh_bus_reset_handler = isci_bus_reset_handler, | ||
135 | .slave_alloc = sas_slave_alloc, | ||
136 | .target_destroy = sas_target_destroy, | ||
137 | .ioctl = sas_ioctl, | ||
138 | }; | ||
139 | |||
140 | static struct sas_domain_function_template isci_transport_ops = { | ||
141 | |||
142 | /* The class calls these to notify the LLDD of an event. */ | ||
143 | .lldd_port_formed = isci_port_formed, | ||
144 | .lldd_port_deformed = isci_port_deformed, | ||
145 | |||
146 | /* The class calls these when a device is found or gone. */ | ||
147 | .lldd_dev_found = isci_remote_device_found, | ||
148 | .lldd_dev_gone = isci_remote_device_gone, | ||
149 | |||
150 | .lldd_execute_task = isci_task_execute_task, | ||
151 | /* Task Management Functions. Must be called from process context. */ | ||
152 | .lldd_abort_task = isci_task_abort_task, | ||
153 | .lldd_abort_task_set = isci_task_abort_task_set, | ||
154 | .lldd_clear_aca = isci_task_clear_aca, | ||
155 | .lldd_clear_task_set = isci_task_clear_task_set, | ||
156 | .lldd_I_T_nexus_reset = isci_task_I_T_nexus_reset, | ||
157 | .lldd_lu_reset = isci_task_lu_reset, | ||
158 | .lldd_query_task = isci_task_query_task, | ||
159 | |||
160 | /* Port and Adapter management */ | ||
161 | .lldd_clear_nexus_port = isci_task_clear_nexus_port, | ||
162 | .lldd_clear_nexus_ha = isci_task_clear_nexus_ha, | ||
163 | |||
164 | /* Phy management */ | ||
165 | .lldd_control_phy = isci_phy_control, | ||
166 | }; | ||
167 | |||
168 | |||
169 | /****************************************************************************** | ||
170 | * P R O T E C T E D M E T H O D S | ||
171 | ******************************************************************************/ | ||
172 | |||
173 | |||
174 | |||
175 | /** | ||
176 | * isci_register_sas_ha() - This method initializes various lldd | ||
177 | * specific members of the sas_ha struct and calls the libsas | ||
178 | * sas_register_ha() function. | ||
179 | * @isci_host: This parameter specifies the lldd specific wrapper for the | ||
180 | * libsas sas_ha struct. | ||
181 | * | ||
182 | * This method returns an error code indicating sucess or failure. The user | ||
183 | * should check for possible memory allocation error return otherwise, a zero | ||
184 | * indicates success. | ||
185 | */ | ||
186 | static int isci_register_sas_ha(struct isci_host *isci_host) | ||
187 | { | ||
188 | int i; | ||
189 | struct sas_ha_struct *sas_ha = &(isci_host->sas_ha); | ||
190 | struct asd_sas_phy **sas_phys; | ||
191 | struct asd_sas_port **sas_ports; | ||
192 | |||
193 | sas_phys = devm_kzalloc(&isci_host->pdev->dev, | ||
194 | SCI_MAX_PHYS * sizeof(void *), | ||
195 | GFP_KERNEL); | ||
196 | if (!sas_phys) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | sas_ports = devm_kzalloc(&isci_host->pdev->dev, | ||
200 | SCI_MAX_PORTS * sizeof(void *), | ||
201 | GFP_KERNEL); | ||
202 | if (!sas_ports) | ||
203 | return -ENOMEM; | ||
204 | |||
205 | /*----------------- Libsas Initialization Stuff---------------------- | ||
206 | * Set various fields in the sas_ha struct: | ||
207 | */ | ||
208 | |||
209 | sas_ha->sas_ha_name = DRV_NAME; | ||
210 | sas_ha->lldd_module = THIS_MODULE; | ||
211 | sas_ha->sas_addr = &(isci_host->sas_addr[0]); | ||
212 | |||
213 | /* set the array of phy and port structs. */ | ||
214 | for (i = 0; i < SCI_MAX_PHYS; i++) { | ||
215 | sas_phys[i] = &(isci_host->phys[i].sas_phy); | ||
216 | sas_ports[i] = &(isci_host->sas_ports[i]); | ||
217 | } | ||
218 | |||
219 | sas_ha->sas_phy = sas_phys; | ||
220 | sas_ha->sas_port = sas_ports; | ||
221 | sas_ha->num_phys = SCI_MAX_PHYS; | ||
222 | |||
223 | sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL; | ||
224 | sas_ha->lldd_max_execute_num = 1; | ||
225 | sas_ha->strict_wide_ports = 1; | ||
226 | |||
227 | sas_register_ha(sas_ha); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static void isci_unregister_sas_ha(struct isci_host *isci_host) | ||
233 | { | ||
234 | if (!isci_host) | ||
235 | return; | ||
236 | |||
237 | sas_unregister_ha(&(isci_host->sas_ha)); | ||
238 | |||
239 | sas_remove_host(isci_host->shost); | ||
240 | scsi_remove_host(isci_host->shost); | ||
241 | scsi_host_put(isci_host->shost); | ||
242 | } | ||
243 | |||
244 | static int __devinit isci_pci_init(struct pci_dev *pdev) | ||
245 | { | ||
246 | int err, bar_num, bar_mask; | ||
247 | void __iomem * const *iomap; | ||
248 | |||
249 | err = pcim_enable_device(pdev); | ||
250 | if (err) { | ||
251 | dev_err(&pdev->dev, | ||
252 | "failed enable PCI device %s!\n", | ||
253 | pci_name(pdev)); | ||
254 | return err; | ||
255 | } | ||
256 | |||
257 | for (bar_num = 0; bar_num < SCI_PCI_BAR_COUNT; bar_num++) | ||
258 | bar_mask |= 1 << (bar_num * 2); | ||
259 | |||
260 | err = pcim_iomap_regions(pdev, bar_mask, DRV_NAME); | ||
261 | if (err) | ||
262 | return err; | ||
263 | |||
264 | iomap = pcim_iomap_table(pdev); | ||
265 | if (!iomap) | ||
266 | return -ENOMEM; | ||
267 | |||
268 | pci_set_master(pdev); | ||
269 | |||
270 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); | ||
271 | if (err) { | ||
272 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
273 | if (err) | ||
274 | return err; | ||
275 | } | ||
276 | |||
277 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | ||
278 | if (err) { | ||
279 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
280 | if (err) | ||
281 | return err; | ||
282 | } | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static struct isci_host *isci_host_by_id(struct pci_dev *pdev, int id) | ||
288 | { | ||
289 | struct isci_host *h; | ||
290 | |||
291 | for_each_isci_host(h, pdev) | ||
292 | if (h->id == id) | ||
293 | return h; | ||
294 | return NULL; | ||
295 | } | ||
296 | |||
297 | static int num_controllers(struct pci_dev *pdev) | ||
298 | { | ||
299 | /* bar size alone can tell us if we are running with a dual controller | ||
300 | * part, no need to trust revision ids that might be under broken firmware | ||
301 | * control | ||
302 | */ | ||
303 | resource_size_t scu_bar_size = pci_resource_len(pdev, SCI_SCU_BAR*2); | ||
304 | resource_size_t smu_bar_size = pci_resource_len(pdev, SCI_SMU_BAR*2); | ||
305 | |||
306 | if (scu_bar_size >= SCI_SCU_BAR_SIZE*SCI_MAX_CONTROLLERS && | ||
307 | smu_bar_size >= SCI_SMU_BAR_SIZE*SCI_MAX_CONTROLLERS) | ||
308 | return SCI_MAX_CONTROLLERS; | ||
309 | else | ||
310 | return 1; | ||
311 | } | ||
312 | |||
313 | static int isci_setup_interrupts(struct pci_dev *pdev) | ||
314 | { | ||
315 | int err, i, num_msix; | ||
316 | struct isci_pci_info *pci_info = to_pci_info(pdev); | ||
317 | |||
318 | /* | ||
319 | * Determine the number of vectors associated with this | ||
320 | * PCI function. | ||
321 | */ | ||
322 | num_msix = num_controllers(pdev) * SCI_NUM_MSI_X_INT; | ||
323 | |||
324 | for (i = 0; i < num_msix; i++) | ||
325 | pci_info->msix_entries[i].entry = i; | ||
326 | |||
327 | err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix); | ||
328 | if (err) | ||
329 | goto intx; | ||
330 | |||
331 | for (i = 0; i < num_msix; i++) { | ||
332 | int id = i / SCI_NUM_MSI_X_INT; | ||
333 | struct msix_entry *msix = &pci_info->msix_entries[i]; | ||
334 | struct isci_host *isci_host = isci_host_by_id(pdev, id); | ||
335 | |||
336 | BUG_ON(!isci_host); | ||
337 | |||
338 | /* @todo: need to handle error case. */ | ||
339 | err = devm_request_irq(&pdev->dev, msix->vector, isci_isr, 0, | ||
340 | DRV_NAME"-msix", isci_host); | ||
341 | if (!err) | ||
342 | continue; | ||
343 | |||
344 | dev_info(&pdev->dev, "msix setup failed falling back to intx\n"); | ||
345 | while (i--) { | ||
346 | id = i / SCI_NUM_MSI_X_INT; | ||
347 | isci_host = isci_host_by_id(pdev, id); | ||
348 | msix = &pci_info->msix_entries[i]; | ||
349 | devm_free_irq(&pdev->dev, msix->vector, isci_host); | ||
350 | } | ||
351 | pci_disable_msix(pdev); | ||
352 | goto intx; | ||
353 | } | ||
354 | |||
355 | return 0; | ||
356 | |||
357 | intx: | ||
358 | err = devm_request_irq(&pdev->dev, pdev->irq, isci_legacy_isr, | ||
359 | IRQF_SHARED, DRV_NAME"-intx", pdev); | ||
360 | |||
361 | return err; | ||
362 | } | ||
363 | |||
364 | /** | ||
365 | * isci_parse_oem_parameters() - This method will take OEM parameters | ||
366 | * from the module init parameters and copy them to oem_params. This will | ||
367 | * only copy values that are not set to the module parameter default values | ||
368 | * @oem_parameters: This parameter specifies the controller default OEM | ||
369 | * parameters. It is expected that this has been initialized to the default | ||
370 | * parameters for the controller | ||
371 | * | ||
372 | * | ||
373 | */ | ||
374 | enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params, | ||
375 | int scu_index, | ||
376 | struct isci_firmware *fw) | ||
377 | { | ||
378 | int i; | ||
379 | |||
380 | /* check for valid inputs */ | ||
381 | if (!(scu_index >= 0 | ||
382 | && scu_index < SCI_MAX_CONTROLLERS | ||
383 | && oem_params != NULL)) { | ||
384 | return SCI_FAILURE; | ||
385 | } | ||
386 | |||
387 | for (i = 0; i < SCI_MAX_PHYS; i++) { | ||
388 | int array_idx = i + (SCI_MAX_PHYS * scu_index); | ||
389 | u64 sas_addr = fw->sas_addrs[array_idx]; | ||
390 | |||
391 | if (sas_addr != 0) { | ||
392 | oem_params->sds1.phys[i].sas_address.low = | ||
393 | (u32)(sas_addr & 0xffffffff); | ||
394 | oem_params->sds1.phys[i].sas_address.high = | ||
395 | (u32)((sas_addr >> 32) & 0xffffffff); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | for (i = 0; i < SCI_MAX_PORTS; i++) { | ||
400 | int array_idx = i + (SCI_MAX_PORTS * scu_index); | ||
401 | u32 pmask = fw->phy_masks[array_idx]; | ||
402 | |||
403 | oem_params->sds1.ports[i].phy_mask = pmask; | ||
404 | } | ||
405 | |||
406 | return SCI_SUCCESS; | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * isci_parse_user_parameters() - This method will take user parameters | ||
411 | * from the module init parameters and copy them to user_params. This will | ||
412 | * only copy values that are not set to the module parameter default values | ||
413 | * @user_parameters: This parameter specifies the controller default user | ||
414 | * parameters. It is expected that this has been initialized to the default | ||
415 | * parameters for the controller | ||
416 | * | ||
417 | * | ||
418 | */ | ||
419 | enum sci_status isci_parse_user_parameters( | ||
420 | union scic_user_parameters *user_params, | ||
421 | int scu_index, | ||
422 | struct isci_firmware *fw) | ||
423 | { | ||
424 | int i; | ||
425 | |||
426 | if (!(scu_index >= 0 | ||
427 | && scu_index < SCI_MAX_CONTROLLERS | ||
428 | && user_params != NULL)) { | ||
429 | return SCI_FAILURE; | ||
430 | } | ||
431 | |||
432 | for (i = 0; i < SCI_MAX_PORTS; i++) { | ||
433 | int array_idx = i + (SCI_MAX_PORTS * scu_index); | ||
434 | u32 gen = fw->phy_gens[array_idx]; | ||
435 | |||
436 | user_params->sds1.phys[i].max_speed_generation = gen; | ||
437 | |||
438 | } | ||
439 | |||
440 | return SCI_SUCCESS; | ||
441 | } | ||
442 | |||
443 | static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) | ||
444 | { | ||
445 | struct isci_host *isci_host; | ||
446 | struct Scsi_Host *shost; | ||
447 | int err; | ||
448 | |||
449 | isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL); | ||
450 | if (!isci_host) | ||
451 | return NULL; | ||
452 | |||
453 | isci_host->pdev = pdev; | ||
454 | isci_host->id = id; | ||
455 | |||
456 | shost = scsi_host_alloc(&isci_sht, sizeof(void *)); | ||
457 | if (!shost) | ||
458 | return NULL; | ||
459 | isci_host->shost = shost; | ||
460 | |||
461 | err = isci_host_init(isci_host); | ||
462 | if (err) | ||
463 | goto err_shost; | ||
464 | |||
465 | SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha; | ||
466 | isci_host->sas_ha.core.shost = shost; | ||
467 | shost->transportt = isci_transport_template; | ||
468 | |||
469 | shost->max_id = ~0; | ||
470 | shost->max_lun = ~0; | ||
471 | shost->max_cmd_len = MAX_COMMAND_SIZE; | ||
472 | |||
473 | err = scsi_add_host(shost, &pdev->dev); | ||
474 | if (err) | ||
475 | goto err_shost; | ||
476 | |||
477 | err = isci_register_sas_ha(isci_host); | ||
478 | if (err) | ||
479 | goto err_shost_remove; | ||
480 | |||
481 | return isci_host; | ||
482 | |||
483 | err_shost_remove: | ||
484 | scsi_remove_host(shost); | ||
485 | err_shost: | ||
486 | scsi_host_put(shost); | ||
487 | |||
488 | return NULL; | ||
489 | } | ||
490 | |||
491 | static void check_si_rev(struct pci_dev *pdev) | ||
492 | { | ||
493 | if (num_controllers(pdev) > 1) | ||
494 | isci_si_rev = ISCI_SI_REVB0; | ||
495 | else { | ||
496 | switch (pdev->revision) { | ||
497 | case 0: | ||
498 | case 1: | ||
499 | /* if the id is ambiguous don't update isci_si_rev */ | ||
500 | break; | ||
501 | case 3: | ||
502 | isci_si_rev = ISCI_SI_REVA2; | ||
503 | break; | ||
504 | default: | ||
505 | case 4: | ||
506 | isci_si_rev = ISCI_SI_REVB0; | ||
507 | break; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n", | ||
512 | isci_si_rev == ISCI_SI_REVA0 ? "A0" : | ||
513 | isci_si_rev == ISCI_SI_REVA2 ? "A2" : "B0", pdev->revision); | ||
514 | |||
515 | } | ||
516 | |||
517 | static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
518 | { | ||
519 | struct isci_pci_info *pci_info; | ||
520 | int err, i; | ||
521 | struct isci_host *isci_host; | ||
522 | |||
523 | check_si_rev(pdev); | ||
524 | |||
525 | pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL); | ||
526 | if (!pci_info) | ||
527 | return -ENOMEM; | ||
528 | pci_set_drvdata(pdev, pci_info); | ||
529 | |||
530 | err = isci_pci_init(pdev); | ||
531 | if (err) | ||
532 | return err; | ||
533 | |||
534 | for (i = 0; i < num_controllers(pdev); i++) { | ||
535 | struct isci_host *h = isci_host_alloc(pdev, i); | ||
536 | |||
537 | if (!h) { | ||
538 | err = -ENOMEM; | ||
539 | goto err_host_alloc; | ||
540 | } | ||
541 | |||
542 | h->next = pci_info->hosts; | ||
543 | pci_info->hosts = h; | ||
544 | } | ||
545 | |||
546 | err = isci_setup_interrupts(pdev); | ||
547 | if (err) | ||
548 | goto err_host_alloc; | ||
549 | |||
550 | for_each_isci_host(isci_host, pdev) | ||
551 | scsi_scan_host(isci_host->shost); | ||
552 | |||
553 | return 0; | ||
554 | |||
555 | err_host_alloc: | ||
556 | for_each_isci_host(isci_host, pdev) | ||
557 | isci_unregister_sas_ha(isci_host); | ||
558 | return err; | ||
559 | } | ||
560 | |||
561 | static void __devexit isci_pci_remove(struct pci_dev *pdev) | ||
562 | { | ||
563 | struct isci_host *isci_host; | ||
564 | |||
565 | for_each_isci_host(isci_host, pdev) { | ||
566 | isci_unregister_sas_ha(isci_host); | ||
567 | isci_host_deinit(isci_host); | ||
568 | scic_controller_disable_interrupts(isci_host->core_controller); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | static __init int isci_init(void) | ||
573 | { | ||
574 | int err = -ENOMEM; | ||
575 | |||
576 | pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME); | ||
577 | |||
578 | isci_kmem_cache = kmem_cache_create(DRV_NAME, | ||
579 | sizeof(struct isci_remote_device) + | ||
580 | scic_remote_device_get_object_size(), | ||
581 | 0, 0, NULL); | ||
582 | if (!isci_kmem_cache) | ||
583 | return err; | ||
584 | |||
585 | isci_transport_template = sas_domain_attach_transport(&isci_transport_ops); | ||
586 | if (!isci_transport_template) | ||
587 | goto err_kmem; | ||
588 | |||
589 | err = pci_register_driver(&isci_pci_driver); | ||
590 | if (err) | ||
591 | goto err_sas; | ||
592 | |||
593 | return 0; | ||
594 | |||
595 | err_sas: | ||
596 | sas_release_transport(isci_transport_template); | ||
597 | err_kmem: | ||
598 | kmem_cache_destroy(isci_kmem_cache); | ||
599 | |||
600 | return err; | ||
601 | } | ||
602 | |||
603 | static __exit void isci_exit(void) | ||
604 | { | ||
605 | pci_unregister_driver(&isci_pci_driver); | ||
606 | sas_release_transport(isci_transport_template); | ||
607 | kmem_cache_destroy(isci_kmem_cache); | ||
608 | } | ||
609 | |||
610 | MODULE_LICENSE("Dual BSD/GPL"); | ||
611 | MODULE_FIRMWARE(ISCI_FW_NAME); | ||
612 | module_init(isci_init); | ||
613 | module_exit(isci_exit); | ||
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h new file mode 100644 index 000000000000..7d984f408f24 --- /dev/null +++ b/drivers/scsi/isci/isci.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the isci_module object definition. | ||
58 | * | ||
59 | * isci.h | ||
60 | */ | ||
61 | |||
62 | #if !defined(_SCI_MODULE_H_) | ||
63 | #define _SCI_MODULE_H_ | ||
64 | |||
65 | /** | ||
66 | * This file contains the SCI low level driver interface to the SCI and Libsas | ||
67 | * Libraries. | ||
68 | * | ||
69 | * isci.h | ||
70 | */ | ||
71 | |||
72 | #include <linux/kernel.h> | ||
73 | #include <linux/list.h> | ||
74 | #include <linux/types.h> | ||
75 | #include <linux/spinlock.h> | ||
76 | #include <linux/interrupt.h> | ||
77 | #include <linux/firmware.h> | ||
78 | #include <linux/bug.h> | ||
79 | #include <scsi/libsas.h> | ||
80 | #include <scsi/scsi.h> | ||
81 | |||
82 | #include "sci_types.h" | ||
83 | #include "sci_base_controller.h" | ||
84 | #include "scic_controller.h" | ||
85 | #include "host.h" | ||
86 | #include "timers.h" | ||
87 | #include "sci_status.h" | ||
88 | |||
89 | extern int loglevel; | ||
90 | extern struct kmem_cache *isci_kmem_cache; | ||
91 | |||
92 | #define ISCI_FW_NAME "isci/isci_firmware.bin" | ||
93 | |||
94 | #define ISCI_FIRMWARE_MIN_SIZE 149 | ||
95 | |||
96 | #define ISCI_FW_IDSIZE 12 | ||
97 | #define ISCI_FW_VER_OFS ISCI_FW_IDSIZE | ||
98 | #define ISCI_FW_SUBVER_OFS ISCI_FW_VER_OFS + 1 | ||
99 | #define ISCI_FW_DATA_OFS ISCI_FW_SUBVER_OFS + 1 | ||
100 | |||
101 | #define ISCI_FW_HDR_PHYMASK 0x1 | ||
102 | #define ISCI_FW_HDR_PHYGEN 0x2 | ||
103 | #define ISCI_FW_HDR_SASADDR 0x3 | ||
104 | #define ISCI_FW_HDR_EOF 0xff | ||
105 | |||
106 | struct isci_firmware { | ||
107 | const u8 *id; | ||
108 | u8 version; | ||
109 | u8 subversion; | ||
110 | const u32 *phy_masks; | ||
111 | u8 phy_masks_size; | ||
112 | const u32 *phy_gens; | ||
113 | u8 phy_gens_size; | ||
114 | const u64 *sas_addrs; | ||
115 | u8 sas_addrs_size; | ||
116 | }; | ||
117 | |||
118 | irqreturn_t isci_isr(int vec, void *data); | ||
119 | irqreturn_t isci_legacy_isr(int vec, void *data); | ||
120 | |||
121 | enum sci_status isci_parse_oem_parameters( | ||
122 | union scic_oem_parameters *oem_params, | ||
123 | int scu_index, | ||
124 | struct isci_firmware *fw); | ||
125 | |||
126 | enum sci_status isci_parse_user_parameters( | ||
127 | union scic_user_parameters *user_params, | ||
128 | int scu_index, | ||
129 | struct isci_firmware *fw); | ||
130 | |||
131 | #ifdef ISCI_SLAVE_ALLOC | ||
132 | extern int ISCI_SLAVE_ALLOC(struct scsi_device *scsi_dev); | ||
133 | #endif /* ISCI_SLAVE_ALLOC */ | ||
134 | |||
135 | #ifdef ISCI_SLAVE_DESTROY | ||
136 | extern void ISCI_SLAVE_DESTROY(struct scsi_device *scsi_dev); | ||
137 | #endif /* ISCI_SLAVE_DESTROY */ | ||
138 | #endif /* !defined(_SCI_MODULE_H_) */ | ||
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c new file mode 100644 index 000000000000..fbda570d25e1 --- /dev/null +++ b/drivers/scsi/isci/phy.c | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "isci.h" | ||
57 | #include "phy.h" | ||
58 | #include "scic_port.h" | ||
59 | #include "scic_config_parameters.h" | ||
60 | |||
61 | |||
62 | /** | ||
63 | * isci_phy_init() - This function is called by the probe function to | ||
64 | * initialize the phy objects. This func assumes that the isci_port objects | ||
65 | * associated with the SCU have been initialized. | ||
66 | * @isci_phy: This parameter specifies the isci_phy object to initialize | ||
67 | * @isci_host: This parameter specifies the parent SCU host object for this | ||
68 | * isci_phy | ||
69 | * @index: This parameter specifies which SCU phy associates with this | ||
70 | * isci_phy. Generally, SCU phy 0 relates isci_phy 0, etc. | ||
71 | * | ||
72 | */ | ||
73 | void isci_phy_init( | ||
74 | struct isci_phy *phy, | ||
75 | struct isci_host *isci_host, | ||
76 | int index) | ||
77 | { | ||
78 | struct scic_sds_controller *controller = isci_host->core_controller; | ||
79 | struct scic_sds_phy *scic_phy; | ||
80 | union scic_oem_parameters oem_parameters; | ||
81 | enum sci_status status = SCI_SUCCESS; | ||
82 | |||
83 | /*--------------- SCU_Phy Initialization Stuff -----------------------*/ | ||
84 | |||
85 | status = scic_controller_get_phy_handle(controller, index, &scic_phy); | ||
86 | if (status == SCI_SUCCESS) { | ||
87 | sci_object_set_association(scic_phy, (void *)phy); | ||
88 | phy->sci_phy_handle = scic_phy; | ||
89 | } else | ||
90 | dev_err(&isci_host->pdev->dev, | ||
91 | "failed scic_controller_get_phy_handle\n"); | ||
92 | |||
93 | scic_oem_parameters_get(controller, &oem_parameters); | ||
94 | |||
95 | phy->sas_addr[0] = oem_parameters.sds1.phys[index].sas_address.low | ||
96 | & 0xFF; | ||
97 | phy->sas_addr[1] = (oem_parameters.sds1.phys[index].sas_address.low | ||
98 | >> 8) & 0xFF; | ||
99 | phy->sas_addr[2] = (oem_parameters.sds1.phys[index].sas_address.low | ||
100 | >> 16) & 0xFF; | ||
101 | phy->sas_addr[3] = (oem_parameters.sds1.phys[index].sas_address.low | ||
102 | >> 24) & 0xFF; | ||
103 | phy->sas_addr[4] = oem_parameters.sds1.phys[index].sas_address.high | ||
104 | & 0xFF; | ||
105 | phy->sas_addr[5] = (oem_parameters.sds1.phys[index].sas_address.high | ||
106 | >> 8) & 0xFF; | ||
107 | phy->sas_addr[6] = (oem_parameters.sds1.phys[index].sas_address.high | ||
108 | >> 16) & 0xFF; | ||
109 | phy->sas_addr[7] = (oem_parameters.sds1.phys[index].sas_address.high | ||
110 | >> 24) & 0xFF; | ||
111 | |||
112 | phy->isci_port = NULL; | ||
113 | phy->sas_phy.enabled = 0; | ||
114 | phy->sas_phy.id = index; | ||
115 | phy->sas_phy.sas_addr = &phy->sas_addr[0]; | ||
116 | phy->sas_phy.frame_rcvd = (u8 *)&phy->frame_rcvd; | ||
117 | phy->sas_phy.ha = &isci_host->sas_ha; | ||
118 | phy->sas_phy.lldd_phy = phy; | ||
119 | phy->sas_phy.enabled = 1; | ||
120 | phy->sas_phy.class = SAS; | ||
121 | phy->sas_phy.iproto = SAS_PROTOCOL_ALL; | ||
122 | phy->sas_phy.tproto = 0; | ||
123 | phy->sas_phy.type = PHY_TYPE_PHYSICAL; | ||
124 | phy->sas_phy.role = PHY_ROLE_INITIATOR; | ||
125 | phy->sas_phy.oob_mode = OOB_NOT_CONNECTED; | ||
126 | phy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN; | ||
127 | memset((u8 *)&phy->frame_rcvd, 0, sizeof(phy->frame_rcvd)); | ||
128 | } | ||
129 | |||
130 | |||
131 | /** | ||
132 | * isci_phy_control() - This function is one of the SAS Domain Template | ||
133 | * functions. This is a phy management function. | ||
134 | * @phy: This parameter specifies the sphy being controlled. | ||
135 | * @func: This parameter specifies the phy control function being invoked. | ||
136 | * @buf: This parameter is specific to the phy function being invoked. | ||
137 | * | ||
138 | * status, zero indicates success. | ||
139 | */ | ||
140 | int isci_phy_control( | ||
141 | struct asd_sas_phy *phy, | ||
142 | enum phy_func func, | ||
143 | void *buf) | ||
144 | { | ||
145 | int ret = TMF_RESP_FUNC_COMPLETE; | ||
146 | struct isci_phy *isci_phy_ptr = (struct isci_phy *)phy->lldd_phy; | ||
147 | struct isci_port *isci_port_ptr = NULL; | ||
148 | |||
149 | if (isci_phy_ptr != NULL) | ||
150 | isci_port_ptr = isci_phy_ptr->isci_port; | ||
151 | |||
152 | if ((isci_phy_ptr == NULL) || (isci_port_ptr == NULL)) { | ||
153 | pr_err("%s: asd_sas_phy %p: lldd_phy %p or " | ||
154 | "isci_port %p == NULL!\n", | ||
155 | __func__, phy, isci_phy_ptr, isci_port_ptr); | ||
156 | return TMF_RESP_FUNC_FAILED; | ||
157 | } | ||
158 | |||
159 | pr_debug("%s: phy %p; func %d; buf %p; isci phy %p, port %p\n", | ||
160 | __func__, phy, func, buf, isci_phy_ptr, isci_port_ptr); | ||
161 | |||
162 | switch (func) { | ||
163 | case PHY_FUNC_HARD_RESET: | ||
164 | case PHY_FUNC_LINK_RESET: | ||
165 | |||
166 | /* Perform the port reset. */ | ||
167 | ret = isci_port_perform_hard_reset(isci_port_ptr, isci_phy_ptr); | ||
168 | |||
169 | break; | ||
170 | |||
171 | case PHY_FUNC_DISABLE: | ||
172 | default: | ||
173 | pr_debug("%s: phy %p; func %d NOT IMPLEMENTED!\n", | ||
174 | __func__, phy, func); | ||
175 | ret = TMF_RESP_FUNC_FAILED; | ||
176 | break; | ||
177 | } | ||
178 | return ret; | ||
179 | } | ||
diff --git a/drivers/scsi/isci/phy.h b/drivers/scsi/isci/phy.h new file mode 100644 index 000000000000..44b727f1c455 --- /dev/null +++ b/drivers/scsi/isci/phy.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | |||
57 | #if !defined(_ISCI_PHY_H_) | ||
58 | #define _ISCI_PHY_H_ | ||
59 | |||
60 | #include "port.h" | ||
61 | #include "host.h" | ||
62 | #include <scsi/libsas.h> | ||
63 | |||
64 | |||
65 | /** | ||
66 | * struct isci_phy - This class implements the ISCI specific representation of | ||
67 | * the phy object. | ||
68 | * | ||
69 | * | ||
70 | */ | ||
71 | |||
72 | struct isci_phy { | ||
73 | |||
74 | struct scic_sds_phy *sci_phy_handle; | ||
75 | |||
76 | struct asd_sas_phy sas_phy; | ||
77 | struct sas_identify_frame *frame; | ||
78 | struct isci_port *isci_port; | ||
79 | u8 sas_addr[SAS_ADDR_SIZE]; | ||
80 | |||
81 | union { | ||
82 | |||
83 | u8 aif[sizeof(struct sci_sas_identify_address_frame)]; | ||
84 | u8 fis[sizeof(struct sata_fis_reg_d2h)]; | ||
85 | |||
86 | } frame_rcvd; | ||
87 | }; | ||
88 | |||
89 | #define to_isci_phy(p) \ | ||
90 | container_of(p, struct isci_phy, sas_phy); | ||
91 | |||
92 | struct isci_host; | ||
93 | |||
94 | void isci_phy_init( | ||
95 | struct isci_phy *phy, | ||
96 | struct isci_host *isci_host, | ||
97 | int index); | ||
98 | |||
99 | int isci_phy_control( | ||
100 | struct asd_sas_phy *phy, | ||
101 | enum phy_func func, | ||
102 | void *buf); | ||
103 | |||
104 | #endif /* !defined(_ISCI_PHY_H_) */ | ||
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c new file mode 100644 index 000000000000..2343f6556428 --- /dev/null +++ b/drivers/scsi/isci/port.c | |||
@@ -0,0 +1,484 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the isci port implementation. | ||
58 | * | ||
59 | * | ||
60 | */ | ||
61 | |||
62 | |||
63 | #include <linux/workqueue.h> | ||
64 | #include "isci.h" | ||
65 | #include "scic_io_request.h" | ||
66 | #include "scic_remote_device.h" | ||
67 | #include "scic_phy.h" | ||
68 | #include "scic_sds_phy.h" | ||
69 | #include "scic_port.h" | ||
70 | #include "port.h" | ||
71 | #include "request.h" | ||
72 | |||
73 | static void isci_port_change_state( | ||
74 | struct isci_port *isci_port, | ||
75 | enum isci_status status); | ||
76 | |||
77 | |||
78 | |||
79 | /** | ||
80 | * isci_port_init() - This function initializes the given isci_port object. | ||
81 | * @isci_port: This parameter specifies the port object to be initialized. | ||
82 | * @isci_host: This parameter specifies parent controller object for the port. | ||
83 | * @index: This parameter specifies which SCU port the isci_port associates | ||
84 | * with. Generally, SCU port 0 relates to isci_port 0, etc. | ||
85 | * | ||
86 | */ | ||
87 | void isci_port_init( | ||
88 | struct isci_port *isci_port, | ||
89 | struct isci_host *isci_host, | ||
90 | int index) | ||
91 | { | ||
92 | struct scic_sds_port *scic_port; | ||
93 | struct scic_sds_controller *controller = isci_host->core_controller; | ||
94 | |||
95 | INIT_LIST_HEAD(&isci_port->remote_dev_list); | ||
96 | INIT_LIST_HEAD(&isci_port->domain_dev_list); | ||
97 | spin_lock_init(&isci_port->remote_device_lock); | ||
98 | spin_lock_init(&isci_port->state_lock); | ||
99 | init_completion(&isci_port->start_complete); | ||
100 | isci_port->isci_host = isci_host; | ||
101 | isci_port_change_state(isci_port, isci_freed); | ||
102 | |||
103 | (void)scic_controller_get_port_handle(controller, index, &scic_port); | ||
104 | sci_object_set_association(scic_port, isci_port); | ||
105 | isci_port->sci_port_handle = scic_port; | ||
106 | } | ||
107 | |||
108 | |||
109 | /** | ||
110 | * isci_port_get_state() - This function gets the status of the port object. | ||
111 | * @isci_port: This parameter points to the isci_port object | ||
112 | * | ||
113 | * status of the object as a isci_status enum. | ||
114 | */ | ||
115 | enum isci_status isci_port_get_state( | ||
116 | struct isci_port *isci_port) | ||
117 | { | ||
118 | return isci_port->status; | ||
119 | } | ||
120 | |||
121 | static void isci_port_change_state( | ||
122 | struct isci_port *isci_port, | ||
123 | enum isci_status status) | ||
124 | { | ||
125 | unsigned long flags; | ||
126 | |||
127 | dev_dbg(&isci_port->isci_host->pdev->dev, | ||
128 | "%s: isci_port = %p, state = 0x%x\n", | ||
129 | __func__, isci_port, status); | ||
130 | |||
131 | spin_lock_irqsave(&isci_port->state_lock, flags); | ||
132 | isci_port->status = status; | ||
133 | spin_unlock_irqrestore(&isci_port->state_lock, flags); | ||
134 | } | ||
135 | |||
136 | void isci_port_bc_change_received( | ||
137 | struct isci_host *isci_host, | ||
138 | struct scic_sds_port *port, | ||
139 | struct scic_sds_phy *phy) | ||
140 | { | ||
141 | struct isci_phy *isci_phy = | ||
142 | (struct isci_phy *)sci_object_get_association(phy); | ||
143 | |||
144 | dev_dbg(&isci_host->pdev->dev, | ||
145 | "%s: isci_phy = %p, sas_phy = %p\n", | ||
146 | __func__, | ||
147 | isci_phy, | ||
148 | &isci_phy->sas_phy); | ||
149 | |||
150 | isci_host->sas_ha.notify_port_event( | ||
151 | &isci_phy->sas_phy, | ||
152 | PORTE_BROADCAST_RCVD | ||
153 | ); | ||
154 | |||
155 | scic_port_enable_broadcast_change_notification(port); | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * isci_port_link_up() - This function is called by the sci core when a link | ||
160 | * becomes active. the identify address frame is retrieved from the core and | ||
161 | * a notify port event is sent to libsas. | ||
162 | * @isci_host: This parameter specifies the isci host object. | ||
163 | * @port: This parameter specifies the sci port with the active link. | ||
164 | * @phy: This parameter specifies the sci phy with the active link. | ||
165 | * | ||
166 | */ | ||
167 | void isci_port_link_up( | ||
168 | struct isci_host *isci_host, | ||
169 | struct scic_sds_port *port, | ||
170 | struct scic_sds_phy *phy) | ||
171 | { | ||
172 | unsigned long flags; | ||
173 | struct scic_port_properties properties; | ||
174 | struct isci_phy *isci_phy | ||
175 | = (struct isci_phy *)sci_object_get_association(phy); | ||
176 | struct isci_port *isci_port | ||
177 | = (struct isci_port *)sci_object_get_association(port); | ||
178 | enum sci_status call_status; | ||
179 | unsigned long success = true; | ||
180 | |||
181 | BUG_ON(isci_phy->isci_port != NULL); | ||
182 | isci_phy->isci_port = isci_port; | ||
183 | |||
184 | dev_dbg(&isci_host->pdev->dev, | ||
185 | "%s: isci_port = %p\n", | ||
186 | __func__, isci_port); | ||
187 | |||
188 | spin_lock_irqsave(&isci_phy->sas_phy.frame_rcvd_lock, flags); | ||
189 | |||
190 | isci_port_change_state(isci_phy->isci_port, isci_starting); | ||
191 | |||
192 | scic_port_get_properties(port, &properties); | ||
193 | |||
194 | if (properties.remote.protocols.u.bits.stp_target) { | ||
195 | |||
196 | struct scic_sata_phy_properties sata_phy_properties; | ||
197 | |||
198 | isci_phy->sas_phy.oob_mode = SATA_OOB_MODE; | ||
199 | |||
200 | /* Get a copy of the signature fis for libsas */ | ||
201 | call_status = scic_sata_phy_get_properties(phy, | ||
202 | &sata_phy_properties); | ||
203 | |||
204 | /* | ||
205 | * XXX I am concerned about this "assert". shouldn't we | ||
206 | * handle the return appropriately? | ||
207 | */ | ||
208 | BUG_ON(call_status != SCI_SUCCESS); | ||
209 | |||
210 | memcpy(isci_phy->frame_rcvd.fis, | ||
211 | &sata_phy_properties.signature_fis, | ||
212 | sizeof(struct sata_fis_reg_d2h)); | ||
213 | |||
214 | isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sata_fis_reg_d2h); | ||
215 | |||
216 | /* | ||
217 | * For direct-attached SATA devices, the SCI core will | ||
218 | * automagically assign a SAS address to the end device | ||
219 | * for the purpose of creating a port. This SAS address | ||
220 | * will not be the same as assigned to the PHY and needs | ||
221 | * to be obtained from struct scic_port_properties properties. | ||
222 | */ | ||
223 | |||
224 | BUG_ON(((size_t)SAS_ADDR_SIZE / 2) | ||
225 | != sizeof(properties.remote.sas_address.low)); | ||
226 | |||
227 | memcpy(&isci_phy->sas_phy.attached_sas_addr[0], | ||
228 | &properties.remote.sas_address.low, | ||
229 | SAS_ADDR_SIZE / 2); | ||
230 | |||
231 | memcpy(&isci_phy->sas_phy.attached_sas_addr[4], | ||
232 | &properties.remote.sas_address.high, | ||
233 | SAS_ADDR_SIZE / 2); | ||
234 | |||
235 | } else if (properties.remote.protocols.u.bits.ssp_target || | ||
236 | properties.remote.protocols.u.bits.smp_target) { | ||
237 | |||
238 | struct scic_sas_phy_properties sas_phy_properties; | ||
239 | |||
240 | isci_phy->sas_phy.oob_mode = SAS_OOB_MODE; | ||
241 | |||
242 | /* Get a copy of the identify address frame for libsas */ | ||
243 | call_status = scic_sas_phy_get_properties(phy, | ||
244 | &sas_phy_properties); | ||
245 | |||
246 | BUG_ON(call_status != SCI_SUCCESS); | ||
247 | |||
248 | memcpy(isci_phy->frame_rcvd.aif, | ||
249 | &(sas_phy_properties.received_iaf), | ||
250 | sizeof(struct sci_sas_identify_address_frame)); | ||
251 | |||
252 | isci_phy->sas_phy.frame_rcvd_size | ||
253 | = sizeof(struct sci_sas_identify_address_frame); | ||
254 | |||
255 | /* Copy the attached SAS address from the IAF */ | ||
256 | memcpy(isci_phy->sas_phy.attached_sas_addr, | ||
257 | ((struct sas_identify_frame *) | ||
258 | (&isci_phy->frame_rcvd.aif))->sas_addr, | ||
259 | SAS_ADDR_SIZE); | ||
260 | |||
261 | } else { | ||
262 | dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__); | ||
263 | success = false; | ||
264 | } | ||
265 | |||
266 | spin_unlock_irqrestore(&isci_phy->sas_phy.frame_rcvd_lock, flags); | ||
267 | |||
268 | /* Notify libsas that we have an address frame, if indeed | ||
269 | * we've found an SSP, SMP, or STP target */ | ||
270 | if (success) | ||
271 | isci_host->sas_ha.notify_port_event(&isci_phy->sas_phy, | ||
272 | PORTE_BYTES_DMAED); | ||
273 | } | ||
274 | |||
275 | |||
276 | /** | ||
277 | * isci_port_link_down() - This function is called by the sci core when a link | ||
278 | * becomes inactive. | ||
279 | * @isci_host: This parameter specifies the isci host object. | ||
280 | * @phy: This parameter specifies the isci phy with the active link. | ||
281 | * @port: This parameter specifies the isci port with the active link. | ||
282 | * | ||
283 | */ | ||
284 | void isci_port_link_down( | ||
285 | struct isci_host *isci_host, | ||
286 | struct isci_phy *isci_phy, | ||
287 | struct isci_port *isci_port) | ||
288 | { | ||
289 | struct isci_remote_device *isci_device; | ||
290 | |||
291 | dev_dbg(&isci_host->pdev->dev, | ||
292 | "%s: isci_port = %p\n", __func__, isci_port); | ||
293 | |||
294 | if (isci_port) { | ||
295 | |||
296 | /* check to see if this is the last phy on this port. */ | ||
297 | if (isci_phy->sas_phy.port | ||
298 | && isci_phy->sas_phy.port->num_phys == 1) { | ||
299 | |||
300 | /* change the state for all devices on this port. | ||
301 | * The next task sent to this device will be returned | ||
302 | * as SAS_TASK_UNDELIVERED, and the scsi mid layer | ||
303 | * will remove the target | ||
304 | */ | ||
305 | list_for_each_entry(isci_device, | ||
306 | &isci_port->remote_dev_list, | ||
307 | node) { | ||
308 | dev_dbg(&isci_host->pdev->dev, | ||
309 | "%s: isci_device = %p\n", | ||
310 | __func__, isci_device); | ||
311 | isci_remote_device_change_state(isci_device, | ||
312 | isci_stopping); | ||
313 | } | ||
314 | } | ||
315 | isci_port_change_state(isci_port, isci_stopping); | ||
316 | } | ||
317 | |||
318 | /* Notify libsas of the borken link, this will trigger calls to our | ||
319 | * isci_port_deformed and isci_dev_gone functions. | ||
320 | */ | ||
321 | sas_phy_disconnected(&isci_phy->sas_phy); | ||
322 | isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy, | ||
323 | PHYE_LOSS_OF_SIGNAL); | ||
324 | |||
325 | isci_phy->isci_port = NULL; | ||
326 | |||
327 | dev_dbg(&isci_host->pdev->dev, | ||
328 | "%s: isci_port = %p - Done\n", __func__, isci_port); | ||
329 | } | ||
330 | |||
331 | |||
332 | /** | ||
333 | * isci_port_deformed() - This function is called by libsas when a port becomes | ||
334 | * inactive. | ||
335 | * @phy: This parameter specifies the libsas phy with the inactive port. | ||
336 | * | ||
337 | */ | ||
338 | void isci_port_deformed( | ||
339 | struct asd_sas_phy *phy) | ||
340 | { | ||
341 | pr_debug("%s: sas_phy = %p\n", __func__, phy); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * isci_port_formed() - This function is called by libsas when a port becomes | ||
346 | * active. | ||
347 | * @phy: This parameter specifies the libsas phy with the active port. | ||
348 | * | ||
349 | */ | ||
350 | void isci_port_formed( | ||
351 | struct asd_sas_phy *phy) | ||
352 | { | ||
353 | pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port); | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * isci_port_ready() - This function is called by the sci core when a link | ||
358 | * becomes ready. | ||
359 | * @isci_host: This parameter specifies the isci host object. | ||
360 | * @port: This parameter specifies the sci port with the active link. | ||
361 | * | ||
362 | */ | ||
363 | void isci_port_ready( | ||
364 | struct isci_host *isci_host, | ||
365 | struct isci_port *isci_port) | ||
366 | { | ||
367 | dev_dbg(&isci_host->pdev->dev, | ||
368 | "%s: isci_port = %p\n", __func__, isci_port); | ||
369 | |||
370 | complete_all(&isci_port->start_complete); | ||
371 | isci_port_change_state(isci_port, isci_ready); | ||
372 | return; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * isci_port_not_ready() - This function is called by the sci core when a link | ||
377 | * is not ready. All remote devices on this link will be removed if they are | ||
378 | * in the stopping state. | ||
379 | * @isci_host: This parameter specifies the isci host object. | ||
380 | * @port: This parameter specifies the sci port with the active link. | ||
381 | * | ||
382 | */ | ||
383 | void isci_port_not_ready( | ||
384 | struct isci_host *isci_host, | ||
385 | struct isci_port *isci_port) | ||
386 | { | ||
387 | dev_dbg(&isci_host->pdev->dev, | ||
388 | "%s: isci_port = %p\n", __func__, isci_port); | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * isci_port_hard_reset_complete() - This function is called by the sci core | ||
393 | * when the hard reset complete notification has been received. | ||
394 | * @port: This parameter specifies the sci port with the active link. | ||
395 | * @completion_status: This parameter specifies the core status for the reset | ||
396 | * process. | ||
397 | * | ||
398 | */ | ||
399 | void isci_port_hard_reset_complete( | ||
400 | struct isci_port *isci_port, | ||
401 | enum sci_status completion_status) | ||
402 | { | ||
403 | dev_dbg(&isci_port->isci_host->pdev->dev, | ||
404 | "%s: isci_port = %p, completion_status=%x\n", | ||
405 | __func__, isci_port, completion_status); | ||
406 | |||
407 | /* Save the status of the hard reset from the port. */ | ||
408 | isci_port->hard_reset_status = completion_status; | ||
409 | |||
410 | complete_all(&isci_port->hard_reset_complete); | ||
411 | } | ||
412 | /** | ||
413 | * isci_port_perform_hard_reset() - This function is one of the SAS Domain | ||
414 | * Template functions. This is a phy management function. | ||
415 | * @isci_port: | ||
416 | * @isci_phy: | ||
417 | * | ||
418 | * status, TMF_RESP_FUNC_COMPLETE indicates success. | ||
419 | */ | ||
420 | int isci_port_perform_hard_reset( | ||
421 | struct isci_port *isci_port, | ||
422 | struct isci_phy *isci_phy) | ||
423 | { | ||
424 | enum sci_status status; | ||
425 | int ret = TMF_RESP_FUNC_COMPLETE; | ||
426 | unsigned long flags; | ||
427 | |||
428 | |||
429 | dev_dbg(&isci_port->isci_host->pdev->dev, | ||
430 | "%s: isci_port = %p\n", | ||
431 | __func__, isci_port); | ||
432 | |||
433 | BUG_ON(isci_port == NULL); | ||
434 | |||
435 | init_completion(&isci_port->hard_reset_complete); | ||
436 | |||
437 | spin_lock_irqsave(&isci_port->isci_host->scic_lock, flags); | ||
438 | |||
439 | #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT | ||
440 | status = scic_port_hard_reset(isci_port->sci_port_handle, | ||
441 | ISCI_PORT_RESET_TIMEOUT); | ||
442 | |||
443 | spin_unlock_irqrestore(&isci_port->isci_host->scic_lock, flags); | ||
444 | |||
445 | if (status == SCI_SUCCESS) { | ||
446 | wait_for_completion(&isci_port->hard_reset_complete); | ||
447 | |||
448 | dev_dbg(&isci_port->isci_host->pdev->dev, | ||
449 | "%s: isci_port = %p; hard reset completion\n", | ||
450 | __func__, isci_port); | ||
451 | |||
452 | if (isci_port->hard_reset_status != SCI_SUCCESS) | ||
453 | ret = TMF_RESP_FUNC_FAILED; | ||
454 | } else { | ||
455 | ret = TMF_RESP_FUNC_FAILED; | ||
456 | |||
457 | dev_err(&isci_port->isci_host->pdev->dev, | ||
458 | "%s: isci_port = %p; scic_port_hard_reset call" | ||
459 | " failed 0x%x\n", | ||
460 | __func__, isci_port, status); | ||
461 | |||
462 | } | ||
463 | |||
464 | /* If the hard reset for the port has failed, consider this | ||
465 | * the same as link failures on all phys in the port. | ||
466 | */ | ||
467 | if (ret != TMF_RESP_FUNC_COMPLETE) { | ||
468 | BUG_ON(isci_port->isci_host == NULL); | ||
469 | |||
470 | dev_err(&isci_port->isci_host->pdev->dev, | ||
471 | "%s: isci_port = %p; hard reset failed " | ||
472 | "(0x%x) - sending link down to libsas for phy %p\n", | ||
473 | __func__, | ||
474 | isci_port, | ||
475 | isci_port->hard_reset_status, | ||
476 | isci_phy); | ||
477 | |||
478 | isci_port_link_down(isci_port->isci_host, | ||
479 | isci_phy, | ||
480 | isci_port); | ||
481 | } | ||
482 | |||
483 | return ret; | ||
484 | } | ||
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h new file mode 100644 index 000000000000..b01b0c63e53f --- /dev/null +++ b/drivers/scsi/isci/port.h | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * This file contains the isci_port object definition. | ||
58 | * | ||
59 | * port.h | ||
60 | */ | ||
61 | |||
62 | #if !defined(_ISCI_PORT_H_) | ||
63 | #define _ISCI_PORT_H_ | ||
64 | |||
65 | struct isci_phy; | ||
66 | struct isci_host; | ||
67 | |||
68 | |||
69 | enum isci_status { | ||
70 | isci_freed = 0x00, | ||
71 | isci_starting = 0x01, | ||
72 | isci_ready = 0x02, | ||
73 | isci_ready_for_io = 0x03, | ||
74 | isci_stopping = 0x04, | ||
75 | isci_stopped = 0x05, | ||
76 | isci_host_quiesce = 0x06 | ||
77 | }; | ||
78 | |||
79 | /** | ||
80 | * struct isci_port - This class represents the port object used to internally | ||
81 | * represent libsas port objects. It also keeps a list of remote device | ||
82 | * objects. | ||
83 | * | ||
84 | * | ||
85 | */ | ||
86 | struct isci_port { | ||
87 | |||
88 | struct scic_sds_port *sci_port_handle; | ||
89 | |||
90 | enum isci_status status; | ||
91 | struct isci_host *isci_host; | ||
92 | struct asd_sas_port sas_port; | ||
93 | struct list_head remote_dev_list; | ||
94 | spinlock_t remote_device_lock; | ||
95 | spinlock_t state_lock; | ||
96 | struct list_head domain_dev_list; | ||
97 | struct completion start_complete; | ||
98 | struct completion hard_reset_complete; | ||
99 | enum sci_status hard_reset_status; | ||
100 | }; | ||
101 | |||
102 | #define to_isci_port(p) \ | ||
103 | container_of(p, struct isci_port, sas_port); | ||
104 | |||
105 | enum isci_status isci_port_get_state( | ||
106 | struct isci_port *isci_port); | ||
107 | |||
108 | |||
109 | |||
110 | void isci_port_formed( | ||
111 | struct asd_sas_phy *); | ||
112 | |||
113 | void isci_port_deformed( | ||
114 | struct asd_sas_phy *); | ||
115 | |||
116 | void isci_port_bc_change_received( | ||
117 | struct isci_host *isci_host, | ||
118 | struct scic_sds_port *port, | ||
119 | struct scic_sds_phy *phy); | ||
120 | |||
121 | void isci_port_link_up( | ||
122 | struct isci_host *isci_host, | ||
123 | struct scic_sds_port *port, | ||
124 | struct scic_sds_phy *phy); | ||
125 | |||
126 | void isci_port_link_down( | ||
127 | struct isci_host *isci_host, | ||
128 | struct isci_phy *isci_phy, | ||
129 | struct isci_port *port); | ||
130 | |||
131 | void isci_port_ready( | ||
132 | struct isci_host *isci_host, | ||
133 | struct isci_port *isci_port); | ||
134 | |||
135 | void isci_port_not_ready( | ||
136 | struct isci_host *isci_host, | ||
137 | struct isci_port *port); | ||
138 | |||
139 | void isci_port_init( | ||
140 | struct isci_port *port, | ||
141 | struct isci_host *host, | ||
142 | int index); | ||
143 | |||
144 | void isci_port_hard_reset_complete( | ||
145 | struct isci_port *isci_port, | ||
146 | enum sci_status completion_status); | ||
147 | |||
148 | int isci_port_perform_hard_reset( | ||
149 | struct isci_port *isci_port_ptr, | ||
150 | struct isci_phy *isci_phy_ptr); | ||
151 | |||
152 | #endif /* !defined(_ISCI_PORT_H_) */ | ||
153 | |||
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c new file mode 100644 index 000000000000..dbf3c82f6195 --- /dev/null +++ b/drivers/scsi/isci/remote_device.c | |||
@@ -0,0 +1,698 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "isci.h" | ||
57 | #include "scic_io_request.h" | ||
58 | #include "scic_remote_device.h" | ||
59 | #include "scic_phy.h" | ||
60 | #include "scic_port.h" | ||
61 | #include "port.h" | ||
62 | #include "remote_device.h" | ||
63 | #include "request.h" | ||
64 | #include "task.h" | ||
65 | |||
66 | |||
67 | |||
68 | /** | ||
69 | * isci_remote_device_deconstruct() - This function frees an isci_remote_device. | ||
70 | * @isci_host: This parameter specifies the isci host object. | ||
71 | * @isci_device: This parameter specifies the remote device to be freed. | ||
72 | * | ||
73 | */ | ||
74 | static void isci_remote_device_deconstruct( | ||
75 | struct isci_host *isci_host, | ||
76 | struct isci_remote_device *isci_device) | ||
77 | { | ||
78 | dev_dbg(&isci_host->pdev->dev, | ||
79 | "%s: isci_device = %p\n", __func__, isci_device); | ||
80 | |||
81 | /* There should not be any outstanding io's. All paths to | ||
82 | * here should go through isci_remote_device_nuke_requests. | ||
83 | * If we hit this condition, we will need a way to complete | ||
84 | * io requests in process */ | ||
85 | while (!list_empty(&isci_device->reqs_in_process)) { | ||
86 | |||
87 | dev_err(&isci_host->pdev->dev, | ||
88 | "%s: ** request list not empty! **\n", __func__); | ||
89 | BUG(); | ||
90 | } | ||
91 | |||
92 | /* Remove all related references to this device and free | ||
93 | * the cache object. | ||
94 | */ | ||
95 | scic_remote_device_destruct(isci_device->sci_device_handle); | ||
96 | isci_device->domain_dev->lldd_dev = NULL; | ||
97 | list_del(&isci_device->node); | ||
98 | kmem_cache_free(isci_kmem_cache, isci_device); | ||
99 | } | ||
100 | |||
101 | |||
102 | /** | ||
103 | * isci_remote_device_construct() - This function calls the scic remote device | ||
104 | * construct and start functions, it waits on the remote device start | ||
105 | * completion. | ||
106 | * @port: This parameter specifies the isci port with the remote device. | ||
107 | * @isci_device: This parameter specifies the isci remote device | ||
108 | * | ||
109 | * status from the scic calls, the caller to this function should clean up | ||
110 | * resources as appropriate. | ||
111 | */ | ||
112 | static enum sci_status isci_remote_device_construct( | ||
113 | struct isci_port *port, | ||
114 | struct isci_remote_device *isci_device) | ||
115 | { | ||
116 | enum sci_status status = SCI_SUCCESS; | ||
117 | |||
118 | /* let the core do it's common constuction. */ | ||
119 | scic_remote_device_construct(port->sci_port_handle, | ||
120 | isci_device->sci_device_handle); | ||
121 | |||
122 | /* let the core do it's device specific constuction. */ | ||
123 | if (isci_device->domain_dev->parent && | ||
124 | (isci_device->domain_dev->parent->dev_type == EDGE_DEV)) { | ||
125 | int i; | ||
126 | |||
127 | /* struct smp_response_discover discover_response; */ | ||
128 | struct discover_resp discover_response; | ||
129 | struct domain_device *parent = | ||
130 | isci_device->domain_dev->parent; | ||
131 | |||
132 | struct expander_device *parent_ex = &parent->ex_dev; | ||
133 | |||
134 | for (i = 0; i < parent_ex->num_phys; i++) { | ||
135 | |||
136 | struct ex_phy *phy = &parent_ex->ex_phy[i]; | ||
137 | |||
138 | if ((phy->phy_state == PHY_VACANT) || | ||
139 | (phy->phy_state == PHY_NOT_PRESENT)) | ||
140 | continue; | ||
141 | |||
142 | if (SAS_ADDR(phy->attached_sas_addr) | ||
143 | == SAS_ADDR(isci_device->domain_dev->sas_addr)) { | ||
144 | |||
145 | discover_response.attached_dev_type | ||
146 | = phy->attached_dev_type; | ||
147 | discover_response.linkrate | ||
148 | = phy->linkrate; | ||
149 | discover_response.attached_sata_host | ||
150 | = phy->attached_sata_host; | ||
151 | discover_response.attached_sata_dev | ||
152 | = phy->attached_sata_dev; | ||
153 | discover_response.attached_sata_ps | ||
154 | = phy->attached_sata_ps; | ||
155 | discover_response.iproto | ||
156 | = phy->attached_iproto >> 1; | ||
157 | discover_response.tproto | ||
158 | = phy->attached_tproto >> 1; | ||
159 | memcpy( | ||
160 | discover_response.attached_sas_addr, | ||
161 | phy->attached_sas_addr, | ||
162 | SAS_ADDR_SIZE | ||
163 | ); | ||
164 | discover_response.attached_phy_id | ||
165 | = phy->attached_phy_id; | ||
166 | discover_response.change_count | ||
167 | = phy->phy_change_count; | ||
168 | discover_response.routing_attr | ||
169 | = phy->routing_attr; | ||
170 | discover_response.hmin_linkrate | ||
171 | = phy->phy->minimum_linkrate_hw; | ||
172 | discover_response.hmax_linkrate | ||
173 | = phy->phy->maximum_linkrate_hw; | ||
174 | discover_response.pmin_linkrate | ||
175 | = phy->phy->minimum_linkrate; | ||
176 | discover_response.pmax_linkrate | ||
177 | = phy->phy->maximum_linkrate; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | |||
182 | dev_dbg(&port->isci_host->pdev->dev, | ||
183 | "%s: parent->dev_type = EDGE_DEV\n", | ||
184 | __func__); | ||
185 | |||
186 | status = scic_remote_device_ea_construct( | ||
187 | isci_device->sci_device_handle, | ||
188 | (struct smp_response_discover *)&discover_response | ||
189 | ); | ||
190 | |||
191 | } else | ||
192 | status = scic_remote_device_da_construct( | ||
193 | isci_device->sci_device_handle | ||
194 | ); | ||
195 | |||
196 | |||
197 | if (status != SCI_SUCCESS) { | ||
198 | dev_dbg(&port->isci_host->pdev->dev, | ||
199 | "%s: scic_remote_device_da_construct failed - " | ||
200 | "isci_device = %p\n", | ||
201 | __func__, | ||
202 | isci_device); | ||
203 | |||
204 | return status; | ||
205 | } | ||
206 | |||
207 | sci_object_set_association( | ||
208 | isci_device->sci_device_handle, | ||
209 | isci_device | ||
210 | ); | ||
211 | |||
212 | BUG_ON(port->isci_host == NULL); | ||
213 | |||
214 | /* start the device. */ | ||
215 | status = scic_remote_device_start( | ||
216 | isci_device->sci_device_handle, | ||
217 | ISCI_REMOTE_DEVICE_START_TIMEOUT | ||
218 | ); | ||
219 | |||
220 | if (status != SCI_SUCCESS) { | ||
221 | dev_warn(&port->isci_host->pdev->dev, | ||
222 | "%s: scic_remote_device_start failed\n", | ||
223 | __func__); | ||
224 | return status; | ||
225 | } | ||
226 | |||
227 | return status; | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * isci_remote_device_nuke_requests() - This function terminates all requests | ||
233 | * for a given remote device. | ||
234 | * @isci_device: This parameter specifies the remote device | ||
235 | * | ||
236 | */ | ||
237 | void isci_remote_device_nuke_requests( | ||
238 | struct isci_remote_device *isci_device) | ||
239 | { | ||
240 | DECLARE_COMPLETION_ONSTACK(aborted_task_completion); | ||
241 | struct isci_host *isci_host; | ||
242 | |||
243 | isci_host = isci_device->isci_port->isci_host; | ||
244 | |||
245 | dev_dbg(&isci_host->pdev->dev, | ||
246 | "%s: isci_device = %p\n", __func__, isci_device); | ||
247 | |||
248 | /* Cleanup all requests pending for this device. */ | ||
249 | isci_terminate_pending_requests(isci_host, isci_device, terminating); | ||
250 | |||
251 | dev_dbg(&isci_host->pdev->dev, | ||
252 | "%s: isci_device = %p, done\n", __func__, isci_device); | ||
253 | } | ||
254 | |||
255 | |||
256 | |||
257 | /** | ||
258 | * This function builds the isci_remote_device when a libsas dev_found message | ||
259 | * is received. | ||
260 | * @isci_host: This parameter specifies the isci host object. | ||
261 | * @port: This parameter specifies the isci_port conected to this device. | ||
262 | * | ||
263 | * pointer to new isci_remote_device. | ||
264 | */ | ||
265 | static struct isci_remote_device * | ||
266 | isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port) | ||
267 | { | ||
268 | struct isci_remote_device *isci_device; | ||
269 | struct scic_sds_remote_device *sci_dev; | ||
270 | |||
271 | isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL); | ||
272 | |||
273 | if (!isci_device) { | ||
274 | dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__); | ||
275 | return NULL; | ||
276 | } | ||
277 | |||
278 | sci_dev = (struct scic_sds_remote_device *) &isci_device[1]; | ||
279 | isci_device->sci_device_handle = sci_dev; | ||
280 | INIT_LIST_HEAD(&isci_device->reqs_in_process); | ||
281 | INIT_LIST_HEAD(&isci_device->node); | ||
282 | isci_device->host_quiesce = false; | ||
283 | |||
284 | spin_lock_init(&isci_device->state_lock); | ||
285 | spin_lock_init(&isci_device->host_quiesce_lock); | ||
286 | isci_remote_device_change_state(isci_device, isci_freed); | ||
287 | |||
288 | return isci_device; | ||
289 | |||
290 | } | ||
291 | /** | ||
292 | * isci_device_set_host_quiesce_lock_state() - This function sets the host I/O | ||
293 | * quiesce lock state for the remote_device object. | ||
294 | * @isci_device,: This parameter points to the isci_remote_device object | ||
295 | * @isci_device: This parameter specifies the new quiesce state. | ||
296 | * | ||
297 | */ | ||
298 | void isci_device_set_host_quiesce_lock_state( | ||
299 | struct isci_remote_device *isci_device, | ||
300 | bool lock_state) | ||
301 | { | ||
302 | unsigned long flags; | ||
303 | |||
304 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
305 | "%s: isci_device=%p, lock_state=%d\n", | ||
306 | __func__, isci_device, lock_state); | ||
307 | |||
308 | spin_lock_irqsave(&isci_device->host_quiesce_lock, flags); | ||
309 | isci_device->host_quiesce = lock_state; | ||
310 | spin_unlock_irqrestore(&isci_device->host_quiesce_lock, flags); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * isci_remote_device_ready() - This function is called by the scic when the | ||
315 | * remote device is ready. We mark the isci device as ready and signal the | ||
316 | * waiting proccess. | ||
317 | * @isci_host: This parameter specifies the isci host object. | ||
318 | * @isci_device: This parameter specifies the remote device | ||
319 | * | ||
320 | */ | ||
321 | void isci_remote_device_ready(struct isci_remote_device *isci_device) | ||
322 | { | ||
323 | unsigned long flags; | ||
324 | |||
325 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
326 | "%s: isci_device = %p\n", __func__, isci_device); | ||
327 | |||
328 | /* device ready is actually a "ready for io" state. */ | ||
329 | if ((isci_starting == isci_remote_device_get_state(isci_device)) || | ||
330 | (isci_ready == isci_remote_device_get_state(isci_device))) { | ||
331 | spin_lock_irqsave(&isci_device->isci_port->remote_device_lock, | ||
332 | flags); | ||
333 | isci_remote_device_change_state(isci_device, isci_ready_for_io); | ||
334 | if (isci_device->completion) | ||
335 | complete(isci_device->completion); | ||
336 | spin_unlock_irqrestore( | ||
337 | &isci_device->isci_port->remote_device_lock, | ||
338 | flags); | ||
339 | } | ||
340 | |||
341 | } | ||
342 | |||
343 | /** | ||
344 | * isci_remote_device_not_ready() - This function is called by the scic when | ||
345 | * the remote device is not ready. We mark the isci device as ready (not | ||
346 | * "ready_for_io") and signal the waiting proccess. | ||
347 | * @isci_host: This parameter specifies the isci host object. | ||
348 | * @isci_device: This parameter specifies the remote device | ||
349 | * | ||
350 | */ | ||
351 | void isci_remote_device_not_ready( | ||
352 | struct isci_remote_device *isci_device, | ||
353 | u32 reason_code) | ||
354 | { | ||
355 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
356 | "%s: isci_device = %p\n", __func__, isci_device); | ||
357 | |||
358 | if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED) | ||
359 | isci_remote_device_change_state(isci_device, isci_stopping); | ||
360 | else | ||
361 | /* device ready is actually a "not ready for io" state. */ | ||
362 | isci_remote_device_change_state(isci_device, isci_ready); | ||
363 | } | ||
364 | |||
365 | /** | ||
366 | * isci_remote_device_stop_complete() - This function is called by the scic | ||
367 | * when the remote device stop has completed. We mark the isci device as not | ||
368 | * ready and remove the isci remote device. | ||
369 | * @isci_host: This parameter specifies the isci host object. | ||
370 | * @isci_device: This parameter specifies the remote device. | ||
371 | * @status: This parameter specifies status of the completion. | ||
372 | * | ||
373 | */ | ||
374 | void isci_remote_device_stop_complete( | ||
375 | struct isci_host *isci_host, | ||
376 | struct isci_remote_device *isci_device, | ||
377 | enum sci_status status) | ||
378 | { | ||
379 | struct completion *completion = isci_device->completion; | ||
380 | |||
381 | dev_dbg(&isci_host->pdev->dev, | ||
382 | "%s: complete isci_device = %p, status = 0x%x\n", | ||
383 | __func__, | ||
384 | isci_device, | ||
385 | status); | ||
386 | |||
387 | isci_remote_device_change_state(isci_device, isci_stopped); | ||
388 | |||
389 | /* after stop, we can tear down resources. */ | ||
390 | isci_remote_device_deconstruct(isci_host, isci_device); | ||
391 | |||
392 | /* notify interested parties. */ | ||
393 | if (completion) | ||
394 | complete(completion); | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * isci_remote_device_start_complete() - This function is called by the scic | ||
399 | * when the remote device start has completed | ||
400 | * @isci_host: This parameter specifies the isci host object. | ||
401 | * @isci_device: This parameter specifies the remote device. | ||
402 | * @status: This parameter specifies status of the completion. | ||
403 | * | ||
404 | */ | ||
405 | void isci_remote_device_start_complete( | ||
406 | struct isci_host *isci_host, | ||
407 | struct isci_remote_device *isci_device, | ||
408 | enum sci_status status) | ||
409 | { | ||
410 | |||
411 | |||
412 | } | ||
413 | |||
414 | |||
415 | /** | ||
416 | * isci_remote_device_stop() - This function is called internally to stop the | ||
417 | * remote device. | ||
418 | * @isci_host: This parameter specifies the isci host object. | ||
419 | * @isci_device: This parameter specifies the remote device. | ||
420 | * | ||
421 | * The status of the scic request to stop. | ||
422 | */ | ||
423 | enum sci_status isci_remote_device_stop( | ||
424 | struct isci_remote_device *isci_device) | ||
425 | { | ||
426 | enum sci_status status; | ||
427 | unsigned long flags; | ||
428 | |||
429 | DECLARE_COMPLETION_ONSTACK(completion); | ||
430 | |||
431 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
432 | "%s: isci_device = %p\n", __func__, isci_device); | ||
433 | |||
434 | isci_remote_device_change_state(isci_device, isci_stopping); | ||
435 | |||
436 | /* We need comfirmation that stop completed. */ | ||
437 | isci_device->completion = &completion; | ||
438 | |||
439 | BUG_ON(isci_device->isci_port == NULL); | ||
440 | BUG_ON(isci_device->isci_port->isci_host == NULL); | ||
441 | |||
442 | spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags); | ||
443 | |||
444 | status = scic_remote_device_stop( | ||
445 | isci_device->sci_device_handle, | ||
446 | 50 | ||
447 | ); | ||
448 | |||
449 | spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags); | ||
450 | |||
451 | /* Wait for the stop complete callback. */ | ||
452 | if (status == SCI_SUCCESS) | ||
453 | wait_for_completion(&completion); | ||
454 | |||
455 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
456 | "%s: isci_device = %p - after completion wait\n", | ||
457 | __func__, isci_device); | ||
458 | |||
459 | isci_device->completion = NULL; | ||
460 | return status; | ||
461 | } | ||
462 | |||
463 | /** | ||
464 | * isci_remote_device_gone() - This function is called by libsas when a domain | ||
465 | * device is removed. | ||
466 | * @domain_device: This parameter specifies the libsas domain device. | ||
467 | * | ||
468 | */ | ||
469 | void isci_remote_device_gone( | ||
470 | struct domain_device *domain_dev) | ||
471 | { | ||
472 | struct isci_remote_device *isci_device = isci_dev_from_domain_dev( | ||
473 | domain_dev); | ||
474 | |||
475 | dev_err(&isci_device->isci_port->isci_host->pdev->dev, | ||
476 | "%s: domain_device = %p, isci_device = %p, isci_port = %p\n", | ||
477 | __func__, domain_dev, isci_device, isci_device->isci_port); | ||
478 | |||
479 | if (isci_device != NULL) | ||
480 | isci_remote_device_stop(isci_device); | ||
481 | } | ||
482 | |||
483 | |||
484 | /** | ||
485 | * isci_remote_device_found() - This function is called by libsas when a remote | ||
486 | * device is discovered. A remote device object is created and started. the | ||
487 | * function then sleeps until the sci core device started message is | ||
488 | * received. | ||
489 | * @domain_device: This parameter specifies the libsas domain device. | ||
490 | * | ||
491 | * status, zero indicates success. | ||
492 | */ | ||
493 | int isci_remote_device_found(struct domain_device *domain_dev) | ||
494 | { | ||
495 | unsigned long flags; | ||
496 | struct isci_host *isci_host; | ||
497 | struct isci_port *isci_port; | ||
498 | struct isci_phy *isci_phy; | ||
499 | struct asd_sas_port *sas_port; | ||
500 | struct asd_sas_phy *sas_phy; | ||
501 | struct isci_remote_device *isci_device; | ||
502 | enum sci_status status; | ||
503 | DECLARE_COMPLETION_ONSTACK(completion); | ||
504 | |||
505 | isci_host = isci_host_from_sas_ha(domain_dev->port->ha); | ||
506 | |||
507 | dev_dbg(&isci_host->pdev->dev, | ||
508 | "%s: domain_device = %p\n", __func__, domain_dev); | ||
509 | |||
510 | sas_port = domain_dev->port; | ||
511 | sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy, | ||
512 | port_phy_el); | ||
513 | isci_phy = to_isci_phy(sas_phy); | ||
514 | isci_port = isci_phy->isci_port; | ||
515 | |||
516 | /* we are being called for a device on this port, | ||
517 | * so it has to come up eventually | ||
518 | */ | ||
519 | wait_for_completion(&isci_port->start_complete); | ||
520 | |||
521 | if ((isci_stopping == isci_port_get_state(isci_port)) || | ||
522 | (isci_stopped == isci_port_get_state(isci_port))) | ||
523 | return -ENODEV; | ||
524 | |||
525 | isci_device = isci_remote_device_alloc(isci_host, isci_port); | ||
526 | |||
527 | INIT_LIST_HEAD(&isci_device->node); | ||
528 | domain_dev->lldd_dev = isci_device; | ||
529 | isci_device->domain_dev = domain_dev; | ||
530 | isci_device->isci_port = isci_port; | ||
531 | isci_remote_device_change_state(isci_device, isci_starting); | ||
532 | |||
533 | |||
534 | spin_lock_irqsave(&isci_port->remote_device_lock, flags); | ||
535 | list_add_tail(&isci_device->node, &isci_port->remote_dev_list); | ||
536 | |||
537 | /* for the device ready event. */ | ||
538 | isci_device->completion = &completion; | ||
539 | |||
540 | status = isci_remote_device_construct(isci_port, isci_device); | ||
541 | |||
542 | spin_unlock_irqrestore(&isci_port->remote_device_lock, flags); | ||
543 | |||
544 | /* wait for the device ready callback. */ | ||
545 | wait_for_completion(isci_device->completion); | ||
546 | isci_device->completion = NULL; | ||
547 | |||
548 | dev_dbg(&isci_host->pdev->dev, | ||
549 | "%s: isci_device = %p\n", | ||
550 | __func__, isci_device); | ||
551 | |||
552 | if (status != SCI_SUCCESS) { | ||
553 | |||
554 | spin_lock_irqsave(&isci_port->remote_device_lock, flags); | ||
555 | isci_remote_device_deconstruct( | ||
556 | isci_host, | ||
557 | isci_device | ||
558 | ); | ||
559 | spin_unlock_irqrestore(&isci_port->remote_device_lock, flags); | ||
560 | return -ENODEV; | ||
561 | } | ||
562 | |||
563 | wait_for_completion(&isci_host->start_complete); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | /** | ||
568 | * isci_device_is_reset_pending() - This function will check if there is any | ||
569 | * pending reset condition on the device. | ||
570 | * @request: This parameter is the isci_device object. | ||
571 | * | ||
572 | * true if there is a reset pending for the device. | ||
573 | */ | ||
574 | bool isci_device_is_reset_pending( | ||
575 | struct isci_host *isci_host, | ||
576 | struct isci_remote_device *isci_device) | ||
577 | { | ||
578 | struct isci_request *isci_request; | ||
579 | struct isci_request *tmp_req; | ||
580 | bool reset_is_pending = false; | ||
581 | unsigned long flags; | ||
582 | |||
583 | dev_dbg(&isci_host->pdev->dev, | ||
584 | "%s: isci_device = %p\n", __func__, isci_device); | ||
585 | |||
586 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
587 | |||
588 | /* Check for reset on all pending requests. */ | ||
589 | list_for_each_entry_safe(isci_request, tmp_req, | ||
590 | &isci_device->reqs_in_process, dev_node) { | ||
591 | dev_dbg(&isci_host->pdev->dev, | ||
592 | "%s: isci_device = %p request = %p\n", | ||
593 | __func__, isci_device, isci_request); | ||
594 | |||
595 | if (isci_request->ttype == io_task) { | ||
596 | |||
597 | unsigned long flags; | ||
598 | struct sas_task *task = isci_request_access_task( | ||
599 | isci_request); | ||
600 | |||
601 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
602 | if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) | ||
603 | reset_is_pending = true; | ||
604 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
605 | } | ||
606 | } | ||
607 | |||
608 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
609 | |||
610 | dev_dbg(&isci_host->pdev->dev, | ||
611 | "%s: isci_device = %p reset_is_pending = %d\n", | ||
612 | __func__, isci_device, reset_is_pending); | ||
613 | |||
614 | return reset_is_pending; | ||
615 | } | ||
616 | |||
617 | /** | ||
618 | * isci_device_clear_reset_pending() - This function will clear if any pending | ||
619 | * reset condition flags on the device. | ||
620 | * @request: This parameter is the isci_device object. | ||
621 | * | ||
622 | * true if there is a reset pending for the device. | ||
623 | */ | ||
624 | void isci_device_clear_reset_pending(struct isci_remote_device *isci_device) | ||
625 | { | ||
626 | struct isci_request *isci_request; | ||
627 | struct isci_request *tmp_req; | ||
628 | struct isci_host *isci_host = NULL; | ||
629 | unsigned long flags = 0; | ||
630 | |||
631 | /* FIXME more port gone confusion, and this time it makes the | ||
632 | * locking "fun" | ||
633 | */ | ||
634 | if (isci_device->isci_port != NULL) | ||
635 | isci_host = isci_device->isci_port->isci_host; | ||
636 | |||
637 | /* | ||
638 | * FIXME when the isci_host gets sorted out | ||
639 | * use dev_dbg() | ||
640 | */ | ||
641 | pr_debug("%s: isci_device=%p, isci_host=%p\n", | ||
642 | __func__, isci_device, isci_host); | ||
643 | |||
644 | if (isci_host != NULL) | ||
645 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
646 | else | ||
647 | pr_err("%s: isci_device %p; isci_host == NULL!\n", | ||
648 | __func__, isci_device); | ||
649 | |||
650 | /* Clear reset pending on all pending requests. */ | ||
651 | list_for_each_entry_safe(isci_request, tmp_req, | ||
652 | &isci_device->reqs_in_process, dev_node) { | ||
653 | /* | ||
654 | * FIXME when the conditional spinlock is gone | ||
655 | * change to dev_dbg() | ||
656 | */ | ||
657 | pr_debug("%s: isci_device = %p request = %p\n", | ||
658 | __func__, isci_device, isci_request); | ||
659 | |||
660 | if (isci_request->ttype == io_task) { | ||
661 | |||
662 | unsigned long flags2; | ||
663 | struct sas_task *task = isci_request_access_task( | ||
664 | isci_request); | ||
665 | |||
666 | spin_lock_irqsave(&task->task_state_lock, flags2); | ||
667 | task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; | ||
668 | spin_unlock_irqrestore(&task->task_state_lock, flags2); | ||
669 | } | ||
670 | } | ||
671 | |||
672 | if (isci_host != NULL) | ||
673 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
674 | } | ||
675 | |||
676 | /** | ||
677 | * isci_remote_device_change_state() - This function gets the status of the | ||
678 | * remote_device object. | ||
679 | * @isci_device: This parameter points to the isci_remote_device object | ||
680 | * | ||
681 | * status of the object as a isci_status enum. | ||
682 | */ | ||
683 | void isci_remote_device_change_state( | ||
684 | struct isci_remote_device *isci_device, | ||
685 | enum isci_status status) | ||
686 | { | ||
687 | unsigned long flags; | ||
688 | |||
689 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
690 | "%s: isci_device = %p, state = 0x%x", | ||
691 | __func__, | ||
692 | isci_device, | ||
693 | status); | ||
694 | |||
695 | spin_lock_irqsave(&isci_device->state_lock, flags); | ||
696 | isci_device->status = status; | ||
697 | spin_unlock_irqrestore(&isci_device->state_lock, flags); | ||
698 | } | ||
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h new file mode 100644 index 000000000000..a208f81785eb --- /dev/null +++ b/drivers/scsi/isci/remote_device.h | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #if !defined(_ISCI_REMOTE_DEVICE_H_) | ||
57 | #define _ISCI_REMOTE_DEVICE_H_ | ||
58 | #include "scic_user_callback.h" | ||
59 | |||
60 | struct isci_host; | ||
61 | struct scic_sds_remote_device; | ||
62 | |||
63 | struct isci_remote_device { | ||
64 | struct scic_sds_remote_device *sci_device_handle; | ||
65 | enum isci_status status; | ||
66 | struct isci_port *isci_port; | ||
67 | struct domain_device *domain_dev; | ||
68 | struct completion *completion; | ||
69 | struct list_head node; | ||
70 | struct list_head reqs_in_process; | ||
71 | struct work_struct stop_work; | ||
72 | spinlock_t state_lock; | ||
73 | spinlock_t host_quiesce_lock; | ||
74 | bool host_quiesce; | ||
75 | }; | ||
76 | |||
77 | #define to_isci_remote_device(p) \ | ||
78 | container_of(p, struct isci_remote_device, sci_remote_device); | ||
79 | |||
80 | #define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000 | ||
81 | |||
82 | |||
83 | /** | ||
84 | * This function gets the status of the remote_device object. | ||
85 | * @isci_device: This parameter points to the isci_remote_device object | ||
86 | * | ||
87 | * status of the object as a isci_status enum. | ||
88 | */ | ||
89 | static inline | ||
90 | enum isci_status isci_remote_device_get_state( | ||
91 | struct isci_remote_device *isci_device) | ||
92 | { | ||
93 | return (isci_device->host_quiesce) | ||
94 | ? isci_host_quiesce | ||
95 | : isci_device->status; | ||
96 | } | ||
97 | |||
98 | |||
99 | /** | ||
100 | * isci_dev_from_domain_dev() - This accessor retrieves the remote_device | ||
101 | * object reference from the Linux domain_device reference. | ||
102 | * @domdev,: This parameter points to the Linux domain_device object . | ||
103 | * | ||
104 | * A reference to the associated isci remote device. | ||
105 | */ | ||
106 | #define isci_dev_from_domain_dev(domdev) \ | ||
107 | ((struct isci_remote_device *)(domdev)->lldd_dev) | ||
108 | |||
109 | void isci_remote_device_start_complete( | ||
110 | struct isci_host *, | ||
111 | struct isci_remote_device *, | ||
112 | enum sci_status); | ||
113 | |||
114 | void isci_remote_device_stop_complete( | ||
115 | struct isci_host *, | ||
116 | struct isci_remote_device *, | ||
117 | enum sci_status); | ||
118 | |||
119 | enum sci_status isci_remote_device_stop( | ||
120 | struct isci_remote_device *isci_device); | ||
121 | |||
122 | void isci_remote_device_nuke_requests( | ||
123 | struct isci_remote_device *isci_device); | ||
124 | |||
125 | void isci_remote_device_ready( | ||
126 | struct isci_remote_device *); | ||
127 | |||
128 | void isci_remote_device_not_ready( | ||
129 | struct isci_remote_device *, | ||
130 | u32); | ||
131 | |||
132 | void isci_remote_device_gone( | ||
133 | struct domain_device *domain_dev); | ||
134 | |||
135 | int isci_remote_device_found( | ||
136 | struct domain_device *domain_dev); | ||
137 | |||
138 | bool isci_device_is_reset_pending( | ||
139 | struct isci_host *isci_host, | ||
140 | struct isci_remote_device *isci_device); | ||
141 | |||
142 | void isci_device_clear_reset_pending( | ||
143 | struct isci_remote_device *isci_device); | ||
144 | |||
145 | void isci_device_set_host_quiesce_lock_state( | ||
146 | struct isci_remote_device *isci_device, | ||
147 | bool lock_state); | ||
148 | |||
149 | void isci_remote_device_change_state( | ||
150 | struct isci_remote_device *isci_device, | ||
151 | enum isci_status status); | ||
152 | |||
153 | #endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */ | ||
154 | |||
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c new file mode 100644 index 000000000000..e564121b6726 --- /dev/null +++ b/drivers/scsi/isci/request.c | |||
@@ -0,0 +1,1472 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "isci.h" | ||
57 | #include "scic_remote_device.h" | ||
58 | #include "scic_io_request.h" | ||
59 | #include "scic_task_request.h" | ||
60 | #include "scic_port.h" | ||
61 | #include "task.h" | ||
62 | #include "request.h" | ||
63 | #include "sata.h" | ||
64 | #include "scu_completion_codes.h" | ||
65 | |||
66 | |||
67 | static enum sci_status isci_request_ssp_request_construct( | ||
68 | struct isci_request *request) | ||
69 | { | ||
70 | enum sci_status status; | ||
71 | |||
72 | dev_dbg(&request->isci_host->pdev->dev, | ||
73 | "%s: request = %p\n", | ||
74 | __func__, | ||
75 | request); | ||
76 | status = scic_io_request_construct_basic_ssp( | ||
77 | request->sci_request_handle | ||
78 | ); | ||
79 | return status; | ||
80 | } | ||
81 | |||
82 | static enum sci_status isci_request_stp_request_construct( | ||
83 | struct isci_request *request) | ||
84 | { | ||
85 | struct sas_task *task = isci_request_access_task(request); | ||
86 | enum sci_status status; | ||
87 | struct host_to_dev_fis *register_fis; | ||
88 | |||
89 | dev_dbg(&request->isci_host->pdev->dev, | ||
90 | "%s: request = %p\n", | ||
91 | __func__, | ||
92 | request); | ||
93 | |||
94 | /* Get the host_to_dev_fis from the core and copy | ||
95 | * the fis from the task into it. | ||
96 | */ | ||
97 | register_fis = isci_sata_task_to_fis_copy(task); | ||
98 | |||
99 | status = scic_io_request_construct_basic_sata( | ||
100 | request->sci_request_handle | ||
101 | ); | ||
102 | |||
103 | /* Set the ncq tag in the fis, from the queue | ||
104 | * command in the task. | ||
105 | */ | ||
106 | if (isci_sata_is_task_ncq(task)) { | ||
107 | |||
108 | isci_sata_set_ncq_tag( | ||
109 | register_fis, | ||
110 | task | ||
111 | ); | ||
112 | } | ||
113 | |||
114 | return status; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * isci_smp_request_build() - This function builds the smp request object. | ||
119 | * @isci_host: This parameter specifies the ISCI host object | ||
120 | * @request: This parameter points to the isci_request object allocated in the | ||
121 | * request construct function. | ||
122 | * @sci_device: This parameter is the handle for the sci core's remote device | ||
123 | * object that is the destination for this request. | ||
124 | * | ||
125 | * SCI_SUCCESS on successfull completion, or specific failure code. | ||
126 | */ | ||
127 | static enum sci_status isci_smp_request_build( | ||
128 | struct isci_request *request) | ||
129 | { | ||
130 | enum sci_status status = SCI_FAILURE; | ||
131 | struct sas_task *task = isci_request_access_task(request); | ||
132 | |||
133 | void *command_iu_address = | ||
134 | scic_io_request_get_command_iu_address( | ||
135 | request->sci_request_handle | ||
136 | ); | ||
137 | |||
138 | dev_dbg(&request->isci_host->pdev->dev, | ||
139 | "%s: request = %p\n", | ||
140 | __func__, | ||
141 | request); | ||
142 | dev_dbg(&request->isci_host->pdev->dev, | ||
143 | "%s: smp_req len = %d\n", | ||
144 | __func__, | ||
145 | task->smp_task.smp_req.length); | ||
146 | |||
147 | /* copy the smp_command to the address; */ | ||
148 | sg_copy_to_buffer(&task->smp_task.smp_req, 1, | ||
149 | (char *)command_iu_address, | ||
150 | sizeof(struct smp_request) | ||
151 | ); | ||
152 | |||
153 | status = scic_io_request_construct_smp(request->sci_request_handle); | ||
154 | if (status != SCI_SUCCESS) | ||
155 | dev_warn(&request->isci_host->pdev->dev, | ||
156 | "%s: scic_io_request_construct_smp failed with " | ||
157 | "status = %d\n", | ||
158 | __func__, | ||
159 | status); | ||
160 | |||
161 | return status; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * isci_io_request_build() - This function builds the io request object. | ||
166 | * @isci_host: This parameter specifies the ISCI host object | ||
167 | * @request: This parameter points to the isci_request object allocated in the | ||
168 | * request construct function. | ||
169 | * @sci_device: This parameter is the handle for the sci core's remote device | ||
170 | * object that is the destination for this request. | ||
171 | * | ||
172 | * SCI_SUCCESS on successfull completion, or specific failure code. | ||
173 | */ | ||
174 | static enum sci_status isci_io_request_build( | ||
175 | struct isci_host *isci_host, | ||
176 | struct isci_request *request, | ||
177 | struct isci_remote_device *isci_device) | ||
178 | { | ||
179 | struct smp_discover_response_protocols dev_protocols; | ||
180 | enum sci_status status = SCI_SUCCESS; | ||
181 | struct sas_task *task = isci_request_access_task(request); | ||
182 | struct scic_sds_remote_device *sci_device = | ||
183 | isci_device->sci_device_handle; | ||
184 | |||
185 | dev_dbg(&isci_host->pdev->dev, | ||
186 | "%s: isci_device = 0x%p; request = %p, " | ||
187 | "num_scatter = %d\n", | ||
188 | __func__, | ||
189 | isci_device, | ||
190 | request, | ||
191 | task->num_scatter); | ||
192 | |||
193 | /* map the sgl addresses, if present. | ||
194 | * libata does the mapping for sata devices | ||
195 | * before we get the request. | ||
196 | */ | ||
197 | if (task->num_scatter && | ||
198 | !sas_protocol_ata(task->task_proto) && | ||
199 | !(SAS_PROTOCOL_SMP & task->task_proto)) { | ||
200 | |||
201 | request->num_sg_entries = dma_map_sg( | ||
202 | &isci_host->pdev->dev, | ||
203 | task->scatter, | ||
204 | task->num_scatter, | ||
205 | task->data_dir | ||
206 | ); | ||
207 | |||
208 | if (request->num_sg_entries == 0) | ||
209 | return SCI_FAILURE_INSUFFICIENT_RESOURCES; | ||
210 | } | ||
211 | |||
212 | /* build the common request object. For now, | ||
213 | * we will let the core allocate the IO tag. | ||
214 | */ | ||
215 | status = scic_io_request_construct( | ||
216 | isci_host->core_controller, | ||
217 | sci_device, | ||
218 | SCI_CONTROLLER_INVALID_IO_TAG, | ||
219 | request, | ||
220 | request->sci_request_mem_ptr, | ||
221 | (struct scic_sds_request **)&request->sci_request_handle | ||
222 | ); | ||
223 | |||
224 | if (status != SCI_SUCCESS) { | ||
225 | dev_warn(&isci_host->pdev->dev, | ||
226 | "%s: failed request construct\n", | ||
227 | __func__); | ||
228 | return SCI_FAILURE; | ||
229 | } | ||
230 | |||
231 | sci_object_set_association(request->sci_request_handle, request); | ||
232 | |||
233 | /* Determine protocol and call the appropriate basic constructor */ | ||
234 | scic_remote_device_get_protocols(sci_device, &dev_protocols); | ||
235 | if (dev_protocols.u.bits.attached_ssp_target) | ||
236 | status = isci_request_ssp_request_construct(request); | ||
237 | else if (dev_protocols.u.bits.attached_stp_target) | ||
238 | status = isci_request_stp_request_construct(request); | ||
239 | else if (dev_protocols.u.bits.attached_smp_target) | ||
240 | status = isci_smp_request_build(request); | ||
241 | else { | ||
242 | dev_warn(&isci_host->pdev->dev, | ||
243 | "%s: unknown protocol\n", __func__); | ||
244 | return SCI_FAILURE; | ||
245 | } | ||
246 | |||
247 | return SCI_SUCCESS; | ||
248 | } | ||
249 | |||
250 | |||
251 | /** | ||
252 | * isci_request_alloc_core() - This function gets the request object from the | ||
253 | * isci_host dma cache. | ||
254 | * @isci_host: This parameter specifies the ISCI host object | ||
255 | * @isci_request: This parameter will contain the pointer to the new | ||
256 | * isci_request object. | ||
257 | * @isci_device: This parameter is the pointer to the isci remote device object | ||
258 | * that is the destination for this request. | ||
259 | * @gfp_flags: This parameter specifies the os allocation flags. | ||
260 | * | ||
261 | * SCI_SUCCESS on successfull completion, or specific failure code. | ||
262 | */ | ||
263 | static int isci_request_alloc_core( | ||
264 | struct isci_host *isci_host, | ||
265 | struct isci_request **isci_request, | ||
266 | struct isci_remote_device *isci_device, | ||
267 | gfp_t gfp_flags) | ||
268 | { | ||
269 | int ret = 0; | ||
270 | dma_addr_t handle; | ||
271 | struct isci_request *request; | ||
272 | |||
273 | |||
274 | /* get pointer to dma memory. This actually points | ||
275 | * to both the isci_remote_device object and the | ||
276 | * sci object. The isci object is at the beginning | ||
277 | * of the memory allocated here. | ||
278 | */ | ||
279 | request = dma_pool_alloc(isci_host->dma_pool, gfp_flags, &handle); | ||
280 | if (!request) { | ||
281 | dev_warn(&isci_host->pdev->dev, | ||
282 | "%s: dma_pool_alloc returned NULL\n", __func__); | ||
283 | return -ENOMEM; | ||
284 | } | ||
285 | |||
286 | /* initialize the request object. */ | ||
287 | spin_lock_init(&request->state_lock); | ||
288 | isci_request_change_state(request, allocated); | ||
289 | request->sci_request_mem_ptr = ((u8 *)request) + | ||
290 | sizeof(struct isci_request); | ||
291 | request->request_daddr = handle; | ||
292 | request->isci_host = isci_host; | ||
293 | request->isci_device = isci_device; | ||
294 | request->io_request_completion = NULL; | ||
295 | |||
296 | request->request_alloc_size = isci_host->dma_pool_alloc_size; | ||
297 | request->num_sg_entries = 0; | ||
298 | |||
299 | request->complete_in_target = false; | ||
300 | |||
301 | INIT_LIST_HEAD(&request->completed_node); | ||
302 | INIT_LIST_HEAD(&request->dev_node); | ||
303 | |||
304 | *isci_request = request; | ||
305 | |||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | static int isci_request_alloc_io( | ||
310 | struct isci_host *isci_host, | ||
311 | struct sas_task *task, | ||
312 | struct isci_request **isci_request, | ||
313 | struct isci_remote_device *isci_device, | ||
314 | gfp_t gfp_flags) | ||
315 | { | ||
316 | int retval = isci_request_alloc_core(isci_host, isci_request, | ||
317 | isci_device, gfp_flags); | ||
318 | |||
319 | if (!retval) { | ||
320 | (*isci_request)->ttype_ptr.io_task_ptr = task; | ||
321 | (*isci_request)->ttype = io_task; | ||
322 | |||
323 | task->lldd_task = *isci_request; | ||
324 | } | ||
325 | return retval; | ||
326 | } | ||
327 | |||
328 | /** | ||
329 | * isci_request_alloc_tmf() - This function gets the request object from the | ||
330 | * isci_host dma cache and initializes the relevant fields as a sas_task. | ||
331 | * @isci_host: This parameter specifies the ISCI host object | ||
332 | * @sas_task: This parameter is the task struct from the upper layer driver. | ||
333 | * @isci_request: This parameter will contain the pointer to the new | ||
334 | * isci_request object. | ||
335 | * @isci_device: This parameter is the pointer to the isci remote device object | ||
336 | * that is the destination for this request. | ||
337 | * @gfp_flags: This parameter specifies the os allocation flags. | ||
338 | * | ||
339 | * SCI_SUCCESS on successfull completion, or specific failure code. | ||
340 | */ | ||
341 | int isci_request_alloc_tmf( | ||
342 | struct isci_host *isci_host, | ||
343 | struct isci_tmf *isci_tmf, | ||
344 | struct isci_request **isci_request, | ||
345 | struct isci_remote_device *isci_device, | ||
346 | gfp_t gfp_flags) | ||
347 | { | ||
348 | int retval = isci_request_alloc_core(isci_host, isci_request, | ||
349 | isci_device, gfp_flags); | ||
350 | |||
351 | if (!retval) { | ||
352 | |||
353 | (*isci_request)->ttype_ptr.tmf_task_ptr = isci_tmf; | ||
354 | (*isci_request)->ttype = tmf_task; | ||
355 | } | ||
356 | return retval; | ||
357 | } | ||
358 | |||
359 | /** | ||
360 | * isci_request_signal_device_reset() - This function will set the "device | ||
361 | * needs target reset" flag in the given sas_tasks' task_state_flags, and | ||
362 | * then cause the task to be added into the SCSI error handler queue which | ||
363 | * will eventually be escalated to a target reset. | ||
364 | * | ||
365 | * | ||
366 | */ | ||
367 | static void isci_request_signal_device_reset( | ||
368 | struct isci_request *isci_request) | ||
369 | { | ||
370 | unsigned long flags; | ||
371 | struct sas_task *task = isci_request_access_task(isci_request); | ||
372 | |||
373 | dev_dbg(&isci_request->isci_host->pdev->dev, | ||
374 | "%s: request=%p, task=%p\n", __func__, isci_request, task); | ||
375 | |||
376 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
377 | task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; | ||
378 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
379 | |||
380 | /* Cause this task to be scheduled in the SCSI error handler | ||
381 | * thread. | ||
382 | */ | ||
383 | sas_task_abort(task); | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * isci_request_execute() - This function allocates the isci_request object, | ||
388 | * all fills in some common fields. | ||
389 | * @isci_host: This parameter specifies the ISCI host object | ||
390 | * @sas_task: This parameter is the task struct from the upper layer driver. | ||
391 | * @isci_request: This parameter will contain the pointer to the new | ||
392 | * isci_request object. | ||
393 | * @gfp_flags: This parameter specifies the os allocation flags. | ||
394 | * | ||
395 | * SCI_SUCCESS on successfull completion, or specific failure code. | ||
396 | */ | ||
397 | int isci_request_execute( | ||
398 | struct isci_host *isci_host, | ||
399 | struct sas_task *task, | ||
400 | struct isci_request **isci_request, | ||
401 | gfp_t gfp_flags) | ||
402 | { | ||
403 | int ret = 0; | ||
404 | struct scic_sds_remote_device *sci_device; | ||
405 | enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL; | ||
406 | struct isci_remote_device *isci_device; | ||
407 | struct isci_request *request; | ||
408 | unsigned long flags; | ||
409 | |||
410 | isci_device = isci_dev_from_domain_dev(task->dev); | ||
411 | sci_device = isci_device->sci_device_handle; | ||
412 | |||
413 | /* do common allocation and init of request object. */ | ||
414 | ret = isci_request_alloc_io( | ||
415 | isci_host, | ||
416 | task, | ||
417 | &request, | ||
418 | isci_device, | ||
419 | gfp_flags | ||
420 | ); | ||
421 | |||
422 | if (ret) | ||
423 | goto out; | ||
424 | |||
425 | status = isci_io_request_build(isci_host, request, isci_device); | ||
426 | if (status == SCI_SUCCESS) { | ||
427 | |||
428 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
429 | |||
430 | /* send the request, let the core assign the IO TAG. */ | ||
431 | status = scic_controller_start_io( | ||
432 | isci_host->core_controller, | ||
433 | sci_device, | ||
434 | request->sci_request_handle, | ||
435 | SCI_CONTROLLER_INVALID_IO_TAG | ||
436 | ); | ||
437 | |||
438 | if (status == SCI_SUCCESS || | ||
439 | status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { | ||
440 | |||
441 | /* Either I/O started OK, or the core has signaled that | ||
442 | * the device needs a target reset. | ||
443 | * | ||
444 | * In either case, hold onto the I/O for later. | ||
445 | * | ||
446 | * Update it's status and add it to the list in the | ||
447 | * remote device object. | ||
448 | */ | ||
449 | isci_request_change_state(request, started); | ||
450 | list_add(&request->dev_node, | ||
451 | &isci_device->reqs_in_process); | ||
452 | |||
453 | if (status == | ||
454 | SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) { | ||
455 | /* Signal libsas that we need the SCSI error | ||
456 | * handler thread to work on this I/O and that | ||
457 | * we want a device reset. | ||
458 | */ | ||
459 | isci_request_signal_device_reset(request); | ||
460 | |||
461 | /* Change the status, since we are holding | ||
462 | * the I/O until it is managed by the SCSI | ||
463 | * error handler. | ||
464 | */ | ||
465 | status = SCI_SUCCESS; | ||
466 | } | ||
467 | } else | ||
468 | dev_warn(&isci_host->pdev->dev, | ||
469 | "%s: failed request start\n", | ||
470 | __func__); | ||
471 | |||
472 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
473 | |||
474 | } else | ||
475 | dev_warn(&isci_host->pdev->dev, | ||
476 | "%s: request_construct failed - status = 0x%x\n", | ||
477 | __func__, | ||
478 | status); | ||
479 | |||
480 | out: | ||
481 | if (status != SCI_SUCCESS) { | ||
482 | |||
483 | /* release dma memory on failure. */ | ||
484 | isci_request_free(isci_host, request); | ||
485 | request = NULL; | ||
486 | ret = SCI_FAILURE; | ||
487 | } | ||
488 | |||
489 | *isci_request = request; | ||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | |||
494 | /** | ||
495 | * isci_request_process_response_iu() - This function sets the status and | ||
496 | * response iu, in the task struct, from the request object for the upper | ||
497 | * layer driver. | ||
498 | * @sas_task: This parameter is the task struct from the upper layer driver. | ||
499 | * @resp_iu: This parameter points to the response iu of the completed request. | ||
500 | * @dev: This parameter specifies the linux device struct. | ||
501 | * | ||
502 | * none. | ||
503 | */ | ||
504 | static void isci_request_process_response_iu( | ||
505 | struct sas_task *task, | ||
506 | struct ssp_response_iu *resp_iu, | ||
507 | struct device *dev) | ||
508 | { | ||
509 | dev_dbg(dev, | ||
510 | "%s: resp_iu = %p " | ||
511 | "resp_iu->status = 0x%x,\nresp_iu->datapres = %d " | ||
512 | "resp_iu->response_data_len = %x, " | ||
513 | "resp_iu->sense_data_len = %x\nrepsonse data: ", | ||
514 | __func__, | ||
515 | resp_iu, | ||
516 | resp_iu->status, | ||
517 | resp_iu->datapres, | ||
518 | resp_iu->response_data_len, | ||
519 | resp_iu->sense_data_len); | ||
520 | |||
521 | task->task_status.stat = resp_iu->status; | ||
522 | |||
523 | /* libsas updates the task status fields based on the response iu. */ | ||
524 | sas_ssp_task_response(dev, task, resp_iu); | ||
525 | } | ||
526 | |||
527 | /** | ||
528 | * isci_request_set_open_reject_status() - This function prepares the I/O | ||
529 | * completion for OPEN_REJECT conditions. | ||
530 | * @request: This parameter is the completed isci_request object. | ||
531 | * @response_ptr: This parameter specifies the service response for the I/O. | ||
532 | * @status_ptr: This parameter specifies the exec status for the I/O. | ||
533 | * @complete_to_host_ptr: This parameter specifies the action to be taken by | ||
534 | * the LLDD with respect to completing this request or forcing an abort | ||
535 | * condition on the I/O. | ||
536 | * @open_rej_reason: This parameter specifies the encoded reason for the | ||
537 | * abandon-class reject. | ||
538 | * | ||
539 | * none. | ||
540 | */ | ||
541 | static void isci_request_set_open_reject_status( | ||
542 | struct isci_request *request, | ||
543 | struct sas_task *task, | ||
544 | enum service_response *response_ptr, | ||
545 | enum exec_status *status_ptr, | ||
546 | enum isci_completion_selection *complete_to_host_ptr, | ||
547 | enum sas_open_rej_reason open_rej_reason) | ||
548 | { | ||
549 | /* Task in the target is done. */ | ||
550 | request->complete_in_target = true; | ||
551 | *response_ptr = SAS_TASK_UNDELIVERED; | ||
552 | *status_ptr = SAS_OPEN_REJECT; | ||
553 | *complete_to_host_ptr = isci_perform_normal_io_completion; | ||
554 | task->task_status.open_rej_reason = open_rej_reason; | ||
555 | } | ||
556 | |||
557 | /** | ||
558 | * isci_request_handle_controller_specific_errors() - This function decodes | ||
559 | * controller-specific I/O completion error conditions. | ||
560 | * @request: This parameter is the completed isci_request object. | ||
561 | * @response_ptr: This parameter specifies the service response for the I/O. | ||
562 | * @status_ptr: This parameter specifies the exec status for the I/O. | ||
563 | * @complete_to_host_ptr: This parameter specifies the action to be taken by | ||
564 | * the LLDD with respect to completing this request or forcing an abort | ||
565 | * condition on the I/O. | ||
566 | * | ||
567 | * none. | ||
568 | */ | ||
569 | static void isci_request_handle_controller_specific_errors( | ||
570 | struct isci_remote_device *isci_device, | ||
571 | struct isci_request *request, | ||
572 | struct sas_task *task, | ||
573 | enum service_response *response_ptr, | ||
574 | enum exec_status *status_ptr, | ||
575 | enum isci_completion_selection *complete_to_host_ptr) | ||
576 | { | ||
577 | unsigned int cstatus; | ||
578 | |||
579 | cstatus = scic_request_get_controller_status( | ||
580 | request->sci_request_handle | ||
581 | ); | ||
582 | |||
583 | dev_dbg(&request->isci_host->pdev->dev, | ||
584 | "%s: %p SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR " | ||
585 | "- controller status = 0x%x\n", | ||
586 | __func__, request, cstatus); | ||
587 | |||
588 | /* Decode the controller-specific errors; most | ||
589 | * important is to recognize those conditions in which | ||
590 | * the target may still have a task outstanding that | ||
591 | * must be aborted. | ||
592 | * | ||
593 | * Note that there are SCU completion codes being | ||
594 | * named in the decode below for which SCIC has already | ||
595 | * done work to handle them in a way other than as | ||
596 | * a controller-specific completion code; these are left | ||
597 | * in the decode below for completeness sake. | ||
598 | */ | ||
599 | switch (cstatus) { | ||
600 | case SCU_TASK_DONE_DMASETUP_DIRERR: | ||
601 | /* Also SCU_TASK_DONE_SMP_FRM_TYPE_ERR: */ | ||
602 | case SCU_TASK_DONE_XFERCNT_ERR: | ||
603 | /* Also SCU_TASK_DONE_SMP_UFI_ERR: */ | ||
604 | if (task->task_proto == SAS_PROTOCOL_SMP) { | ||
605 | /* SCU_TASK_DONE_SMP_UFI_ERR == Task Done. */ | ||
606 | *response_ptr = SAS_TASK_COMPLETE; | ||
607 | |||
608 | /* See if the device has been/is being stopped. Note | ||
609 | * that we ignore the quiesce state, since we are | ||
610 | * concerned about the actual device state. | ||
611 | */ | ||
612 | if ((isci_device->status == isci_stopping) || | ||
613 | (isci_device->status == isci_stopped)) | ||
614 | *status_ptr = SAS_DEVICE_UNKNOWN; | ||
615 | else | ||
616 | *status_ptr = SAS_ABORTED_TASK; | ||
617 | |||
618 | request->complete_in_target = true; | ||
619 | |||
620 | *complete_to_host_ptr = | ||
621 | isci_perform_normal_io_completion; | ||
622 | } else { | ||
623 | /* Task in the target is not done. */ | ||
624 | *response_ptr = SAS_TASK_UNDELIVERED; | ||
625 | |||
626 | if ((isci_device->status == isci_stopping) || | ||
627 | (isci_device->status == isci_stopped)) | ||
628 | *status_ptr = SAS_DEVICE_UNKNOWN; | ||
629 | else | ||
630 | *status_ptr = SAM_STAT_TASK_ABORTED; | ||
631 | |||
632 | request->complete_in_target = false; | ||
633 | |||
634 | *complete_to_host_ptr = | ||
635 | isci_perform_error_io_completion; | ||
636 | } | ||
637 | |||
638 | break; | ||
639 | |||
640 | case SCU_TASK_DONE_CRC_ERR: | ||
641 | case SCU_TASK_DONE_NAK_CMD_ERR: | ||
642 | case SCU_TASK_DONE_EXCESS_DATA: | ||
643 | case SCU_TASK_DONE_UNEXP_FIS: | ||
644 | /* Also SCU_TASK_DONE_UNEXP_RESP: */ | ||
645 | case SCU_TASK_DONE_VIIT_ENTRY_NV: /* TODO - conditions? */ | ||
646 | case SCU_TASK_DONE_IIT_ENTRY_NV: /* TODO - conditions? */ | ||
647 | case SCU_TASK_DONE_RNCNV_OUTBOUND: /* TODO - conditions? */ | ||
648 | /* These are conditions in which the target | ||
649 | * has completed the task, so that no cleanup | ||
650 | * is necessary. | ||
651 | */ | ||
652 | *response_ptr = SAS_TASK_COMPLETE; | ||
653 | |||
654 | /* See if the device has been/is being stopped. Note | ||
655 | * that we ignore the quiesce state, since we are | ||
656 | * concerned about the actual device state. | ||
657 | */ | ||
658 | if ((isci_device->status == isci_stopping) || | ||
659 | (isci_device->status == isci_stopped)) | ||
660 | *status_ptr = SAS_DEVICE_UNKNOWN; | ||
661 | else | ||
662 | *status_ptr = SAS_ABORTED_TASK; | ||
663 | |||
664 | request->complete_in_target = true; | ||
665 | |||
666 | *complete_to_host_ptr = isci_perform_normal_io_completion; | ||
667 | break; | ||
668 | |||
669 | |||
670 | /* Note that the only open reject completion codes seen here will be | ||
671 | * abandon-class codes; all others are automatically retried in the SCU. | ||
672 | */ | ||
673 | case SCU_TASK_OPEN_REJECT_WRONG_DESTINATION: | ||
674 | |||
675 | isci_request_set_open_reject_status( | ||
676 | request, task, response_ptr, status_ptr, | ||
677 | complete_to_host_ptr, SAS_OREJ_WRONG_DEST); | ||
678 | break; | ||
679 | |||
680 | case SCU_TASK_OPEN_REJECT_ZONE_VIOLATION: | ||
681 | |||
682 | /* Note - the return of AB0 will change when | ||
683 | * libsas implements detection of zone violations. | ||
684 | */ | ||
685 | isci_request_set_open_reject_status( | ||
686 | request, task, response_ptr, status_ptr, | ||
687 | complete_to_host_ptr, SAS_OREJ_RESV_AB0); | ||
688 | break; | ||
689 | |||
690 | case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1: | ||
691 | |||
692 | isci_request_set_open_reject_status( | ||
693 | request, task, response_ptr, status_ptr, | ||
694 | complete_to_host_ptr, SAS_OREJ_RESV_AB1); | ||
695 | break; | ||
696 | |||
697 | case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2: | ||
698 | |||
699 | isci_request_set_open_reject_status( | ||
700 | request, task, response_ptr, status_ptr, | ||
701 | complete_to_host_ptr, SAS_OREJ_RESV_AB2); | ||
702 | break; | ||
703 | |||
704 | case SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3: | ||
705 | |||
706 | isci_request_set_open_reject_status( | ||
707 | request, task, response_ptr, status_ptr, | ||
708 | complete_to_host_ptr, SAS_OREJ_RESV_AB3); | ||
709 | break; | ||
710 | |||
711 | case SCU_TASK_OPEN_REJECT_BAD_DESTINATION: | ||
712 | |||
713 | isci_request_set_open_reject_status( | ||
714 | request, task, response_ptr, status_ptr, | ||
715 | complete_to_host_ptr, SAS_OREJ_BAD_DEST); | ||
716 | break; | ||
717 | |||
718 | case SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY: | ||
719 | |||
720 | isci_request_set_open_reject_status( | ||
721 | request, task, response_ptr, status_ptr, | ||
722 | complete_to_host_ptr, SAS_OREJ_STP_NORES); | ||
723 | break; | ||
724 | |||
725 | case SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED: | ||
726 | |||
727 | isci_request_set_open_reject_status( | ||
728 | request, task, response_ptr, status_ptr, | ||
729 | complete_to_host_ptr, SAS_OREJ_EPROTO); | ||
730 | break; | ||
731 | |||
732 | case SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED: | ||
733 | |||
734 | isci_request_set_open_reject_status( | ||
735 | request, task, response_ptr, status_ptr, | ||
736 | complete_to_host_ptr, SAS_OREJ_CONN_RATE); | ||
737 | break; | ||
738 | |||
739 | case SCU_TASK_DONE_LL_R_ERR: | ||
740 | /* Also SCU_TASK_DONE_ACK_NAK_TO: */ | ||
741 | case SCU_TASK_DONE_LL_PERR: | ||
742 | case SCU_TASK_DONE_LL_SY_TERM: | ||
743 | /* Also SCU_TASK_DONE_NAK_ERR:*/ | ||
744 | case SCU_TASK_DONE_LL_LF_TERM: | ||
745 | /* Also SCU_TASK_DONE_DATA_LEN_ERR: */ | ||
746 | case SCU_TASK_DONE_LL_ABORT_ERR: | ||
747 | case SCU_TASK_DONE_SEQ_INV_TYPE: | ||
748 | /* Also SCU_TASK_DONE_UNEXP_XR: */ | ||
749 | case SCU_TASK_DONE_XR_IU_LEN_ERR: | ||
750 | case SCU_TASK_DONE_INV_FIS_LEN: | ||
751 | /* Also SCU_TASK_DONE_XR_WD_LEN: */ | ||
752 | case SCU_TASK_DONE_SDMA_ERR: | ||
753 | case SCU_TASK_DONE_OFFSET_ERR: | ||
754 | case SCU_TASK_DONE_MAX_PLD_ERR: | ||
755 | case SCU_TASK_DONE_LF_ERR: | ||
756 | case SCU_TASK_DONE_SMP_RESP_TO_ERR: /* Escalate to dev reset? */ | ||
757 | case SCU_TASK_DONE_SMP_LL_RX_ERR: | ||
758 | case SCU_TASK_DONE_UNEXP_DATA: | ||
759 | case SCU_TASK_DONE_UNEXP_SDBFIS: | ||
760 | case SCU_TASK_DONE_REG_ERR: | ||
761 | case SCU_TASK_DONE_SDB_ERR: | ||
762 | case SCU_TASK_DONE_TASK_ABORT: | ||
763 | default: | ||
764 | /* Task in the target is not done. */ | ||
765 | *response_ptr = SAS_TASK_UNDELIVERED; | ||
766 | *status_ptr = SAM_STAT_TASK_ABORTED; | ||
767 | request->complete_in_target = false; | ||
768 | |||
769 | *complete_to_host_ptr = isci_perform_error_io_completion; | ||
770 | break; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | /** | ||
775 | * isci_task_save_for_upper_layer_completion() - This function saves the | ||
776 | * request for later completion to the upper layer driver. | ||
777 | * @host: This parameter is a pointer to the host on which the the request | ||
778 | * should be queued (either as an error or success). | ||
779 | * @request: This parameter is the completed request. | ||
780 | * @response: This parameter is the response code for the completed task. | ||
781 | * @status: This parameter is the status code for the completed task. | ||
782 | * | ||
783 | * none. | ||
784 | */ | ||
785 | static void isci_task_save_for_upper_layer_completion( | ||
786 | struct isci_host *host, | ||
787 | struct isci_request *request, | ||
788 | enum service_response response, | ||
789 | enum exec_status status, | ||
790 | enum isci_completion_selection task_notification_selection) | ||
791 | { | ||
792 | struct sas_task *task = isci_request_access_task(request); | ||
793 | |||
794 | isci_task_set_completion_status(task, response, status, | ||
795 | task_notification_selection); | ||
796 | |||
797 | |||
798 | /* Tasks aborted specifically by a call to the lldd_abort_task | ||
799 | * function should not be completed to the host in the regular path. | ||
800 | */ | ||
801 | switch (task_notification_selection) { | ||
802 | |||
803 | case isci_perform_normal_io_completion: | ||
804 | |||
805 | /* Normal notification (task_done) */ | ||
806 | dev_dbg(&host->pdev->dev, | ||
807 | "%s: Normal - task = %p, response=%d, status=%d\n", | ||
808 | __func__, | ||
809 | task, | ||
810 | response, | ||
811 | status); | ||
812 | /* Add to the completed list. */ | ||
813 | list_add(&request->completed_node, | ||
814 | &host->requests_to_complete); | ||
815 | break; | ||
816 | |||
817 | case isci_perform_aborted_io_completion: | ||
818 | /* | ||
819 | * No notification because this request is already | ||
820 | * in the abort path. | ||
821 | */ | ||
822 | dev_warn(&host->pdev->dev, | ||
823 | "%s: Aborted - task = %p, response=%d, status=%d\n", | ||
824 | __func__, | ||
825 | task, | ||
826 | response, | ||
827 | status); | ||
828 | break; | ||
829 | |||
830 | case isci_perform_error_io_completion: | ||
831 | /* Use sas_task_abort */ | ||
832 | dev_warn(&host->pdev->dev, | ||
833 | "%s: Error - task = %p, response=%d, status=%d\n", | ||
834 | __func__, | ||
835 | task, | ||
836 | response, | ||
837 | status); | ||
838 | /* Add to the aborted list. */ | ||
839 | list_add(&request->completed_node, | ||
840 | &host->requests_to_abort); | ||
841 | break; | ||
842 | |||
843 | default: | ||
844 | dev_warn(&host->pdev->dev, | ||
845 | "%s: Unknown - task = %p, response=%d, status=%d\n", | ||
846 | __func__, | ||
847 | task, | ||
848 | response, | ||
849 | status); | ||
850 | |||
851 | /* Add to the aborted list. */ | ||
852 | list_add(&request->completed_node, | ||
853 | &host->requests_to_abort); | ||
854 | break; | ||
855 | } | ||
856 | } | ||
857 | |||
858 | /** | ||
859 | * isci_request_io_request_complete() - This function is called by the sci core | ||
860 | * when an io request completes. | ||
861 | * @isci_host: This parameter specifies the ISCI host object | ||
862 | * @request: This parameter is the completed isci_request object. | ||
863 | * @completion_status: This parameter specifies the completion status from the | ||
864 | * sci core. | ||
865 | * | ||
866 | * none. | ||
867 | */ | ||
868 | void isci_request_io_request_complete( | ||
869 | struct isci_host *isci_host, | ||
870 | struct isci_request *request, | ||
871 | enum sci_io_status completion_status) | ||
872 | { | ||
873 | struct sas_task *task = isci_request_access_task(request); | ||
874 | struct ssp_response_iu *resp_iu; | ||
875 | void *resp_buf; | ||
876 | unsigned long task_flags; | ||
877 | unsigned long state_flags; | ||
878 | struct completion *io_request_completion; | ||
879 | struct isci_remote_device *isci_device = request->isci_device; | ||
880 | enum service_response response = SAS_TASK_UNDELIVERED; | ||
881 | enum exec_status status = SAS_ABORTED_TASK; | ||
882 | enum isci_request_status request_status; | ||
883 | enum isci_completion_selection complete_to_host | ||
884 | = isci_perform_normal_io_completion; | ||
885 | |||
886 | dev_dbg(&isci_host->pdev->dev, | ||
887 | "%s: request = %p, task = %p,\n" | ||
888 | "task->data_dir = %d completion_status = 0x%x\n", | ||
889 | __func__, | ||
890 | request, | ||
891 | task, | ||
892 | task->data_dir, | ||
893 | completion_status); | ||
894 | |||
895 | spin_lock_irqsave(&request->state_lock, state_flags); | ||
896 | request_status = isci_request_get_state(request); | ||
897 | spin_unlock_irqrestore(&request->state_lock, state_flags); | ||
898 | |||
899 | /* Decode the request status. Note that if the request has been | ||
900 | * aborted by a task management function, we don't care | ||
901 | * what the status is. | ||
902 | */ | ||
903 | switch (request_status) { | ||
904 | |||
905 | case aborted: | ||
906 | /* "aborted" indicates that the request was aborted by a task | ||
907 | * management function, since once a task management request is | ||
908 | * perfomed by the device, the request only completes because | ||
909 | * of the subsequent driver terminate. | ||
910 | * | ||
911 | * Aborted also means an external thread is explicitly managing | ||
912 | * this request, so that we do not complete it up the stack. | ||
913 | * | ||
914 | * The target is still there (since the TMF was successful). | ||
915 | */ | ||
916 | request->complete_in_target = true; | ||
917 | response = SAS_TASK_COMPLETE; | ||
918 | |||
919 | /* See if the device has been/is being stopped. Note | ||
920 | * that we ignore the quiesce state, since we are | ||
921 | * concerned about the actual device state. | ||
922 | */ | ||
923 | if ((isci_device->status == isci_stopping) | ||
924 | || (isci_device->status == isci_stopped) | ||
925 | ) | ||
926 | status = SAS_DEVICE_UNKNOWN; | ||
927 | else | ||
928 | status = SAS_ABORTED_TASK; | ||
929 | |||
930 | complete_to_host = isci_perform_aborted_io_completion; | ||
931 | /* This was an aborted request. */ | ||
932 | break; | ||
933 | |||
934 | case aborting: | ||
935 | /* aborting means that the task management function tried and | ||
936 | * failed to abort the request. We need to note the request | ||
937 | * as SAS_TASK_UNDELIVERED, so that the scsi mid layer marks the | ||
938 | * target as down. | ||
939 | * | ||
940 | * Aborting also means an external thread is explicitly managing | ||
941 | * this request, so that we do not complete it up the stack. | ||
942 | */ | ||
943 | request->complete_in_target = true; | ||
944 | response = SAS_TASK_UNDELIVERED; | ||
945 | |||
946 | if ((isci_device->status == isci_stopping) || | ||
947 | (isci_device->status == isci_stopped)) | ||
948 | /* The device has been /is being stopped. Note that | ||
949 | * we ignore the quiesce state, since we are | ||
950 | * concerned about the actual device state. | ||
951 | */ | ||
952 | status = SAS_DEVICE_UNKNOWN; | ||
953 | else | ||
954 | status = SAS_PHY_DOWN; | ||
955 | |||
956 | complete_to_host = isci_perform_aborted_io_completion; | ||
957 | |||
958 | /* This was an aborted request. */ | ||
959 | break; | ||
960 | |||
961 | case terminating: | ||
962 | |||
963 | /* This was an terminated request. This happens when | ||
964 | * the I/O is being terminated because of an action on | ||
965 | * the device (reset, tear down, etc.), and the I/O needs | ||
966 | * to be completed up the stack. | ||
967 | */ | ||
968 | request->complete_in_target = true; | ||
969 | response = SAS_TASK_UNDELIVERED; | ||
970 | |||
971 | /* See if the device has been/is being stopped. Note | ||
972 | * that we ignore the quiesce state, since we are | ||
973 | * concerned about the actual device state. | ||
974 | */ | ||
975 | if ((isci_device->status == isci_stopping) || | ||
976 | (isci_device->status == isci_stopped)) | ||
977 | status = SAS_DEVICE_UNKNOWN; | ||
978 | else | ||
979 | status = SAS_ABORTED_TASK; | ||
980 | |||
981 | complete_to_host = isci_perform_normal_io_completion; | ||
982 | |||
983 | /* This was a terminated request. */ | ||
984 | break; | ||
985 | |||
986 | default: | ||
987 | |||
988 | /* This is an active request being completed from the core. */ | ||
989 | switch (completion_status) { | ||
990 | |||
991 | case SCI_IO_FAILURE_RESPONSE_VALID: | ||
992 | dev_dbg(&isci_host->pdev->dev, | ||
993 | "%s: SCI_IO_FAILURE_RESPONSE_VALID (%p/%p)\n", | ||
994 | __func__, | ||
995 | request, | ||
996 | task); | ||
997 | |||
998 | if (sas_protocol_ata(task->task_proto)) { | ||
999 | resp_buf | ||
1000 | = scic_stp_io_request_get_d2h_reg_address( | ||
1001 | request->sci_request_handle | ||
1002 | ); | ||
1003 | isci_request_process_stp_response(task, | ||
1004 | resp_buf | ||
1005 | ); | ||
1006 | |||
1007 | } else if (SAS_PROTOCOL_SSP == task->task_proto) { | ||
1008 | |||
1009 | /* crack the iu response buffer. */ | ||
1010 | resp_iu | ||
1011 | = scic_io_request_get_response_iu_address( | ||
1012 | request->sci_request_handle | ||
1013 | ); | ||
1014 | |||
1015 | isci_request_process_response_iu(task, resp_iu, | ||
1016 | &isci_host->pdev->dev | ||
1017 | ); | ||
1018 | |||
1019 | } else if (SAS_PROTOCOL_SMP == task->task_proto) { | ||
1020 | |||
1021 | dev_err(&isci_host->pdev->dev, | ||
1022 | "%s: SCI_IO_FAILURE_RESPONSE_VALID: " | ||
1023 | "SAS_PROTOCOL_SMP protocol\n", | ||
1024 | __func__); | ||
1025 | |||
1026 | } else | ||
1027 | dev_err(&isci_host->pdev->dev, | ||
1028 | "%s: unknown protocol\n", __func__); | ||
1029 | |||
1030 | /* use the task status set in the task struct by the | ||
1031 | * isci_request_process_response_iu call. | ||
1032 | */ | ||
1033 | request->complete_in_target = true; | ||
1034 | response = task->task_status.resp; | ||
1035 | status = task->task_status.stat; | ||
1036 | break; | ||
1037 | |||
1038 | case SCI_IO_SUCCESS: | ||
1039 | case SCI_IO_SUCCESS_IO_DONE_EARLY: | ||
1040 | |||
1041 | response = SAS_TASK_COMPLETE; | ||
1042 | status = SAM_STAT_GOOD; | ||
1043 | request->complete_in_target = true; | ||
1044 | |||
1045 | if (task->task_proto == SAS_PROTOCOL_SMP) { | ||
1046 | |||
1047 | u8 *command_iu_address | ||
1048 | = scic_io_request_get_command_iu_address( | ||
1049 | request->sci_request_handle | ||
1050 | ); | ||
1051 | |||
1052 | dev_dbg(&isci_host->pdev->dev, | ||
1053 | "%s: SMP protocol completion\n", | ||
1054 | __func__); | ||
1055 | |||
1056 | sg_copy_from_buffer( | ||
1057 | &task->smp_task.smp_resp, 1, | ||
1058 | command_iu_address | ||
1059 | + sizeof(struct smp_request), | ||
1060 | sizeof(struct smp_resp) | ||
1061 | ); | ||
1062 | } else if (completion_status | ||
1063 | == SCI_IO_SUCCESS_IO_DONE_EARLY) { | ||
1064 | |||
1065 | /* This was an SSP / STP / SATA transfer. | ||
1066 | * There is a possibility that less data than | ||
1067 | * the maximum was transferred. | ||
1068 | */ | ||
1069 | u32 transferred_length | ||
1070 | = scic_io_request_get_number_of_bytes_transferred( | ||
1071 | request->sci_request_handle); | ||
1072 | |||
1073 | task->task_status.residual | ||
1074 | = task->total_xfer_len - transferred_length; | ||
1075 | |||
1076 | /* If there were residual bytes, call this an | ||
1077 | * underrun. | ||
1078 | */ | ||
1079 | if (task->task_status.residual != 0) | ||
1080 | status = SAS_DATA_UNDERRUN; | ||
1081 | |||
1082 | dev_dbg(&isci_host->pdev->dev, | ||
1083 | "%s: SCI_IO_SUCCESS_IO_DONE_EARLY %d\n", | ||
1084 | __func__, | ||
1085 | status); | ||
1086 | |||
1087 | } else | ||
1088 | dev_dbg(&isci_host->pdev->dev, | ||
1089 | "%s: SCI_IO_SUCCESS\n", | ||
1090 | __func__); | ||
1091 | |||
1092 | break; | ||
1093 | |||
1094 | case SCI_IO_FAILURE_TERMINATED: | ||
1095 | dev_dbg(&isci_host->pdev->dev, | ||
1096 | "%s: SCI_IO_FAILURE_TERMINATED (%p/%p)\n", | ||
1097 | __func__, | ||
1098 | request, | ||
1099 | task); | ||
1100 | |||
1101 | /* The request was terminated explicitly. No handling | ||
1102 | * is needed in the SCSI error handler path. | ||
1103 | */ | ||
1104 | request->complete_in_target = true; | ||
1105 | response = SAS_TASK_UNDELIVERED; | ||
1106 | |||
1107 | /* See if the device has been/is being stopped. Note | ||
1108 | * that we ignore the quiesce state, since we are | ||
1109 | * concerned about the actual device state. | ||
1110 | */ | ||
1111 | if ((isci_device->status == isci_stopping) || | ||
1112 | (isci_device->status == isci_stopped)) | ||
1113 | status = SAS_DEVICE_UNKNOWN; | ||
1114 | else | ||
1115 | status = SAS_ABORTED_TASK; | ||
1116 | |||
1117 | complete_to_host = isci_perform_normal_io_completion; | ||
1118 | break; | ||
1119 | |||
1120 | case SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR: | ||
1121 | |||
1122 | isci_request_handle_controller_specific_errors( | ||
1123 | isci_device, request, task, &response, &status, | ||
1124 | &complete_to_host); | ||
1125 | |||
1126 | break; | ||
1127 | |||
1128 | case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED: | ||
1129 | /* This is a special case, in that the I/O completion | ||
1130 | * is telling us that the device needs a reset. | ||
1131 | * In order for the device reset condition to be | ||
1132 | * noticed, the I/O has to be handled in the error | ||
1133 | * handler. Set the reset flag and cause the | ||
1134 | * SCSI error thread to be scheduled. | ||
1135 | */ | ||
1136 | spin_lock_irqsave(&task->task_state_lock, task_flags); | ||
1137 | task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; | ||
1138 | spin_unlock_irqrestore(&task->task_state_lock, task_flags); | ||
1139 | |||
1140 | complete_to_host = isci_perform_error_io_completion; | ||
1141 | request->complete_in_target = false; | ||
1142 | break; | ||
1143 | |||
1144 | default: | ||
1145 | /* Catch any otherwise unhandled error codes here. */ | ||
1146 | dev_warn(&isci_host->pdev->dev, | ||
1147 | "%s: invalid completion code: 0x%x - " | ||
1148 | "isci_request = %p\n", | ||
1149 | __func__, completion_status, request); | ||
1150 | |||
1151 | response = SAS_TASK_UNDELIVERED; | ||
1152 | |||
1153 | /* See if the device has been/is being stopped. Note | ||
1154 | * that we ignore the quiesce state, since we are | ||
1155 | * concerned about the actual device state. | ||
1156 | */ | ||
1157 | if ((isci_device->status == isci_stopping) || | ||
1158 | (isci_device->status == isci_stopped)) | ||
1159 | status = SAS_DEVICE_UNKNOWN; | ||
1160 | else | ||
1161 | status = SAS_ABORTED_TASK; | ||
1162 | |||
1163 | complete_to_host = isci_perform_error_io_completion; | ||
1164 | request->complete_in_target = false; | ||
1165 | break; | ||
1166 | } | ||
1167 | break; | ||
1168 | } | ||
1169 | |||
1170 | isci_request_unmap_sgl(request, isci_host->pdev); | ||
1171 | |||
1172 | /* Put the completed request on the correct list */ | ||
1173 | isci_task_save_for_upper_layer_completion(isci_host, request, response, | ||
1174 | status, complete_to_host | ||
1175 | ); | ||
1176 | |||
1177 | /* complete the io request to the core. */ | ||
1178 | scic_controller_complete_io( | ||
1179 | isci_host->core_controller, | ||
1180 | isci_device->sci_device_handle, | ||
1181 | request->sci_request_handle | ||
1182 | ); | ||
1183 | /* NULL the request handle so it cannot be completed or | ||
1184 | * terminated again, and to cause any calls into abort | ||
1185 | * task to recognize the already completed case. | ||
1186 | */ | ||
1187 | request->sci_request_handle = NULL; | ||
1188 | |||
1189 | /* Only remove the request from the remote device list | ||
1190 | * of pending requests if we have not requested error | ||
1191 | * handling on this request. | ||
1192 | */ | ||
1193 | if (complete_to_host != isci_perform_error_io_completion) | ||
1194 | list_del_init(&request->dev_node); | ||
1195 | |||
1196 | |||
1197 | /* Save possible completion ptr. */ | ||
1198 | io_request_completion = request->io_request_completion; | ||
1199 | |||
1200 | if (io_request_completion) { | ||
1201 | |||
1202 | /* This is inherantly a regular I/O request, | ||
1203 | * since we are currently in the regular | ||
1204 | * I/O completion callback function. | ||
1205 | * Signal whoever is waiting that this | ||
1206 | * request is complete. | ||
1207 | */ | ||
1208 | complete(io_request_completion); | ||
1209 | } | ||
1210 | |||
1211 | isci_host_can_dequeue(isci_host, 1); | ||
1212 | } | ||
1213 | |||
1214 | /** | ||
1215 | * isci_request_io_request_get_transfer_length() - This function is called by | ||
1216 | * the sci core to retrieve the transfer length for a given request. | ||
1217 | * @request: This parameter is the isci_request object. | ||
1218 | * | ||
1219 | * length of transfer for specified request. | ||
1220 | */ | ||
1221 | u32 isci_request_io_request_get_transfer_length(struct isci_request *request) | ||
1222 | { | ||
1223 | struct sas_task *task = isci_request_access_task(request); | ||
1224 | |||
1225 | dev_dbg(&request->isci_host->pdev->dev, | ||
1226 | "%s: total_xfer_len: %d\n", | ||
1227 | __func__, | ||
1228 | task->total_xfer_len); | ||
1229 | return task->total_xfer_len; | ||
1230 | } | ||
1231 | |||
1232 | |||
1233 | /** | ||
1234 | * isci_request_io_request_get_data_direction() - This function is called by | ||
1235 | * the sci core to retrieve the data direction for a given request. | ||
1236 | * @request: This parameter is the isci_request object. | ||
1237 | * | ||
1238 | * data direction for specified request. | ||
1239 | */ | ||
1240 | SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction( | ||
1241 | struct isci_request *request) | ||
1242 | { | ||
1243 | struct sas_task *task = isci_request_access_task(request); | ||
1244 | SCI_IO_REQUEST_DATA_DIRECTION ret; | ||
1245 | |||
1246 | switch (task->data_dir) { | ||
1247 | |||
1248 | case DMA_FROM_DEVICE: | ||
1249 | ret = SCI_IO_REQUEST_DATA_IN; | ||
1250 | dev_dbg(&request->isci_host->pdev->dev, | ||
1251 | "%s: request=%p, FROM_DEVICE\n", | ||
1252 | __func__, | ||
1253 | request); | ||
1254 | break; | ||
1255 | |||
1256 | case DMA_TO_DEVICE: | ||
1257 | ret = SCI_IO_REQUEST_DATA_OUT; | ||
1258 | dev_dbg(&request->isci_host->pdev->dev, | ||
1259 | "%s: request=%p, TO_DEVICE\n", | ||
1260 | __func__, | ||
1261 | request); | ||
1262 | break; | ||
1263 | |||
1264 | case DMA_BIDIRECTIONAL: | ||
1265 | case DMA_NONE: | ||
1266 | default: | ||
1267 | ret = SCI_IO_REQUEST_NO_DATA; | ||
1268 | dev_dbg(&request->isci_host->pdev->dev, | ||
1269 | "%s: request=%p, unhandled direction case, " | ||
1270 | "data_dir=%d\n", | ||
1271 | __func__, | ||
1272 | request, | ||
1273 | task->data_dir); | ||
1274 | break; | ||
1275 | |||
1276 | } | ||
1277 | return ret; | ||
1278 | } | ||
1279 | |||
1280 | /** | ||
1281 | * isci_request_sge_get_address_field() - This function is called by the sci | ||
1282 | * core to retrieve the address field contents for a given sge. | ||
1283 | * @request: This parameter is the isci_request object. | ||
1284 | * @sge_address: This parameter is the sge. | ||
1285 | * | ||
1286 | * physical address in the specified sge. | ||
1287 | */ | ||
1288 | dma_addr_t isci_request_sge_get_address_field( | ||
1289 | struct isci_request *request, | ||
1290 | void *sge_address) | ||
1291 | { | ||
1292 | struct sas_task *task = isci_request_access_task(request); | ||
1293 | dma_addr_t ret; | ||
1294 | struct isci_host *isci_host = isci_host_from_sas_ha( | ||
1295 | task->dev->port->ha); | ||
1296 | |||
1297 | dev_dbg(&isci_host->pdev->dev, | ||
1298 | "%s: request = %p, sge_address = %p\n", | ||
1299 | __func__, | ||
1300 | request, | ||
1301 | sge_address); | ||
1302 | |||
1303 | if (task->data_dir == PCI_DMA_NONE) | ||
1304 | return 0; | ||
1305 | |||
1306 | /* the case where num_scatter == 0 is special, in that | ||
1307 | * task->scatter is the actual buffer address, not an sgl. | ||
1308 | * so a map single is required here. | ||
1309 | */ | ||
1310 | if ((task->num_scatter == 0) && | ||
1311 | !sas_protocol_ata(task->task_proto)) { | ||
1312 | ret = dma_map_single( | ||
1313 | &isci_host->pdev->dev, | ||
1314 | task->scatter, | ||
1315 | task->total_xfer_len, | ||
1316 | task->data_dir | ||
1317 | ); | ||
1318 | request->zero_scatter_daddr = ret; | ||
1319 | } else | ||
1320 | ret = sg_dma_address(((struct scatterlist *)sge_address)); | ||
1321 | |||
1322 | dev_dbg(&isci_host->pdev->dev, | ||
1323 | "%s: bus address = %lx\n", | ||
1324 | __func__, | ||
1325 | (unsigned long)ret); | ||
1326 | |||
1327 | return ret; | ||
1328 | } | ||
1329 | |||
1330 | |||
1331 | /** | ||
1332 | * isci_request_sge_get_length_field() - This function is called by the sci | ||
1333 | * core to retrieve the length field contents for a given sge. | ||
1334 | * @request: This parameter is the isci_request object. | ||
1335 | * @sge_address: This parameter is the sge. | ||
1336 | * | ||
1337 | * length field value in the specified sge. | ||
1338 | */ | ||
1339 | u32 isci_request_sge_get_length_field( | ||
1340 | struct isci_request *request, | ||
1341 | void *sge_address) | ||
1342 | { | ||
1343 | struct sas_task *task = isci_request_access_task(request); | ||
1344 | int ret; | ||
1345 | |||
1346 | dev_dbg(&request->isci_host->pdev->dev, | ||
1347 | "%s: request = %p, sge_address = %p\n", | ||
1348 | __func__, | ||
1349 | request, | ||
1350 | sge_address); | ||
1351 | |||
1352 | if (task->data_dir == PCI_DMA_NONE) | ||
1353 | return 0; | ||
1354 | |||
1355 | /* the case where num_scatter == 0 is special, in that | ||
1356 | * task->scatter is the actual buffer address, not an sgl. | ||
1357 | * so we return total_xfer_len here. | ||
1358 | */ | ||
1359 | if (task->num_scatter == 0) | ||
1360 | ret = task->total_xfer_len; | ||
1361 | else | ||
1362 | ret = sg_dma_len((struct scatterlist *)sge_address); | ||
1363 | |||
1364 | dev_dbg(&request->isci_host->pdev->dev, | ||
1365 | "%s: len = %d\n", | ||
1366 | __func__, | ||
1367 | ret); | ||
1368 | |||
1369 | return ret; | ||
1370 | } | ||
1371 | |||
1372 | |||
1373 | /** | ||
1374 | * isci_request_ssp_io_request_get_cdb_address() - This function is called by | ||
1375 | * the sci core to retrieve the cdb address for a given request. | ||
1376 | * @request: This parameter is the isci_request object. | ||
1377 | * | ||
1378 | * cdb address for specified request. | ||
1379 | */ | ||
1380 | void *isci_request_ssp_io_request_get_cdb_address( | ||
1381 | struct isci_request *request) | ||
1382 | { | ||
1383 | struct sas_task *task = isci_request_access_task(request); | ||
1384 | |||
1385 | dev_dbg(&request->isci_host->pdev->dev, | ||
1386 | "%s: request->task->ssp_task.cdb = %p\n", | ||
1387 | __func__, | ||
1388 | task->ssp_task.cdb); | ||
1389 | return task->ssp_task.cdb; | ||
1390 | } | ||
1391 | |||
1392 | |||
1393 | /** | ||
1394 | * isci_request_ssp_io_request_get_cdb_length() - This function is called by | ||
1395 | * the sci core to retrieve the cdb length for a given request. | ||
1396 | * @request: This parameter is the isci_request object. | ||
1397 | * | ||
1398 | * cdb length for specified request. | ||
1399 | */ | ||
1400 | u32 isci_request_ssp_io_request_get_cdb_length( | ||
1401 | struct isci_request *request) | ||
1402 | { | ||
1403 | return 16; | ||
1404 | } | ||
1405 | |||
1406 | |||
1407 | /** | ||
1408 | * isci_request_ssp_io_request_get_lun() - This function is called by the sci | ||
1409 | * core to retrieve the lun for a given request. | ||
1410 | * @request: This parameter is the isci_request object. | ||
1411 | * | ||
1412 | * lun for specified request. | ||
1413 | */ | ||
1414 | u32 isci_request_ssp_io_request_get_lun( | ||
1415 | struct isci_request *request) | ||
1416 | { | ||
1417 | struct sas_task *task = isci_request_access_task(request); | ||
1418 | |||
1419 | #ifdef DEBUG | ||
1420 | int i; | ||
1421 | |||
1422 | for (i = 0; i < 8; i++) | ||
1423 | dev_dbg(&request->isci_host->pdev->dev, | ||
1424 | "%s: request->task->ssp_task.LUN[%d] = %x\n", | ||
1425 | __func__, i, request->task->ssp_task.LUN[i]); | ||
1426 | |||
1427 | #endif | ||
1428 | |||
1429 | return task->ssp_task.LUN[0]; | ||
1430 | } | ||
1431 | |||
1432 | |||
1433 | /** | ||
1434 | * isci_request_ssp_io_request_get_task_attribute() - This function is called | ||
1435 | * by the sci core to retrieve the task attribute for a given request. | ||
1436 | * @request: This parameter is the isci_request object. | ||
1437 | * | ||
1438 | * task attribute for specified request. | ||
1439 | */ | ||
1440 | u32 isci_request_ssp_io_request_get_task_attribute( | ||
1441 | struct isci_request *request) | ||
1442 | { | ||
1443 | struct sas_task *task = isci_request_access_task(request); | ||
1444 | |||
1445 | dev_dbg(&request->isci_host->pdev->dev, | ||
1446 | "%s: request->task->ssp_task.task_attr = %x\n", | ||
1447 | __func__, | ||
1448 | task->ssp_task.task_attr); | ||
1449 | |||
1450 | return task->ssp_task.task_attr; | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | /** | ||
1455 | * isci_request_ssp_io_request_get_command_priority() - This function is called | ||
1456 | * by the sci core to retrieve the command priority for a given request. | ||
1457 | * @request: This parameter is the isci_request object. | ||
1458 | * | ||
1459 | * command priority for specified request. | ||
1460 | */ | ||
1461 | u32 isci_request_ssp_io_request_get_command_priority( | ||
1462 | struct isci_request *request) | ||
1463 | { | ||
1464 | struct sas_task *task = isci_request_access_task(request); | ||
1465 | |||
1466 | dev_dbg(&request->isci_host->pdev->dev, | ||
1467 | "%s: request->task->ssp_task.task_prio = %x\n", | ||
1468 | __func__, | ||
1469 | task->ssp_task.task_prio); | ||
1470 | |||
1471 | return task->ssp_task.task_prio; | ||
1472 | } | ||
diff --git a/drivers/scsi/isci/request.h b/drivers/scsi/isci/request.h new file mode 100644 index 000000000000..5079d4a7c41b --- /dev/null +++ b/drivers/scsi/isci/request.h | |||
@@ -0,0 +1,429 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #if !defined(_ISCI_REQUEST_H_) | ||
57 | #define _ISCI_REQUEST_H_ | ||
58 | |||
59 | #include "isci.h" | ||
60 | |||
61 | /** | ||
62 | * struct isci_request_status - This enum defines the possible states of an I/O | ||
63 | * request. | ||
64 | * | ||
65 | * | ||
66 | */ | ||
67 | enum isci_request_status { | ||
68 | unallocated = 0x00, | ||
69 | allocated = 0x01, | ||
70 | started = 0x02, | ||
71 | completed = 0x03, | ||
72 | aborting = 0x04, | ||
73 | aborted = 0x05, | ||
74 | terminating = 0x06 | ||
75 | }; | ||
76 | |||
77 | enum task_type { | ||
78 | io_task = 0, | ||
79 | tmf_task = 1 | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * struct isci_request - This class represents the request object used to track | ||
84 | * IO, smp and TMF request internal. It wraps the SCIC request object. | ||
85 | * | ||
86 | * | ||
87 | */ | ||
88 | struct isci_request { | ||
89 | |||
90 | struct scic_sds_request *sci_request_handle; | ||
91 | |||
92 | enum isci_request_status status; | ||
93 | enum task_type ttype; | ||
94 | unsigned short io_tag; | ||
95 | bool complete_in_target; | ||
96 | |||
97 | union ttype_ptr_union { | ||
98 | struct sas_task *io_task_ptr; /* When ttype==io_task */ | ||
99 | struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */ | ||
100 | } ttype_ptr; | ||
101 | struct isci_host *isci_host; | ||
102 | struct isci_remote_device *isci_device; | ||
103 | /* For use in the requests_to_{complete|abort} lists: */ | ||
104 | struct list_head completed_node; | ||
105 | /* For use in the reqs_in_process list: */ | ||
106 | struct list_head dev_node; | ||
107 | void *sci_request_mem_ptr; | ||
108 | spinlock_t state_lock; | ||
109 | dma_addr_t request_daddr; | ||
110 | dma_addr_t zero_scatter_daddr; | ||
111 | |||
112 | unsigned int num_sg_entries; /* returned by pci_alloc_sg */ | ||
113 | unsigned int request_alloc_size; /* size of block from dma_pool_alloc */ | ||
114 | |||
115 | /** Note: "io_request_completion" is completed in two different ways | ||
116 | * depending on whether this is a TMF or regular request. | ||
117 | * - TMF requests are completed in the thread that started them; | ||
118 | * - regular requests are completed in the request completion callback | ||
119 | * function. | ||
120 | * This difference in operation allows the aborter of a TMF request | ||
121 | * to be sure that once the TMF request completes, the I/O that the | ||
122 | * TMF was aborting is guaranteed to have completed. | ||
123 | */ | ||
124 | struct completion *io_request_completion; | ||
125 | }; | ||
126 | |||
127 | /** | ||
128 | * This function gets the status of the request object. | ||
129 | * @request: This parameter points to the isci_request object | ||
130 | * | ||
131 | * status of the object as a isci_request_status enum. | ||
132 | */ | ||
133 | static inline | ||
134 | enum isci_request_status isci_request_get_state( | ||
135 | struct isci_request *isci_request) | ||
136 | { | ||
137 | BUG_ON(isci_request == NULL); | ||
138 | |||
139 | /*probably a bad sign... */ | ||
140 | if (isci_request->status == unallocated) | ||
141 | dev_warn(&isci_request->isci_host->pdev->dev, | ||
142 | "%s: isci_request->status == unallocated\n", | ||
143 | __func__); | ||
144 | |||
145 | return isci_request->status; | ||
146 | } | ||
147 | |||
148 | |||
149 | /** | ||
150 | * isci_request_change_state() - This function sets the status of the request | ||
151 | * object. | ||
152 | * @request: This parameter points to the isci_request object | ||
153 | * @status: This Parameter is the new status of the object | ||
154 | * | ||
155 | */ | ||
156 | static inline enum isci_request_status isci_request_change_state( | ||
157 | struct isci_request *isci_request, | ||
158 | enum isci_request_status status) | ||
159 | { | ||
160 | enum isci_request_status old_state; | ||
161 | unsigned long flags; | ||
162 | |||
163 | dev_dbg(&isci_request->isci_host->pdev->dev, | ||
164 | "%s: isci_request = %p, state = 0x%x\n", | ||
165 | __func__, | ||
166 | isci_request, | ||
167 | status); | ||
168 | |||
169 | BUG_ON(isci_request == NULL); | ||
170 | |||
171 | spin_lock_irqsave(&isci_request->state_lock, flags); | ||
172 | old_state = isci_request->status; | ||
173 | isci_request->status = status; | ||
174 | spin_unlock_irqrestore(&isci_request->state_lock, flags); | ||
175 | |||
176 | return old_state; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * isci_request_change_started_to_newstate() - This function sets the status of | ||
181 | * the request object. | ||
182 | * @request: This parameter points to the isci_request object | ||
183 | * @status: This Parameter is the new status of the object | ||
184 | * | ||
185 | * state previous to any change. | ||
186 | */ | ||
187 | static inline enum isci_request_status isci_request_change_started_to_newstate( | ||
188 | struct isci_request *isci_request, | ||
189 | struct completion *completion_ptr, | ||
190 | enum isci_request_status newstate) | ||
191 | { | ||
192 | enum isci_request_status old_state; | ||
193 | unsigned long flags; | ||
194 | |||
195 | BUG_ON(isci_request == NULL); | ||
196 | |||
197 | spin_lock_irqsave(&isci_request->state_lock, flags); | ||
198 | |||
199 | old_state = isci_request->status; | ||
200 | |||
201 | if (old_state == started) { | ||
202 | BUG_ON(isci_request->io_request_completion != NULL); | ||
203 | |||
204 | isci_request->io_request_completion = completion_ptr; | ||
205 | isci_request->status = newstate; | ||
206 | } | ||
207 | spin_unlock_irqrestore(&isci_request->state_lock, flags); | ||
208 | |||
209 | dev_dbg(&isci_request->isci_host->pdev->dev, | ||
210 | "%s: isci_request = %p, old_state = 0x%x\n", | ||
211 | __func__, | ||
212 | isci_request, | ||
213 | old_state); | ||
214 | |||
215 | return old_state; | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * isci_request_change_started_to_aborted() - This function sets the status of | ||
220 | * the request object. | ||
221 | * @request: This parameter points to the isci_request object | ||
222 | * @completion_ptr: This parameter is saved as the kernel completion structure | ||
223 | * signalled when the old request completes. | ||
224 | * | ||
225 | * state previous to any change. | ||
226 | */ | ||
227 | static inline enum isci_request_status isci_request_change_started_to_aborted( | ||
228 | struct isci_request *isci_request, | ||
229 | struct completion *completion_ptr) | ||
230 | { | ||
231 | return isci_request_change_started_to_newstate( | ||
232 | isci_request, completion_ptr, aborted | ||
233 | ); | ||
234 | } | ||
235 | /** | ||
236 | * isci_request_free() - This function frees the request object. | ||
237 | * @isci_host: This parameter specifies the ISCI host object | ||
238 | * @isci_request: This parameter points to the isci_request object | ||
239 | * | ||
240 | */ | ||
241 | static inline void isci_request_free( | ||
242 | struct isci_host *isci_host, | ||
243 | struct isci_request *isci_request) | ||
244 | { | ||
245 | BUG_ON(isci_request == NULL); | ||
246 | |||
247 | /* release the dma memory if we fail. */ | ||
248 | dma_pool_free(isci_host->dma_pool, isci_request, | ||
249 | isci_request->request_daddr); | ||
250 | } | ||
251 | |||
252 | |||
253 | /* #define ISCI_REQUEST_VALIDATE_ACCESS | ||
254 | */ | ||
255 | |||
256 | #ifdef ISCI_REQUEST_VALIDATE_ACCESS | ||
257 | |||
258 | static inline | ||
259 | struct sas_task *isci_request_access_task(struct isci_request *isci_request) | ||
260 | { | ||
261 | BUG_ON(isci_request->ttype != io_task); | ||
262 | return isci_request->ttype_ptr.io_task_ptr; | ||
263 | } | ||
264 | |||
265 | static inline | ||
266 | struct isci_tmf *isci_request_access_tmf(struct isci_request *isci_request) | ||
267 | { | ||
268 | BUG_ON(isci_request->ttype != tmf_task); | ||
269 | return isci_request->ttype_ptr.tmf_task_ptr; | ||
270 | } | ||
271 | |||
272 | #else /* not ISCI_REQUEST_VALIDATE_ACCESS */ | ||
273 | |||
274 | #define isci_request_access_task(RequestPtr) \ | ||
275 | ((RequestPtr)->ttype_ptr.io_task_ptr) | ||
276 | |||
277 | #define isci_request_access_tmf(RequestPtr) \ | ||
278 | ((RequestPtr)->ttype_ptr.tmf_task_ptr) | ||
279 | |||
280 | #endif /* not ISCI_REQUEST_VALIDATE_ACCESS */ | ||
281 | |||
282 | |||
283 | int isci_request_alloc_tmf( | ||
284 | struct isci_host *isci_host, | ||
285 | struct isci_tmf *isci_tmf, | ||
286 | struct isci_request **isci_request, | ||
287 | struct isci_remote_device *isci_device, | ||
288 | gfp_t gfp_flags); | ||
289 | |||
290 | |||
291 | int isci_request_execute( | ||
292 | struct isci_host *isci_host, | ||
293 | struct sas_task *task, | ||
294 | struct isci_request **request, | ||
295 | gfp_t gfp_flags); | ||
296 | |||
297 | /** | ||
298 | * isci_request_unmap_sgl() - This function unmaps the DMA address of a given | ||
299 | * sgl | ||
300 | * @request: This parameter points to the isci_request object | ||
301 | * @*pdev: This Parameter is the pci_device struct for the controller | ||
302 | * | ||
303 | */ | ||
304 | static inline void isci_request_unmap_sgl( | ||
305 | struct isci_request *request, | ||
306 | struct pci_dev *pdev) | ||
307 | { | ||
308 | struct sas_task *task = isci_request_access_task(request); | ||
309 | |||
310 | dev_dbg(&request->isci_host->pdev->dev, | ||
311 | "%s: request = %p, task = %p,\n" | ||
312 | "task->data_dir = %d, is_sata = %d\n ", | ||
313 | __func__, | ||
314 | request, | ||
315 | task, | ||
316 | task->data_dir, | ||
317 | sas_protocol_ata(task->task_proto)); | ||
318 | |||
319 | if ((task->data_dir != PCI_DMA_NONE) && | ||
320 | !sas_protocol_ata(task->task_proto)) { | ||
321 | if (task->num_scatter == 0) | ||
322 | /* 0 indicates a single dma address */ | ||
323 | dma_unmap_single( | ||
324 | &pdev->dev, | ||
325 | request->zero_scatter_daddr, | ||
326 | task->total_xfer_len, | ||
327 | task->data_dir | ||
328 | ); | ||
329 | |||
330 | else /* unmap the sgl dma addresses */ | ||
331 | dma_unmap_sg( | ||
332 | &pdev->dev, | ||
333 | task->scatter, | ||
334 | request->num_sg_entries, | ||
335 | task->data_dir | ||
336 | ); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | |||
341 | void isci_request_io_request_complete( | ||
342 | struct isci_host *isci_host, | ||
343 | struct isci_request *request, | ||
344 | enum sci_io_status completion_status); | ||
345 | |||
346 | u32 isci_request_io_request_get_transfer_length( | ||
347 | struct isci_request *request); | ||
348 | |||
349 | SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction( | ||
350 | struct isci_request *request); | ||
351 | |||
352 | /** | ||
353 | * isci_request_io_request_get_next_sge() - This function is called by the sci | ||
354 | * core to retrieve the next sge for a given request. | ||
355 | * @request: This parameter is the isci_request object. | ||
356 | * @current_sge_address: This parameter is the last sge retrieved by the sci | ||
357 | * core for this request. | ||
358 | * | ||
359 | * pointer to the next sge for specified request. | ||
360 | */ | ||
361 | static inline void *isci_request_io_request_get_next_sge( | ||
362 | struct isci_request *request, | ||
363 | void *current_sge_address) | ||
364 | { | ||
365 | struct sas_task *task = isci_request_access_task(request); | ||
366 | void *ret = NULL; | ||
367 | |||
368 | dev_dbg(&request->isci_host->pdev->dev, | ||
369 | "%s: request = %p, " | ||
370 | "current_sge_address = %p, " | ||
371 | "num_scatter = %d\n", | ||
372 | __func__, | ||
373 | request, | ||
374 | current_sge_address, | ||
375 | task->num_scatter); | ||
376 | |||
377 | if (!current_sge_address) /* First time through.. */ | ||
378 | ret = task->scatter; /* always task->scatter */ | ||
379 | else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */ | ||
380 | ret = NULL; /* there is only one element. */ | ||
381 | else | ||
382 | ret = sg_next(current_sge_address); /* sg_next returns NULL | ||
383 | * for the last element | ||
384 | */ | ||
385 | |||
386 | dev_dbg(&request->isci_host->pdev->dev, | ||
387 | "%s: next sge address = %p\n", | ||
388 | __func__, | ||
389 | ret); | ||
390 | |||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | dma_addr_t isci_request_sge_get_address_field( | ||
395 | struct isci_request *request, | ||
396 | void *sge_address); | ||
397 | |||
398 | u32 isci_request_sge_get_length_field( | ||
399 | struct isci_request *request, | ||
400 | void *sge_address); | ||
401 | |||
402 | void *isci_request_ssp_io_request_get_cdb_address( | ||
403 | struct isci_request *request); | ||
404 | |||
405 | u32 isci_request_ssp_io_request_get_cdb_length( | ||
406 | struct isci_request *request); | ||
407 | |||
408 | u32 isci_request_ssp_io_request_get_lun( | ||
409 | struct isci_request *request); | ||
410 | |||
411 | u32 isci_request_ssp_io_request_get_task_attribute( | ||
412 | struct isci_request *request); | ||
413 | |||
414 | u32 isci_request_ssp_io_request_get_command_priority( | ||
415 | struct isci_request *request); | ||
416 | |||
417 | |||
418 | |||
419 | |||
420 | |||
421 | void isci_terminate_pending_requests( | ||
422 | struct isci_host *isci_host, | ||
423 | struct isci_remote_device *isci_device, | ||
424 | enum isci_request_status new_request_state); | ||
425 | |||
426 | |||
427 | |||
428 | |||
429 | #endif /* !defined(_ISCI_REQUEST_H_) */ | ||
diff --git a/drivers/scsi/isci/sata.c b/drivers/scsi/isci/sata.c new file mode 100644 index 000000000000..19b0eea93ca7 --- /dev/null +++ b/drivers/scsi/isci/sata.c | |||
@@ -0,0 +1,356 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "isci.h" | ||
57 | #include "scic_remote_device.h" | ||
58 | #include "scic_sds_remote_device.h" | ||
59 | #include "scic_io_request.h" | ||
60 | #include "scic_task_request.h" | ||
61 | #include "task.h" | ||
62 | #include "request.h" | ||
63 | #include "sata.h" | ||
64 | #include "intel_sat.h" | ||
65 | #include "intel_ata.h" | ||
66 | |||
67 | static u8 isci_sata_get_management_task_protocol(struct isci_tmf *tmf); | ||
68 | |||
69 | |||
70 | /** | ||
71 | * isci_sata_task_to_fis_copy() - This function gets the host_to_dev_fis from | ||
72 | * the core and copies the fis from the task into it. | ||
73 | * @task: This parameter is a pointer to the task struct from libsas. | ||
74 | * | ||
75 | * pointer to the host_to_dev_fis from the core request object. | ||
76 | */ | ||
77 | struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task) | ||
78 | { | ||
79 | struct isci_request *request = task->lldd_task; | ||
80 | struct host_to_dev_fis *register_fis = | ||
81 | scic_stp_io_request_get_h2d_reg_address( | ||
82 | request->sci_request_handle | ||
83 | ); | ||
84 | |||
85 | memcpy( | ||
86 | (u8 *)register_fis, | ||
87 | (u8 *)&task->ata_task.fis, | ||
88 | sizeof(struct host_to_dev_fis) | ||
89 | ); | ||
90 | |||
91 | if (!task->ata_task.device_control_reg_update) | ||
92 | register_fis->flags |= 0x80; | ||
93 | |||
94 | register_fis->flags &= 0xF0; | ||
95 | |||
96 | return register_fis; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * isci_sata_is_task_ncq() - This function determines if the given stp task is | ||
101 | * a ncq request. | ||
102 | * @task: This parameter is a pointer to the task struct from libsas. | ||
103 | * | ||
104 | * true if the task is ncq | ||
105 | */ | ||
106 | bool isci_sata_is_task_ncq(struct sas_task *task) | ||
107 | { | ||
108 | struct ata_queued_cmd *qc = task->uldd_task; | ||
109 | |||
110 | bool ret = (qc && | ||
111 | (qc->tf.command == ATA_CMD_FPDMA_WRITE || | ||
112 | qc->tf.command == ATA_CMD_FPDMA_READ)); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * isci_sata_set_ncq_tag() - This function sets the ncq tag field in the | ||
119 | * host_to_dev_fis equal to the tag in the queue command in the task. | ||
120 | * @task: This parameter is a pointer to the task struct from libsas. | ||
121 | * @register_fis: This parameter is a pointer to the host_to_dev_fis from the | ||
122 | * core request object. | ||
123 | * | ||
124 | */ | ||
125 | void isci_sata_set_ncq_tag( | ||
126 | struct host_to_dev_fis *register_fis, | ||
127 | struct sas_task *task) | ||
128 | { | ||
129 | struct ata_queued_cmd *qc = task->uldd_task; | ||
130 | struct isci_request *request = task->lldd_task; | ||
131 | |||
132 | register_fis->sector_count = qc->tag << 3; | ||
133 | scic_stp_io_request_set_ncq_tag(request->sci_request_handle, qc->tag); | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * isci_request_process_stp_response() - This function sets the status and | ||
138 | * response, in the task struct, from the request object for the upper layer | ||
139 | * driver. | ||
140 | * @sas_task: This parameter is the task struct from the upper layer driver. | ||
141 | * @response_buffer: This parameter points to the response of the completed | ||
142 | * request. | ||
143 | * | ||
144 | * none. | ||
145 | */ | ||
146 | void isci_request_process_stp_response( | ||
147 | struct sas_task *task, | ||
148 | void *response_buffer) | ||
149 | { | ||
150 | struct sata_fis_reg_d2h *d2h_reg_fis = (struct sata_fis_reg_d2h *)response_buffer; | ||
151 | struct task_status_struct *ts = &task->task_status; | ||
152 | struct ata_task_resp *resp = (void *)&ts->buf[0]; | ||
153 | |||
154 | resp->frame_len = le16_to_cpu(*(__le16 *)(response_buffer + 6)); | ||
155 | memcpy(&resp->ending_fis[0], response_buffer + 16, 24); | ||
156 | ts->buf_valid_size = sizeof(*resp); | ||
157 | |||
158 | /** | ||
159 | * If the device fault bit is set in the status register, then | ||
160 | * set the sense data and return. | ||
161 | */ | ||
162 | if (d2h_reg_fis->status & ATA_STATUS_REG_DEVICE_FAULT_BIT) | ||
163 | ts->stat = SAS_PROTO_RESPONSE; | ||
164 | else | ||
165 | ts->stat = SAM_STAT_GOOD; | ||
166 | |||
167 | ts->resp = SAS_TASK_COMPLETE; | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * isci_sata_get_sat_protocol() - retrieve the sat protocol for the request | ||
172 | * @isci_request: ata request | ||
173 | * | ||
174 | * Note: temporary implementation until expert mode removes the callback | ||
175 | * | ||
176 | */ | ||
177 | u8 isci_sata_get_sat_protocol(struct isci_request *isci_request) | ||
178 | { | ||
179 | struct sas_task *task; | ||
180 | struct domain_device *dev; | ||
181 | |||
182 | dev_dbg(&isci_request->isci_host->pdev->dev, | ||
183 | "%s: isci_request = %p, ttype = %d\n", | ||
184 | __func__, isci_request, isci_request->ttype); | ||
185 | |||
186 | if (tmf_task == isci_request->ttype) { | ||
187 | struct isci_tmf *tmf = isci_request_access_tmf(isci_request); | ||
188 | |||
189 | return isci_sata_get_management_task_protocol(tmf); | ||
190 | } | ||
191 | |||
192 | task = isci_request_access_task(isci_request); | ||
193 | dev = task->dev; | ||
194 | |||
195 | if (!sas_protocol_ata(task->task_proto)) { | ||
196 | WARN(1, "unhandled task protocol\n"); | ||
197 | return SAT_PROTOCOL_NON_DATA; | ||
198 | } | ||
199 | |||
200 | if (task->data_dir == DMA_NONE) | ||
201 | return SAT_PROTOCOL_NON_DATA; | ||
202 | |||
203 | /* the "_IN" protocol types are equivalent to their "_OUT" | ||
204 | * analogs as far as the core is concerned | ||
205 | */ | ||
206 | if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { | ||
207 | if (task->ata_task.dma_xfer) | ||
208 | return SAT_PROTOCOL_PACKET_DMA_DATA_IN; | ||
209 | else | ||
210 | return SAT_PROTOCOL_PACKET_PIO_DATA_IN; | ||
211 | } | ||
212 | |||
213 | if (task->ata_task.use_ncq) | ||
214 | return SAT_PROTOCOL_FPDMA; | ||
215 | |||
216 | if (task->ata_task.dma_xfer) | ||
217 | return SAT_PROTOCOL_UDMA_DATA_IN; | ||
218 | else | ||
219 | return SAT_PROTOCOL_PIO_DATA_IN; | ||
220 | } | ||
221 | |||
222 | static u8 isci_sata_get_management_task_protocol( | ||
223 | struct isci_tmf *tmf) | ||
224 | { | ||
225 | u8 ret = 0; | ||
226 | |||
227 | pr_warn("tmf = %p, func = %d\n", tmf, tmf->tmf_code); | ||
228 | |||
229 | if ((tmf->tmf_code == isci_tmf_sata_srst_high) || | ||
230 | (tmf->tmf_code == isci_tmf_sata_srst_low)) { | ||
231 | pr_warn("%s: tmf->tmf_code == TMF_LU_RESET\n", __func__); | ||
232 | ret = SAT_PROTOCOL_SOFT_RESET; | ||
233 | } | ||
234 | |||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | enum sci_status isci_sata_management_task_request_build( | ||
239 | struct isci_request *isci_request) | ||
240 | { | ||
241 | struct isci_tmf *isci_tmf; | ||
242 | enum sci_status status; | ||
243 | |||
244 | if (tmf_task != isci_request->ttype) | ||
245 | return SCI_FAILURE; | ||
246 | |||
247 | isci_tmf = isci_request_access_tmf(isci_request); | ||
248 | |||
249 | switch (isci_tmf->tmf_code) { | ||
250 | |||
251 | case isci_tmf_sata_srst_high: | ||
252 | case isci_tmf_sata_srst_low: | ||
253 | { | ||
254 | struct host_to_dev_fis *register_fis = | ||
255 | scic_stp_io_request_get_h2d_reg_address( | ||
256 | isci_request->sci_request_handle | ||
257 | ); | ||
258 | |||
259 | memset(register_fis, 0, sizeof(*register_fis)); | ||
260 | |||
261 | register_fis->fis_type = 0x27; | ||
262 | register_fis->flags &= ~0x80; | ||
263 | register_fis->flags &= 0xF0; | ||
264 | if (isci_tmf->tmf_code == isci_tmf_sata_srst_high) | ||
265 | register_fis->control |= ATA_SRST; | ||
266 | else | ||
267 | register_fis->control &= ~ATA_SRST; | ||
268 | break; | ||
269 | } | ||
270 | /* other management commnd go here... */ | ||
271 | default: | ||
272 | return SCI_FAILURE; | ||
273 | } | ||
274 | |||
275 | /* core builds the protocol specific request | ||
276 | * based on the h2d fis. | ||
277 | */ | ||
278 | status = scic_task_request_construct_sata( | ||
279 | isci_request->sci_request_handle | ||
280 | ); | ||
281 | |||
282 | return status; | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * isci_task_send_lu_reset_sata() - This function is called by of the SAS | ||
287 | * Domain Template functions. This is one of the Task Management functoins | ||
288 | * called by libsas, to reset the given SAS lun. Note the assumption that | ||
289 | * while this call is executing, no I/O will be sent by the host to the | ||
290 | * device. | ||
291 | * @lun: This parameter specifies the lun to be reset. | ||
292 | * | ||
293 | * status, zero indicates success. | ||
294 | */ | ||
295 | int isci_task_send_lu_reset_sata( | ||
296 | struct isci_host *isci_host, | ||
297 | struct isci_remote_device *isci_device, | ||
298 | u8 *lun) | ||
299 | { | ||
300 | struct isci_tmf tmf; | ||
301 | int ret = TMF_RESP_FUNC_FAILED; | ||
302 | unsigned long flags; | ||
303 | |||
304 | /* Send the initial SRST to the target */ | ||
305 | #define ISCI_SRST_TIMEOUT_MS 20 /* 20 ms timeout. */ | ||
306 | isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_high, | ||
307 | NULL, NULL | ||
308 | ); | ||
309 | |||
310 | ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS); | ||
311 | |||
312 | if (ret != TMF_RESP_FUNC_COMPLETE) { | ||
313 | dev_warn(&isci_host->pdev->dev, | ||
314 | "%s: Assert SRST failed (%p) = %x", | ||
315 | __func__, | ||
316 | isci_device, | ||
317 | ret); | ||
318 | |||
319 | /* Return the failure so that the LUN reset is escalated | ||
320 | * to a target reset. | ||
321 | */ | ||
322 | goto out; | ||
323 | } | ||
324 | |||
325 | /* Leave SRST high for a bit. */ | ||
326 | #define ISCI_SRST_ASSERT_DELAY 100 /* usecs */ | ||
327 | scic_cb_stall_execution(ISCI_SRST_ASSERT_DELAY); | ||
328 | |||
329 | /* Deassert SRST. */ | ||
330 | isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low, | ||
331 | NULL, NULL | ||
332 | ); | ||
333 | ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS); | ||
334 | |||
335 | if (ret == TMF_RESP_FUNC_COMPLETE) | ||
336 | dev_dbg(&isci_host->pdev->dev, | ||
337 | "%s: SATA LUN reset passed (%p)\n", | ||
338 | __func__, | ||
339 | isci_device); | ||
340 | else | ||
341 | dev_warn(&isci_host->pdev->dev, | ||
342 | "%s: Deassert SRST failed (%p)=%x\n", | ||
343 | __func__, | ||
344 | isci_device, | ||
345 | ret); | ||
346 | |||
347 | out: | ||
348 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
349 | |||
350 | /* Resume the device. */ | ||
351 | scic_sds_remote_device_resume(isci_device->sci_device_handle); | ||
352 | |||
353 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
354 | |||
355 | return ret; | ||
356 | } | ||
diff --git a/drivers/scsi/isci/sata.h b/drivers/scsi/isci/sata.h new file mode 100644 index 000000000000..b6ba25b52d2c --- /dev/null +++ b/drivers/scsi/isci/sata.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "intel_sat.h" | ||
57 | |||
58 | |||
59 | |||
60 | struct host_to_dev_fis *isci_sata_task_to_fis_copy( | ||
61 | struct sas_task *task); | ||
62 | |||
63 | bool isci_sata_is_task_ncq( | ||
64 | struct sas_task *task); | ||
65 | |||
66 | void isci_sata_set_ncq_tag( | ||
67 | struct host_to_dev_fis *register_fis, | ||
68 | struct sas_task *task); | ||
69 | |||
70 | void isci_request_process_stp_response( | ||
71 | struct sas_task *task, | ||
72 | void *response_buffer); | ||
73 | |||
74 | u8 isci_sata_get_sat_protocol( | ||
75 | struct isci_request *isci_request); | ||
76 | |||
77 | enum sci_status isci_sata_management_task_request_build( | ||
78 | struct isci_request *isci_request); | ||
79 | |||
80 | int isci_task_send_lu_reset_sata( | ||
81 | struct isci_host *isci_host, | ||
82 | struct isci_remote_device *isci_device, | ||
83 | u8 *lun); | ||
diff --git a/drivers/scsi/isci/sci_environment.h b/drivers/scsi/isci/sci_environment.h new file mode 100644 index 000000000000..e1020ee6c38e --- /dev/null +++ b/drivers/scsi/isci/sci_environment.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #ifndef _SCI_ENVIRONMENT_H_ | ||
57 | #define _SCI_ENVIRONMENT_H_ | ||
58 | |||
59 | #include "isci.h" | ||
60 | |||
61 | struct scic_sds_controller; | ||
62 | struct scic_sds_phy; | ||
63 | struct scic_sds_port; | ||
64 | struct scic_sds_remote_device; | ||
65 | |||
66 | static inline struct device *scic_to_dev(struct scic_sds_controller *scic) | ||
67 | { | ||
68 | struct isci_host *isci_host = sci_object_get_association(scic); | ||
69 | |||
70 | return &isci_host->pdev->dev; | ||
71 | } | ||
72 | |||
73 | static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy) | ||
74 | { | ||
75 | struct isci_phy *iphy = sci_object_get_association(sci_phy); | ||
76 | |||
77 | if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host) | ||
78 | return NULL; | ||
79 | |||
80 | return &iphy->isci_port->isci_host->pdev->dev; | ||
81 | } | ||
82 | |||
83 | static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port) | ||
84 | { | ||
85 | struct isci_port *iport = sci_object_get_association(sci_port); | ||
86 | |||
87 | if (!iport || !iport->isci_host) | ||
88 | return NULL; | ||
89 | |||
90 | return &iport->isci_host->pdev->dev; | ||
91 | } | ||
92 | |||
93 | static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev) | ||
94 | { | ||
95 | struct isci_remote_device *idev = sci_object_get_association(sci_dev); | ||
96 | |||
97 | if (!idev || !idev->isci_port || !idev->isci_port->isci_host) | ||
98 | return NULL; | ||
99 | |||
100 | return &idev->isci_port->isci_host->pdev->dev; | ||
101 | } | ||
102 | |||
103 | enum { | ||
104 | ISCI_SI_REVA0, | ||
105 | ISCI_SI_REVA2, | ||
106 | ISCI_SI_REVB0, | ||
107 | }; | ||
108 | |||
109 | extern int isci_si_rev; | ||
110 | |||
111 | |||
112 | #endif | ||
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c new file mode 100644 index 000000000000..5e6f55863407 --- /dev/null +++ b/drivers/scsi/isci/task.c | |||
@@ -0,0 +1,1691 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include <linux/completion.h> | ||
57 | #include "scic_task_request.h" | ||
58 | #include "scic_remote_device.h" | ||
59 | #include "scic_io_request.h" | ||
60 | #include "scic_sds_remote_device.h" | ||
61 | #include "scic_sds_remote_node_context.h" | ||
62 | #include "isci.h" | ||
63 | #include "request.h" | ||
64 | #include "sata.h" | ||
65 | #include "task.h" | ||
66 | |||
67 | |||
68 | /** | ||
69 | * isci_task_execute_task() - This function is one of the SAS Domain Template | ||
70 | * functions. This function is called by libsas to send a task down to | ||
71 | * hardware. | ||
72 | * @task: This parameter specifies the SAS task to send. | ||
73 | * @num: This parameter specifies the number of tasks to queue. | ||
74 | * @gfp_flags: This parameter specifies the context of this call. | ||
75 | * | ||
76 | * status, zero indicates success. | ||
77 | */ | ||
78 | int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags) | ||
79 | { | ||
80 | struct isci_host *isci_host; | ||
81 | struct isci_request *request = NULL; | ||
82 | struct isci_remote_device *device; | ||
83 | unsigned long flags; | ||
84 | unsigned long quiesce_flags = 0; | ||
85 | int ret; | ||
86 | enum sci_status status; | ||
87 | |||
88 | |||
89 | dev_dbg(task->dev->port->ha->dev, "%s: num=%d\n", __func__, num); | ||
90 | |||
91 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | ||
92 | |||
93 | isci_task_complete_for_upper_layer( | ||
94 | task, | ||
95 | SAS_TASK_UNDELIVERED, | ||
96 | SAM_STAT_TASK_ABORTED, | ||
97 | isci_perform_normal_io_completion | ||
98 | ); | ||
99 | |||
100 | return 0; /* The I/O was accepted (and failed). */ | ||
101 | } | ||
102 | if ((task->dev == NULL) || (task->dev->port == NULL)) { | ||
103 | |||
104 | /* Indicate SAS_TASK_UNDELIVERED, so that the scsi midlayer | ||
105 | * removes the target. | ||
106 | */ | ||
107 | isci_task_complete_for_upper_layer( | ||
108 | task, | ||
109 | SAS_TASK_UNDELIVERED, | ||
110 | SAS_DEVICE_UNKNOWN, | ||
111 | isci_perform_normal_io_completion | ||
112 | ); | ||
113 | return 0; /* The I/O was accepted (and failed). */ | ||
114 | } | ||
115 | isci_host = isci_host_from_sas_ha(task->dev->port->ha); | ||
116 | |||
117 | /* Check if we have room for more tasks */ | ||
118 | ret = isci_host_can_queue(isci_host, num); | ||
119 | |||
120 | if (ret) { | ||
121 | dev_warn(task->dev->port->ha->dev, "%s: queue full\n", __func__); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | do { | ||
126 | dev_dbg(task->dev->port->ha->dev, | ||
127 | "task = %p, num = %d; dev = %p; cmd = %p\n", | ||
128 | task, num, task->dev, task->uldd_task); | ||
129 | |||
130 | if ((task->dev == NULL) || (task->dev->port == NULL)) { | ||
131 | dev_warn(task->dev->port->ha->dev, | ||
132 | "%s: task %p's port or dev == NULL!\n", | ||
133 | __func__, task); | ||
134 | |||
135 | /* Indicate SAS_TASK_UNDELIVERED, so that the scsi | ||
136 | * midlayer removes the target. | ||
137 | */ | ||
138 | isci_task_complete_for_upper_layer( | ||
139 | task, | ||
140 | SAS_TASK_UNDELIVERED, | ||
141 | SAS_DEVICE_UNKNOWN, | ||
142 | isci_perform_normal_io_completion | ||
143 | ); | ||
144 | /* We don't have a valid host reference, so we | ||
145 | * can't control the host queueing condition. | ||
146 | */ | ||
147 | continue; | ||
148 | } | ||
149 | |||
150 | device = isci_dev_from_domain_dev(task->dev); | ||
151 | |||
152 | isci_host = isci_host_from_sas_ha(task->dev->port->ha); | ||
153 | |||
154 | /* check if the controller hasn't started or if the device | ||
155 | * is ready but not accepting IO. | ||
156 | */ | ||
157 | if (device) { | ||
158 | |||
159 | spin_lock_irqsave(&device->host_quiesce_lock, | ||
160 | quiesce_flags); | ||
161 | } | ||
162 | /* From this point onward, any process that needs to guarantee | ||
163 | * that there is no kernel I/O being started will have to wait | ||
164 | * for the quiesce spinlock. | ||
165 | */ | ||
166 | |||
167 | if (isci_host_get_state(isci_host) == isci_starting || | ||
168 | (device && ((isci_remote_device_get_state(device) == isci_ready) || | ||
169 | (isci_remote_device_get_state(device) == isci_host_quiesce)))) { | ||
170 | |||
171 | /* Forces a retry from scsi mid layer. */ | ||
172 | dev_warn(task->dev->port->ha->dev, | ||
173 | "%s: task %p: isci_host->status = %d, " | ||
174 | "device = %p\n", | ||
175 | __func__, | ||
176 | task, | ||
177 | isci_host_get_state(isci_host), | ||
178 | device); | ||
179 | |||
180 | if (device) | ||
181 | dev_dbg(task->dev->port->ha->dev, | ||
182 | "%s: device->status = 0x%x\n", | ||
183 | __func__, | ||
184 | isci_remote_device_get_state(device)); | ||
185 | |||
186 | /* Indicate QUEUE_FULL so that the scsi midlayer | ||
187 | * retries. | ||
188 | */ | ||
189 | isci_task_complete_for_upper_layer( | ||
190 | task, | ||
191 | SAS_TASK_COMPLETE, | ||
192 | SAS_QUEUE_FULL, | ||
193 | isci_perform_normal_io_completion | ||
194 | ); | ||
195 | isci_host_can_dequeue(isci_host, 1); | ||
196 | } | ||
197 | /* the device is going down... */ | ||
198 | else if (!device || (isci_ready_for_io != isci_remote_device_get_state(device))) { | ||
199 | |||
200 | dev_dbg(task->dev->port->ha->dev, | ||
201 | "%s: task %p: isci_host->status = %d, " | ||
202 | "device = %p\n", | ||
203 | __func__, | ||
204 | task, | ||
205 | isci_host_get_state(isci_host), | ||
206 | device); | ||
207 | |||
208 | if (device) | ||
209 | dev_dbg(task->dev->port->ha->dev, | ||
210 | "%s: device->status = 0x%x\n", | ||
211 | __func__, | ||
212 | isci_remote_device_get_state(device)); | ||
213 | |||
214 | /* Indicate SAS_TASK_UNDELIVERED, so that the scsi | ||
215 | * midlayer removes the target. | ||
216 | */ | ||
217 | isci_task_complete_for_upper_layer( | ||
218 | task, | ||
219 | SAS_TASK_UNDELIVERED, | ||
220 | SAS_DEVICE_UNKNOWN, | ||
221 | isci_perform_normal_io_completion | ||
222 | ); | ||
223 | isci_host_can_dequeue(isci_host, 1); | ||
224 | |||
225 | } else { | ||
226 | /* build and send the request. */ | ||
227 | status = isci_request_execute(isci_host, task, &request, | ||
228 | gfp_flags); | ||
229 | |||
230 | if (status == SCI_SUCCESS) { | ||
231 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
232 | task->task_state_flags |= SAS_TASK_AT_INITIATOR; | ||
233 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
234 | } else { | ||
235 | /* Indicate QUEUE_FULL so that the scsi | ||
236 | * midlayer retries. if the request | ||
237 | * failed for remote device reasons, | ||
238 | * it gets returned as | ||
239 | * SAS_TASK_UNDELIVERED next time | ||
240 | * through. | ||
241 | */ | ||
242 | isci_task_complete_for_upper_layer( | ||
243 | task, | ||
244 | SAS_TASK_COMPLETE, | ||
245 | SAS_QUEUE_FULL, | ||
246 | isci_perform_normal_io_completion | ||
247 | ); | ||
248 | isci_host_can_dequeue(isci_host, 1); | ||
249 | } | ||
250 | } | ||
251 | if (device) { | ||
252 | spin_unlock_irqrestore(&device->host_quiesce_lock, | ||
253 | quiesce_flags | ||
254 | ); | ||
255 | } | ||
256 | task = list_entry(task->list.next, struct sas_task, list); | ||
257 | } while (--num > 0); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | |||
262 | |||
263 | /** | ||
264 | * isci_task_request_build() - This function builds the task request object. | ||
265 | * @isci_host: This parameter specifies the ISCI host object | ||
266 | * @request: This parameter points to the isci_request object allocated in the | ||
267 | * request construct function. | ||
268 | * @tmf: This parameter is the task management struct to be built | ||
269 | * | ||
270 | * SCI_SUCCESS on successfull completion, or specific failure code. | ||
271 | */ | ||
272 | static enum sci_status isci_task_request_build( | ||
273 | struct isci_host *isci_host, | ||
274 | struct isci_request **isci_request, | ||
275 | struct isci_tmf *isci_tmf) | ||
276 | { | ||
277 | struct scic_sds_remote_device *sci_device; | ||
278 | enum sci_status status = SCI_FAILURE; | ||
279 | struct isci_request *request; | ||
280 | struct isci_remote_device *isci_device; | ||
281 | /* struct sci_sas_identify_address_frame_protocols dev_protocols; */ | ||
282 | struct smp_discover_response_protocols dev_protocols; | ||
283 | |||
284 | |||
285 | dev_dbg(&isci_host->pdev->dev, | ||
286 | "%s: isci_tmf = %p\n", __func__, isci_tmf); | ||
287 | |||
288 | isci_device = isci_tmf->device; | ||
289 | sci_device = isci_device->sci_device_handle; | ||
290 | |||
291 | /* do common allocation and init of request object. */ | ||
292 | status = isci_request_alloc_tmf( | ||
293 | isci_host, | ||
294 | isci_tmf, | ||
295 | &request, | ||
296 | isci_device, | ||
297 | GFP_ATOMIC | ||
298 | ); | ||
299 | |||
300 | if (status != SCI_SUCCESS) | ||
301 | goto out; | ||
302 | |||
303 | /* let the core do it's construct. */ | ||
304 | status = scic_task_request_construct( | ||
305 | isci_host->core_controller, | ||
306 | sci_device, | ||
307 | SCI_CONTROLLER_INVALID_IO_TAG, | ||
308 | request, | ||
309 | request->sci_request_mem_ptr, | ||
310 | &request->sci_request_handle | ||
311 | ); | ||
312 | |||
313 | if (status != SCI_SUCCESS) { | ||
314 | dev_warn(&isci_host->pdev->dev, | ||
315 | "%s: scic_task_request_construct failed - " | ||
316 | "status = 0x%x\n", | ||
317 | __func__, | ||
318 | status); | ||
319 | goto errout; | ||
320 | } | ||
321 | |||
322 | sci_object_set_association( | ||
323 | request->sci_request_handle, | ||
324 | request | ||
325 | ); | ||
326 | |||
327 | scic_remote_device_get_protocols( | ||
328 | sci_device, | ||
329 | &dev_protocols | ||
330 | ); | ||
331 | |||
332 | /* let the core do it's protocol | ||
333 | * specific construction. | ||
334 | */ | ||
335 | if (dev_protocols.u.bits.attached_ssp_target) { | ||
336 | |||
337 | isci_tmf->proto = SAS_PROTOCOL_SSP; | ||
338 | status = scic_task_request_construct_ssp( | ||
339 | request->sci_request_handle | ||
340 | ); | ||
341 | if (status != SCI_SUCCESS) | ||
342 | goto errout; | ||
343 | } | ||
344 | |||
345 | if (dev_protocols.u.bits.attached_stp_target) { | ||
346 | |||
347 | isci_tmf->proto = SAS_PROTOCOL_SATA; | ||
348 | status = isci_sata_management_task_request_build(request); | ||
349 | |||
350 | if (status != SCI_SUCCESS) | ||
351 | goto errout; | ||
352 | } | ||
353 | |||
354 | goto out; | ||
355 | |||
356 | errout: | ||
357 | |||
358 | /* release the dma memory if we fail. */ | ||
359 | isci_request_free(isci_host, request); | ||
360 | request = NULL; | ||
361 | |||
362 | out: | ||
363 | *isci_request = request; | ||
364 | return status; | ||
365 | } | ||
366 | |||
367 | /** | ||
368 | * isci_tmf_timeout_cb() - This function is called as a kernel callback when | ||
369 | * the timeout period for the TMF has expired. | ||
370 | * | ||
371 | * | ||
372 | */ | ||
373 | static void isci_tmf_timeout_cb(void *tmf_request_arg) | ||
374 | { | ||
375 | struct isci_request *request = (struct isci_request *)tmf_request_arg; | ||
376 | struct isci_tmf *tmf = isci_request_access_tmf(request); | ||
377 | enum sci_status status; | ||
378 | |||
379 | BUG_ON(request->ttype != tmf_task); | ||
380 | |||
381 | /* This task management request has timed-out. Terminate the request | ||
382 | * so that the request eventually completes to the requestor in the | ||
383 | * request completion callback path. | ||
384 | */ | ||
385 | /* Note - the timer callback function itself has provided spinlock | ||
386 | * exclusion from the start and completion paths. No need to take | ||
387 | * the request->isci_host->scic_lock here. | ||
388 | */ | ||
389 | |||
390 | if (tmf->timeout_timer != NULL) { | ||
391 | /* Call the users callback, if any. */ | ||
392 | if (tmf->cb_state_func != NULL) | ||
393 | tmf->cb_state_func(isci_tmf_timed_out, tmf, | ||
394 | tmf->cb_data); | ||
395 | |||
396 | /* Terminate the TMF transmit request. */ | ||
397 | status = scic_controller_terminate_request( | ||
398 | request->isci_host->core_controller, | ||
399 | request->isci_device->sci_device_handle, | ||
400 | request->sci_request_handle | ||
401 | ); | ||
402 | |||
403 | dev_dbg(&request->isci_host->pdev->dev, | ||
404 | "%s: tmf_request = %p; tmf = %p; status = %d\n", | ||
405 | __func__, request, tmf, status); | ||
406 | } else | ||
407 | dev_dbg(&request->isci_host->pdev->dev, | ||
408 | "%s: timer already canceled! " | ||
409 | "tmf_request = %p; tmf = %p\n", | ||
410 | __func__, request, tmf); | ||
411 | |||
412 | /* No need to unlock since the caller to this callback is doing it for | ||
413 | * us. | ||
414 | * request->isci_host->scic_lock | ||
415 | */ | ||
416 | } | ||
417 | |||
418 | /** | ||
419 | * isci_task_execute_tmf() - This function builds and sends a task request, | ||
420 | * then waits for the completion. | ||
421 | * @isci_host: This parameter specifies the ISCI host object | ||
422 | * @tmf: This parameter is the pointer to the task management structure for | ||
423 | * this request. | ||
424 | * @timeout_ms: This parameter specifies the timeout period for the task | ||
425 | * management request. | ||
426 | * | ||
427 | * TMF_RESP_FUNC_COMPLETE on successful completion of the TMF (this includes | ||
428 | * error conditions reported in the IU status), or TMF_RESP_FUNC_FAILED. | ||
429 | */ | ||
430 | int isci_task_execute_tmf( | ||
431 | struct isci_host *isci_host, | ||
432 | struct isci_tmf *tmf, | ||
433 | unsigned long timeout_ms) | ||
434 | { | ||
435 | DECLARE_COMPLETION_ONSTACK(completion); | ||
436 | enum sci_status status = SCI_FAILURE; | ||
437 | struct scic_sds_remote_device *sci_device; | ||
438 | struct isci_remote_device *isci_device = tmf->device; | ||
439 | struct isci_request *request; | ||
440 | int ret = TMF_RESP_FUNC_FAILED; | ||
441 | unsigned long flags; | ||
442 | |||
443 | /* sanity check, return TMF_RESP_FUNC_FAILED | ||
444 | * if the device is not there and ready. | ||
445 | */ | ||
446 | if (!isci_device || | ||
447 | ((isci_ready_for_io != isci_remote_device_get_state(isci_device)) && | ||
448 | (isci_host_quiesce != isci_remote_device_get_state(isci_device)))) { | ||
449 | dev_dbg(&isci_host->pdev->dev, | ||
450 | "%s: isci_device = %p not ready (%d)\n", | ||
451 | __func__, | ||
452 | isci_device, | ||
453 | isci_remote_device_get_state(isci_device)); | ||
454 | return TMF_RESP_FUNC_FAILED; | ||
455 | } else | ||
456 | dev_dbg(&isci_host->pdev->dev, | ||
457 | "%s: isci_device = %p\n", | ||
458 | __func__, isci_device); | ||
459 | |||
460 | sci_device = isci_device->sci_device_handle; | ||
461 | |||
462 | /* Assign the pointer to the TMF's completion kernel wait structure. */ | ||
463 | tmf->complete = &completion; | ||
464 | |||
465 | isci_task_request_build( | ||
466 | isci_host, | ||
467 | &request, | ||
468 | tmf | ||
469 | ); | ||
470 | |||
471 | if (!request) { | ||
472 | dev_warn(&isci_host->pdev->dev, | ||
473 | "%s: isci_task_request_build failed\n", | ||
474 | __func__); | ||
475 | return TMF_RESP_FUNC_FAILED; | ||
476 | } | ||
477 | |||
478 | /* Allocate the TMF timeout timer. */ | ||
479 | tmf->timeout_timer = isci_timer_create( | ||
480 | &isci_host->timer_list_struct, | ||
481 | isci_host, | ||
482 | request, | ||
483 | isci_tmf_timeout_cb | ||
484 | ); | ||
485 | |||
486 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
487 | |||
488 | /* Start the timer. */ | ||
489 | if (tmf->timeout_timer) | ||
490 | isci_timer_start(tmf->timeout_timer, timeout_ms); | ||
491 | else | ||
492 | dev_warn(&isci_host->pdev->dev, | ||
493 | "%s: isci_timer_create failed!!!!\n", | ||
494 | __func__); | ||
495 | |||
496 | /* start the TMF io. */ | ||
497 | status = scic_controller_start_task( | ||
498 | isci_host->core_controller, | ||
499 | sci_device, | ||
500 | request->sci_request_handle, | ||
501 | SCI_CONTROLLER_INVALID_IO_TAG | ||
502 | ); | ||
503 | |||
504 | if (status != SCI_SUCCESS) { | ||
505 | dev_warn(&isci_host->pdev->dev, | ||
506 | "%s: start_io failed - status = 0x%x, request = %p\n", | ||
507 | __func__, | ||
508 | status, | ||
509 | request); | ||
510 | goto cleanup_request; | ||
511 | } | ||
512 | |||
513 | /* Call the users callback, if any. */ | ||
514 | if (tmf->cb_state_func != NULL) | ||
515 | tmf->cb_state_func(isci_tmf_started, tmf, tmf->cb_data); | ||
516 | |||
517 | /* Change the state of the TMF-bearing request to "started". */ | ||
518 | isci_request_change_state(request, started); | ||
519 | |||
520 | /* add the request to the remote device request list. */ | ||
521 | list_add(&request->dev_node, &isci_device->reqs_in_process); | ||
522 | |||
523 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
524 | |||
525 | /* Wait for the TMF to complete, or a timeout. */ | ||
526 | wait_for_completion(&completion); | ||
527 | |||
528 | isci_print_tmf(tmf); | ||
529 | |||
530 | if (tmf->status == SCI_SUCCESS) | ||
531 | ret = TMF_RESP_FUNC_COMPLETE; | ||
532 | else if (tmf->status == SCI_FAILURE_IO_RESPONSE_VALID) { | ||
533 | dev_dbg(&isci_host->pdev->dev, | ||
534 | "%s: tmf.status == " | ||
535 | "SCI_FAILURE_IO_RESPONSE_VALID\n", | ||
536 | __func__); | ||
537 | ret = TMF_RESP_FUNC_COMPLETE; | ||
538 | } | ||
539 | /* Else - leave the default "failed" status alone. */ | ||
540 | |||
541 | dev_dbg(&isci_host->pdev->dev, | ||
542 | "%s: completed request = %p\n", | ||
543 | __func__, | ||
544 | request); | ||
545 | |||
546 | if (request->io_request_completion != NULL) { | ||
547 | |||
548 | /* The fact that this is non-NULL for a TMF request | ||
549 | * means there is a thread waiting for this TMF to | ||
550 | * finish. | ||
551 | */ | ||
552 | complete(request->io_request_completion); | ||
553 | } | ||
554 | |||
555 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
556 | |||
557 | cleanup_request: | ||
558 | |||
559 | /* Clean up the timer if needed. */ | ||
560 | if (tmf->timeout_timer) { | ||
561 | isci_timer_stop(tmf->timeout_timer); | ||
562 | isci_timer_free(&isci_host->timer_list_struct, | ||
563 | tmf->timeout_timer); | ||
564 | tmf->timeout_timer = NULL; | ||
565 | } | ||
566 | |||
567 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
568 | |||
569 | isci_request_free(isci_host, request); | ||
570 | |||
571 | return ret; | ||
572 | } | ||
573 | |||
574 | void isci_task_build_tmf( | ||
575 | struct isci_tmf *tmf, | ||
576 | struct isci_remote_device *isci_device, | ||
577 | enum isci_tmf_function_codes code, | ||
578 | void (*tmf_sent_cb)(enum isci_tmf_cb_state, | ||
579 | struct isci_tmf *, | ||
580 | void *), | ||
581 | void *cb_data) | ||
582 | { | ||
583 | dev_dbg(&isci_device->isci_port->isci_host->pdev->dev, | ||
584 | "%s: isci_device = %p\n", __func__, isci_device); | ||
585 | |||
586 | memset(tmf, 0, sizeof(*tmf)); | ||
587 | |||
588 | tmf->device = isci_device; | ||
589 | tmf->tmf_code = code; | ||
590 | tmf->timeout_timer = NULL; | ||
591 | tmf->cb_state_func = tmf_sent_cb; | ||
592 | tmf->cb_data = cb_data; | ||
593 | } | ||
594 | |||
595 | static struct isci_request *isci_task_get_request_from_task( | ||
596 | struct sas_task *task, | ||
597 | struct isci_host **isci_host, | ||
598 | struct isci_remote_device **isci_device) | ||
599 | { | ||
600 | |||
601 | struct isci_request *request = NULL; | ||
602 | unsigned long flags; | ||
603 | |||
604 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
605 | |||
606 | request = task->lldd_task; | ||
607 | |||
608 | /* If task is already done, the request isn't valid */ | ||
609 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && | ||
610 | (task->task_state_flags & SAS_TASK_AT_INITIATOR) && | ||
611 | (request != NULL)) { | ||
612 | |||
613 | if (isci_host != NULL) | ||
614 | *isci_host = request->isci_host; | ||
615 | |||
616 | if (isci_device != NULL) | ||
617 | *isci_device = request->isci_device; | ||
618 | } | ||
619 | |||
620 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
621 | |||
622 | return request; | ||
623 | } | ||
624 | |||
625 | /** | ||
626 | * isci_task_validate_request_to_abort() - This function checks the given I/O | ||
627 | * against the "started" state. If the request is still "started", it's | ||
628 | * state is changed to aborted. NOTE: isci_host->scic_lock MUST BE HELD | ||
629 | * BEFORE CALLING THIS FUNCTION. | ||
630 | * @isci_request: This parameter specifies the request object to control. | ||
631 | * @isci_host: This parameter specifies the ISCI host object | ||
632 | * @isci_device: This is the device to which the request is pending. | ||
633 | * @aborted_io_completion: This is a completion structure that will be added to | ||
634 | * the request in case it is changed to aborting; this completion is | ||
635 | * triggered when the request is fully completed. | ||
636 | * | ||
637 | * Either "started" on successful change of the task status to "aborted", or | ||
638 | * "unallocated" if the task cannot be controlled. | ||
639 | */ | ||
640 | static enum isci_request_status isci_task_validate_request_to_abort( | ||
641 | struct isci_request *isci_request, | ||
642 | struct isci_host *isci_host, | ||
643 | struct isci_remote_device *isci_device, | ||
644 | struct completion *aborted_io_completion) | ||
645 | { | ||
646 | enum isci_request_status old_state = unallocated; | ||
647 | |||
648 | /* Only abort the task if it's in the | ||
649 | * device's request_in_process list | ||
650 | */ | ||
651 | if (isci_request && !list_empty(&isci_request->dev_node)) { | ||
652 | old_state = isci_request_change_started_to_aborted( | ||
653 | isci_request, aborted_io_completion); | ||
654 | |||
655 | /* Only abort requests in the started state. */ | ||
656 | if (old_state != started) | ||
657 | old_state = unallocated; | ||
658 | } | ||
659 | |||
660 | return old_state; | ||
661 | } | ||
662 | |||
663 | static void isci_request_cleanup_completed_loiterer( | ||
664 | struct isci_host *isci_host, | ||
665 | struct isci_remote_device *isci_device, | ||
666 | struct isci_request *isci_request) | ||
667 | { | ||
668 | struct sas_task *task = isci_request_access_task(isci_request); | ||
669 | unsigned long flags; | ||
670 | |||
671 | dev_dbg(&isci_host->pdev->dev, | ||
672 | "%s: isci_device=%p, request=%p, task=%p\n", | ||
673 | __func__, isci_device, isci_request, | ||
674 | isci_request->ttype_ptr.io_task_ptr); | ||
675 | |||
676 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
677 | list_del_init(&isci_request->dev_node); | ||
678 | if (task != NULL) | ||
679 | task->lldd_task = NULL; | ||
680 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
681 | |||
682 | isci_request_free(isci_host, isci_request); | ||
683 | } | ||
684 | /** | ||
685 | * isci_terminate_request_core() - This function will terminate the given | ||
686 | * request, and wait for it to complete. This function must only be called | ||
687 | * from a thread that can wait. Note that the request is terminated and | ||
688 | * completed (back to the host, if started there). | ||
689 | * @isci_host: This SCU. | ||
690 | * @isci_device: The target. | ||
691 | * @isci_request: The I/O request to be terminated. | ||
692 | * | ||
693 | * | ||
694 | */ | ||
695 | static void isci_terminate_request_core( | ||
696 | struct isci_host *isci_host, | ||
697 | struct isci_remote_device *isci_device, | ||
698 | struct isci_request *isci_request, | ||
699 | struct completion *request_completion) | ||
700 | { | ||
701 | enum sci_status status = SCI_SUCCESS; | ||
702 | bool was_terminated = false; | ||
703 | bool needs_cleanup_handling = false; | ||
704 | enum isci_request_status request_status; | ||
705 | unsigned long flags; | ||
706 | |||
707 | dev_dbg(&isci_host->pdev->dev, | ||
708 | "%s: device = %p; request = %p\n", | ||
709 | __func__, isci_device, isci_request); | ||
710 | |||
711 | /* Peek at the current status of the request. This will tell | ||
712 | * us if there was special handling on the request such that it | ||
713 | * needs to be detached and freed here. | ||
714 | */ | ||
715 | spin_lock_irqsave(&isci_request->state_lock, flags); | ||
716 | request_status = isci_request_get_state(isci_request); | ||
717 | |||
718 | /* TMFs are in their own thread */ | ||
719 | if ((isci_request->ttype == io_task) && | ||
720 | ((request_status == aborted) || | ||
721 | (request_status == aborting) || | ||
722 | (request_status == terminating))) | ||
723 | /* The completion routine won't free a request in | ||
724 | * the aborted/aborting/terminating state, so we do | ||
725 | * it here. | ||
726 | */ | ||
727 | needs_cleanup_handling = true; | ||
728 | |||
729 | spin_unlock_irqrestore(&isci_request->state_lock, flags); | ||
730 | |||
731 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
732 | /* Make sure the request wasn't just sitting around signalling | ||
733 | * device condition (if the request handle is NULL, then the | ||
734 | * request completed but needed additional handling here). | ||
735 | */ | ||
736 | if (isci_request->sci_request_handle != NULL) { | ||
737 | was_terminated = true; | ||
738 | status = scic_controller_terminate_request( | ||
739 | isci_host->core_controller, | ||
740 | isci_device->sci_device_handle, | ||
741 | isci_request->sci_request_handle | ||
742 | ); | ||
743 | } | ||
744 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
745 | |||
746 | /* | ||
747 | * The only time the request to terminate will | ||
748 | * fail is when the io request is completed and | ||
749 | * being aborted. | ||
750 | */ | ||
751 | if (status != SCI_SUCCESS) | ||
752 | dev_err(&isci_host->pdev->dev, | ||
753 | "%s: scic_controller_terminate_request" | ||
754 | " returned = 0x%x\n", | ||
755 | __func__, | ||
756 | status); | ||
757 | else { | ||
758 | if (was_terminated) { | ||
759 | dev_dbg(&isci_host->pdev->dev, | ||
760 | "%s: before completion wait (%p)\n", | ||
761 | __func__, | ||
762 | request_completion); | ||
763 | |||
764 | /* Wait here for the request to complete. */ | ||
765 | wait_for_completion(request_completion); | ||
766 | |||
767 | dev_dbg(&isci_host->pdev->dev, | ||
768 | "%s: after completion wait (%p)\n", | ||
769 | __func__, | ||
770 | request_completion); | ||
771 | } | ||
772 | |||
773 | if (needs_cleanup_handling) | ||
774 | isci_request_cleanup_completed_loiterer( | ||
775 | isci_host, isci_device, isci_request | ||
776 | ); | ||
777 | } | ||
778 | } | ||
779 | static void isci_terminate_request( | ||
780 | struct isci_host *isci_host, | ||
781 | struct isci_remote_device *isci_device, | ||
782 | struct isci_request *isci_request, | ||
783 | enum isci_request_status new_request_state) | ||
784 | { | ||
785 | enum isci_request_status old_state; | ||
786 | |||
787 | DECLARE_COMPLETION_ONSTACK(request_completion); | ||
788 | unsigned long flags; | ||
789 | |||
790 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
791 | |||
792 | /* Change state to "new_request_state" if it is currently "started" */ | ||
793 | old_state = isci_request_change_started_to_newstate( | ||
794 | isci_request, | ||
795 | &request_completion, | ||
796 | new_request_state | ||
797 | ); | ||
798 | |||
799 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
800 | |||
801 | if (old_state == started) | ||
802 | /* This request was not already being aborted. If it had been, | ||
803 | * then the aborting I/O (ie. the TMF request) would not be in | ||
804 | * the aborting state, and thus would be terminated here. Note | ||
805 | * that since the TMF completion's call to the kernel function | ||
806 | * "complete()" does not happen until the pending I/O request | ||
807 | * terminate fully completes, we do not have to implement a | ||
808 | * special wait here for already aborting requests - the | ||
809 | * termination of the TMF request will force the request | ||
810 | * to finish it's already started terminate. | ||
811 | */ | ||
812 | isci_terminate_request_core(isci_host, isci_device, | ||
813 | isci_request, &request_completion); | ||
814 | } | ||
815 | |||
816 | /** | ||
817 | * isci_terminate_pending_requests() - This function will change the all of the | ||
818 | * requests on the given device's state to "aborting", will terminate the | ||
819 | * requests, and wait for them to complete. This function must only be | ||
820 | * called from a thread that can wait. Note that the requests are all | ||
821 | * terminated and completed (back to the host, if started there). | ||
822 | * @isci_host: This parameter specifies SCU. | ||
823 | * @isci_device: This parameter specifies the target. | ||
824 | * | ||
825 | * | ||
826 | */ | ||
827 | void isci_terminate_pending_requests( | ||
828 | struct isci_host *isci_host, | ||
829 | struct isci_remote_device *isci_device, | ||
830 | enum isci_request_status new_request_state) | ||
831 | { | ||
832 | struct isci_request *isci_request; | ||
833 | struct sas_task *task; | ||
834 | bool done = false; | ||
835 | unsigned long flags; | ||
836 | |||
837 | dev_dbg(&isci_host->pdev->dev, | ||
838 | "%s: isci_device = %p (new request state = %d)\n", | ||
839 | __func__, isci_device, new_request_state); | ||
840 | |||
841 | #define ISCI_TERMINATE_SHOW_PENDING_REQUESTS | ||
842 | #ifdef ISCI_TERMINATE_SHOW_PENDING_REQUESTS | ||
843 | { | ||
844 | struct isci_request *request; | ||
845 | |||
846 | /* Only abort the task if it's in the | ||
847 | * device's request_in_process list | ||
848 | */ | ||
849 | list_for_each_entry(request, | ||
850 | &isci_device->reqs_in_process, | ||
851 | dev_node) | ||
852 | dev_dbg(&isci_host->pdev->dev, | ||
853 | "%s: isci_device = %p; request is on " | ||
854 | "reqs_in_process list: %p\n", | ||
855 | __func__, isci_device, request); | ||
856 | } | ||
857 | #endif /* ISCI_TERMINATE_SHOW_PENDING_REQUESTS */ | ||
858 | |||
859 | /* Clean up all pending requests. */ | ||
860 | do { | ||
861 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
862 | |||
863 | if (list_empty(&isci_device->reqs_in_process)) { | ||
864 | |||
865 | done = true; | ||
866 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
867 | |||
868 | dev_dbg(&isci_host->pdev->dev, | ||
869 | "%s: isci_device = %p; done.\n", | ||
870 | __func__, isci_device); | ||
871 | } else { | ||
872 | /* The list was not empty - grab the first request. */ | ||
873 | isci_request = list_first_entry( | ||
874 | &isci_device->reqs_in_process, | ||
875 | struct isci_request, dev_node | ||
876 | ); | ||
877 | /* Note that we are not expecting to have to control | ||
878 | * the target to abort the request. | ||
879 | */ | ||
880 | isci_request->complete_in_target = true; | ||
881 | |||
882 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
883 | |||
884 | /* Get the libsas task reference. */ | ||
885 | task = isci_request_access_task(isci_request); | ||
886 | |||
887 | dev_dbg(&isci_host->pdev->dev, | ||
888 | "%s: isci_device=%p request=%p; task=%p\n", | ||
889 | __func__, isci_device, isci_request, task); | ||
890 | |||
891 | /* Mark all still pending I/O with the selected next | ||
892 | * state. | ||
893 | */ | ||
894 | isci_terminate_request(isci_host, isci_device, | ||
895 | isci_request, new_request_state | ||
896 | ); | ||
897 | |||
898 | /* Set the 'done' state on the task. */ | ||
899 | if (task) | ||
900 | isci_task_all_done(task); | ||
901 | } | ||
902 | } while (!done); | ||
903 | } | ||
904 | |||
905 | /** | ||
906 | * isci_task_send_lu_reset_sas() - This function is called by of the SAS Domain | ||
907 | * Template functions. | ||
908 | * @lun: This parameter specifies the lun to be reset. | ||
909 | * | ||
910 | * status, zero indicates success. | ||
911 | */ | ||
912 | static int isci_task_send_lu_reset_sas( | ||
913 | struct isci_host *isci_host, | ||
914 | struct isci_remote_device *isci_device, | ||
915 | u8 *lun) | ||
916 | { | ||
917 | struct isci_tmf tmf; | ||
918 | int ret = TMF_RESP_FUNC_FAILED; | ||
919 | |||
920 | dev_dbg(&isci_host->pdev->dev, | ||
921 | "%s: isci_host = %p, isci_device = %p\n", | ||
922 | __func__, isci_host, isci_device); | ||
923 | /* Send the LUN reset to the target. By the time the call returns, | ||
924 | * the TMF has fully exected in the target (in which case the return | ||
925 | * value is "TMF_RESP_FUNC_COMPLETE", or the request timed-out (or | ||
926 | * was otherwise unable to be executed ("TMF_RESP_FUNC_FAILED"). | ||
927 | */ | ||
928 | isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_lun_reset, NULL, | ||
929 | NULL); | ||
930 | |||
931 | #define ISCI_LU_RESET_TIMEOUT_MS 2000 /* 2 second timeout. */ | ||
932 | ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_LU_RESET_TIMEOUT_MS); | ||
933 | |||
934 | if (ret == TMF_RESP_FUNC_COMPLETE) | ||
935 | dev_dbg(&isci_host->pdev->dev, | ||
936 | "%s: %p: TMF_LU_RESET passed\n", | ||
937 | __func__, isci_device); | ||
938 | else | ||
939 | dev_dbg(&isci_host->pdev->dev, | ||
940 | "%s: %p: TMF_LU_RESET failed (%x)\n", | ||
941 | __func__, isci_device, ret); | ||
942 | |||
943 | return ret; | ||
944 | } | ||
945 | |||
946 | /** | ||
947 | * isci_task_lu_reset() - This function is one of the SAS Domain Template | ||
948 | * functions. This is one of the Task Management functoins called by libsas, | ||
949 | * to reset the given lun. Note the assumption that while this call is | ||
950 | * executing, no I/O will be sent by the host to the device. | ||
951 | * @lun: This parameter specifies the lun to be reset. | ||
952 | * | ||
953 | * status, zero indicates success. | ||
954 | */ | ||
955 | int isci_task_lu_reset( | ||
956 | struct domain_device *domain_device, | ||
957 | u8 *lun) | ||
958 | { | ||
959 | struct isci_host *isci_host = NULL; | ||
960 | struct isci_remote_device *isci_device = NULL; | ||
961 | int ret; | ||
962 | bool device_stopping = false; | ||
963 | |||
964 | if (domain_device == NULL) { | ||
965 | pr_warn("%s: domain_device == NULL\n", __func__); | ||
966 | return TMF_RESP_FUNC_FAILED; | ||
967 | } | ||
968 | |||
969 | isci_device = isci_dev_from_domain_dev(domain_device); | ||
970 | |||
971 | if (domain_device->port != NULL) | ||
972 | isci_host = isci_host_from_sas_ha(domain_device->port->ha); | ||
973 | |||
974 | pr_debug("%s: domain_device=%p, isci_host=%p; isci_device=%p\n", | ||
975 | __func__, domain_device, isci_host, isci_device); | ||
976 | |||
977 | if (isci_device != NULL) | ||
978 | device_stopping = (isci_device->status == isci_stopping) | ||
979 | || (isci_device->status == isci_stopped); | ||
980 | |||
981 | /* If there is a device reset pending on any request in the | ||
982 | * device's list, fail this LUN reset request in order to | ||
983 | * escalate to the device reset. | ||
984 | */ | ||
985 | if ((isci_device == NULL) || | ||
986 | (isci_host == NULL) || | ||
987 | ((isci_host != NULL) && | ||
988 | (isci_device != NULL) && | ||
989 | (device_stopping || | ||
990 | (isci_device_is_reset_pending(isci_host, isci_device))))) { | ||
991 | dev_warn(&isci_host->pdev->dev, | ||
992 | "%s: No dev (%p), no host (%p), or " | ||
993 | "RESET PENDING: domain_device=%p\n", | ||
994 | __func__, isci_device, isci_host, domain_device); | ||
995 | return TMF_RESP_FUNC_FAILED; | ||
996 | } | ||
997 | |||
998 | /* Stop I/O to the remote device. */ | ||
999 | isci_device_set_host_quiesce_lock_state(isci_device, true); | ||
1000 | |||
1001 | /* Send the task management part of the reset. */ | ||
1002 | if (sas_protocol_ata(domain_device->tproto)) { | ||
1003 | ret = isci_task_send_lu_reset_sata( | ||
1004 | isci_host, isci_device, lun | ||
1005 | ); | ||
1006 | } else | ||
1007 | ret = isci_task_send_lu_reset_sas(isci_host, isci_device, lun); | ||
1008 | |||
1009 | /* If the LUN reset worked, all the I/O can now be terminated. */ | ||
1010 | if (ret == TMF_RESP_FUNC_COMPLETE) | ||
1011 | /* Terminate all I/O now. */ | ||
1012 | isci_terminate_pending_requests(isci_host, | ||
1013 | isci_device, | ||
1014 | terminating); | ||
1015 | |||
1016 | /* Resume I/O to the remote device. */ | ||
1017 | isci_device_set_host_quiesce_lock_state(isci_device, false); | ||
1018 | |||
1019 | return ret; | ||
1020 | } | ||
1021 | |||
1022 | |||
1023 | /* int (*lldd_clear_nexus_port)(struct asd_sas_port *); */ | ||
1024 | int isci_task_clear_nexus_port(struct asd_sas_port *port) | ||
1025 | { | ||
1026 | return TMF_RESP_FUNC_FAILED; | ||
1027 | } | ||
1028 | |||
1029 | |||
1030 | |||
1031 | int isci_task_clear_nexus_ha(struct sas_ha_struct *ha) | ||
1032 | { | ||
1033 | return TMF_RESP_FUNC_FAILED; | ||
1034 | } | ||
1035 | |||
1036 | int isci_task_I_T_nexus_reset(struct domain_device *dev) | ||
1037 | { | ||
1038 | return TMF_RESP_FUNC_FAILED; | ||
1039 | } | ||
1040 | |||
1041 | |||
1042 | /* Task Management Functions. Must be called from process context. */ | ||
1043 | |||
1044 | /** | ||
1045 | * isci_abort_task_process_cb() - This is a helper function for the abort task | ||
1046 | * TMF command. It manages the request state with respect to the successful | ||
1047 | * transmission / completion of the abort task request. | ||
1048 | * @cb_state: This parameter specifies when this function was called - after | ||
1049 | * the TMF request has been started and after it has timed-out. | ||
1050 | * @tmf: This parameter specifies the TMF in progress. | ||
1051 | * | ||
1052 | * | ||
1053 | */ | ||
1054 | static void isci_abort_task_process_cb( | ||
1055 | enum isci_tmf_cb_state cb_state, | ||
1056 | struct isci_tmf *tmf, | ||
1057 | void *cb_data) | ||
1058 | { | ||
1059 | struct isci_request *old_request; | ||
1060 | |||
1061 | old_request = (struct isci_request *)cb_data; | ||
1062 | |||
1063 | dev_dbg(&old_request->isci_host->pdev->dev, | ||
1064 | "%s: tmf=%p, old_request=%p\n", | ||
1065 | __func__, tmf, old_request); | ||
1066 | |||
1067 | switch (cb_state) { | ||
1068 | |||
1069 | case isci_tmf_started: | ||
1070 | /* The TMF has been started. Nothing to do here, since the | ||
1071 | * request state was already set to "aborted" by the abort | ||
1072 | * task function. | ||
1073 | */ | ||
1074 | BUG_ON(old_request->status != aborted); | ||
1075 | break; | ||
1076 | |||
1077 | case isci_tmf_timed_out: | ||
1078 | |||
1079 | /* Set the task's state to "aborting", since the abort task | ||
1080 | * function thread set it to "aborted" (above) in anticipation | ||
1081 | * of the task management request working correctly. Since the | ||
1082 | * timeout has now fired, the TMF request failed. We set the | ||
1083 | * state such that the request completion will indicate the | ||
1084 | * device is no longer present. | ||
1085 | */ | ||
1086 | isci_request_change_state(old_request, aborting); | ||
1087 | break; | ||
1088 | |||
1089 | default: | ||
1090 | dev_err(&old_request->isci_host->pdev->dev, | ||
1091 | "%s: Bad cb_state (%d): tmf=%p, old_request=%p\n", | ||
1092 | __func__, cb_state, tmf, old_request); | ||
1093 | break; | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | /** | ||
1098 | * isci_task_abort_task() - This function is one of the SAS Domain Template | ||
1099 | * functions. This function is called by libsas to abort a specified task. | ||
1100 | * @task: This parameter specifies the SAS task to abort. | ||
1101 | * | ||
1102 | * status, zero indicates success. | ||
1103 | */ | ||
1104 | int isci_task_abort_task(struct sas_task *task) | ||
1105 | { | ||
1106 | DECLARE_COMPLETION_ONSTACK(aborted_io_completion); | ||
1107 | struct isci_request *old_request = NULL; | ||
1108 | struct isci_remote_device *isci_device = NULL; | ||
1109 | struct isci_host *isci_host = NULL; | ||
1110 | struct isci_tmf tmf; | ||
1111 | int ret = TMF_RESP_FUNC_FAILED; | ||
1112 | unsigned long flags; | ||
1113 | bool any_dev_reset, device_stopping; | ||
1114 | |||
1115 | /* Get the isci_request reference from the task. Note that | ||
1116 | * this check does not depend on the pending request list | ||
1117 | * in the device, because tasks driving resets may land here | ||
1118 | * after completion in the core. | ||
1119 | */ | ||
1120 | old_request = isci_task_get_request_from_task(task, &isci_host, | ||
1121 | &isci_device); | ||
1122 | |||
1123 | dev_dbg(&isci_host->pdev->dev, | ||
1124 | "%s: task = %p\n", __func__, task); | ||
1125 | |||
1126 | /* Check if the device has been / is currently being removed. | ||
1127 | * If so, no task management will be done, and the I/O will | ||
1128 | * be terminated. | ||
1129 | */ | ||
1130 | device_stopping = (isci_device->status == isci_stopping) | ||
1131 | || (isci_device->status == isci_stopped); | ||
1132 | |||
1133 | #ifdef NOMORE | ||
1134 | /* This abort task function is the first stop of the libsas error | ||
1135 | * handler thread. Since libsas is executing in a thread with a | ||
1136 | * referernce to the "task" parameter, that task cannot be completed | ||
1137 | * directly back to the upper layers. In order to make sure that | ||
1138 | * the task is managed correctly if this abort task fails, set the | ||
1139 | * "SAS_TASK_STATE_ABORTED" bit now such that completions up the | ||
1140 | * stack will be intercepted and only allowed to happen in the | ||
1141 | * libsas SCSI error handler thread. | ||
1142 | */ | ||
1143 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
1144 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
1145 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
1146 | #endif /* NOMORE */ | ||
1147 | |||
1148 | /* This version of the driver will fail abort requests for | ||
1149 | * SATA/STP. Failing the abort request this way will cause the | ||
1150 | * SCSI error handler thread to escalate to LUN reset | ||
1151 | */ | ||
1152 | if (sas_protocol_ata(task->task_proto) && !device_stopping) { | ||
1153 | dev_warn(&isci_host->pdev->dev, | ||
1154 | " task %p is for a STP/SATA device;" | ||
1155 | " returning TMF_RESP_FUNC_FAILED\n" | ||
1156 | " to cause a LUN reset...\n", task); | ||
1157 | return TMF_RESP_FUNC_FAILED; | ||
1158 | } | ||
1159 | |||
1160 | dev_dbg(&isci_host->pdev->dev, | ||
1161 | "%s: old_request == %p\n", __func__, old_request); | ||
1162 | |||
1163 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
1164 | |||
1165 | /* Don't do resets to stopping devices. */ | ||
1166 | if (device_stopping) | ||
1167 | task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET; | ||
1168 | |||
1169 | /* See if there is a pending device reset for this device. */ | ||
1170 | any_dev_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; | ||
1171 | |||
1172 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
1173 | |||
1174 | if ((isci_device != NULL) && !device_stopping) | ||
1175 | any_dev_reset = any_dev_reset | ||
1176 | || isci_device_is_reset_pending(isci_host, | ||
1177 | isci_device | ||
1178 | ); | ||
1179 | |||
1180 | /* If the extraction of the request reference from the task | ||
1181 | * failed, then the request has been completed (or if there is a | ||
1182 | * pending reset then this abort request function must be failed | ||
1183 | * in order to escalate to the target reset). | ||
1184 | */ | ||
1185 | if ((old_request == NULL) || | ||
1186 | ((old_request != NULL) && | ||
1187 | (old_request->sci_request_handle == NULL) && | ||
1188 | (old_request->complete_in_target)) || | ||
1189 | any_dev_reset) { | ||
1190 | |||
1191 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
1192 | |||
1193 | /* If the device reset task flag is set, fail the task | ||
1194 | * management request. Otherwise, the original request | ||
1195 | * has completed. | ||
1196 | */ | ||
1197 | if (any_dev_reset) { | ||
1198 | |||
1199 | /* Turn off the task's DONE to make sure this | ||
1200 | * task is escalated to a target reset. | ||
1201 | */ | ||
1202 | task->task_state_flags &= ~SAS_TASK_STATE_DONE; | ||
1203 | |||
1204 | /* Fail the task management request in order to | ||
1205 | * escalate to the target reset. | ||
1206 | */ | ||
1207 | ret = TMF_RESP_FUNC_FAILED; | ||
1208 | |||
1209 | dev_dbg(&isci_host->pdev->dev, | ||
1210 | "%s: Failing task abort in order to " | ||
1211 | "escalate to target reset because\n" | ||
1212 | "SAS_TASK_NEED_DEV_RESET is set for " | ||
1213 | "task %p on dev %p\n", | ||
1214 | __func__, task, isci_device); | ||
1215 | |||
1216 | } else { | ||
1217 | ret = TMF_RESP_FUNC_COMPLETE; | ||
1218 | |||
1219 | dev_dbg(&isci_host->pdev->dev, | ||
1220 | "%s: abort task not needed for %p\n", | ||
1221 | __func__, task); | ||
1222 | |||
1223 | /* The request has already completed and there | ||
1224 | * is nothing to do here other than to set the task | ||
1225 | * done bit, and indicate that the task abort function | ||
1226 | * was sucessful. | ||
1227 | */ | ||
1228 | isci_set_task_doneflags(task); | ||
1229 | |||
1230 | /* Set the abort bit to make sure that libsas sticks the | ||
1231 | * task in the completed task queue. | ||
1232 | */ | ||
1233 | /* task->task_state_flags |= SAS_TASK_STATE_ABORTED; */ | ||
1234 | |||
1235 | /* Check for the situation where the request was | ||
1236 | * left around on the device list but the | ||
1237 | * request already completed. | ||
1238 | */ | ||
1239 | if (old_request && !old_request->sci_request_handle) { | ||
1240 | |||
1241 | isci_request_cleanup_completed_loiterer( | ||
1242 | isci_host, isci_device, old_request | ||
1243 | ); | ||
1244 | } | ||
1245 | } | ||
1246 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
1247 | |||
1248 | return ret; | ||
1249 | } | ||
1250 | |||
1251 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
1252 | |||
1253 | /* Sanity check the request status, and set the I/O kernel completion | ||
1254 | * struct that will be triggered when the request completes. | ||
1255 | */ | ||
1256 | if (isci_task_validate_request_to_abort( | ||
1257 | old_request, | ||
1258 | isci_host, | ||
1259 | isci_device, | ||
1260 | &aborted_io_completion) | ||
1261 | == unallocated) { | ||
1262 | dev_dbg(&isci_host->pdev->dev, | ||
1263 | "%s: old_request not valid for device = %p\n", | ||
1264 | __func__, | ||
1265 | isci_device); | ||
1266 | old_request = NULL; | ||
1267 | } | ||
1268 | |||
1269 | if (!old_request) { | ||
1270 | |||
1271 | /* There is no isci_request attached to the sas_task. | ||
1272 | * It must have been completed and detached. | ||
1273 | */ | ||
1274 | dev_dbg(&isci_host->pdev->dev, | ||
1275 | "%s: old_request == NULL\n", | ||
1276 | __func__); | ||
1277 | |||
1278 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
1279 | |||
1280 | /* Set the state on the task. */ | ||
1281 | isci_task_all_done(task); | ||
1282 | |||
1283 | return TMF_RESP_FUNC_COMPLETE; | ||
1284 | } | ||
1285 | if (task->task_proto == SAS_PROTOCOL_SMP || device_stopping) { | ||
1286 | |||
1287 | if (device_stopping) | ||
1288 | dev_dbg(&isci_host->pdev->dev, | ||
1289 | "%s: device is stopping, thus no TMF\n", | ||
1290 | __func__); | ||
1291 | else | ||
1292 | dev_dbg(&isci_host->pdev->dev, | ||
1293 | "%s: request is SMP, thus no TMF\n", | ||
1294 | __func__); | ||
1295 | |||
1296 | old_request->complete_in_target = true; | ||
1297 | |||
1298 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
1299 | |||
1300 | /* Set the state on the task. */ | ||
1301 | isci_task_all_done(task); | ||
1302 | |||
1303 | ret = TMF_RESP_FUNC_COMPLETE; | ||
1304 | |||
1305 | /* Stopping and SMP devices are not sent a TMF, and are not | ||
1306 | * reset, but the outstanding I/O request is terminated here. | ||
1307 | * | ||
1308 | * Clean up the request on our side, and wait for the aborted | ||
1309 | * I/O to complete. | ||
1310 | */ | ||
1311 | isci_terminate_request_core(isci_host, isci_device, old_request, | ||
1312 | &aborted_io_completion); | ||
1313 | } else { | ||
1314 | /* Fill in the tmf stucture */ | ||
1315 | isci_task_build_tmf(&tmf, isci_device, isci_tmf_ssp_task_abort, | ||
1316 | isci_abort_task_process_cb, old_request); | ||
1317 | |||
1318 | tmf.io_tag = scic_io_request_get_io_tag( | ||
1319 | old_request->sci_request_handle | ||
1320 | ); | ||
1321 | |||
1322 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
1323 | |||
1324 | #define ISCI_ABORT_TASK_TIMEOUT_MS 500 /* half second timeout. */ | ||
1325 | ret = isci_task_execute_tmf(isci_host, &tmf, | ||
1326 | ISCI_ABORT_TASK_TIMEOUT_MS); | ||
1327 | |||
1328 | if (ret == TMF_RESP_FUNC_COMPLETE) { | ||
1329 | old_request->complete_in_target = true; | ||
1330 | |||
1331 | /* Clean up the request on our side, and wait for the aborted I/O to | ||
1332 | * complete. | ||
1333 | */ | ||
1334 | isci_terminate_request_core(isci_host, isci_device, old_request, | ||
1335 | &aborted_io_completion); | ||
1336 | |||
1337 | /* Set the state on the task. */ | ||
1338 | isci_task_all_done(task); | ||
1339 | } else | ||
1340 | dev_err(&isci_host->pdev->dev, | ||
1341 | "%s: isci_task_send_tmf failed\n", | ||
1342 | __func__); | ||
1343 | } | ||
1344 | |||
1345 | return ret; | ||
1346 | } | ||
1347 | |||
1348 | /** | ||
1349 | * isci_task_abort_task_set() - This function is one of the SAS Domain Template | ||
1350 | * functions. This is one of the Task Management functoins called by libsas, | ||
1351 | * to abort all task for the given lun. | ||
1352 | * @d_device: This parameter specifies the domain device associated with this | ||
1353 | * request. | ||
1354 | * @lun: This parameter specifies the lun associated with this request. | ||
1355 | * | ||
1356 | * status, zero indicates success. | ||
1357 | */ | ||
1358 | int isci_task_abort_task_set( | ||
1359 | struct domain_device *d_device, | ||
1360 | u8 *lun) | ||
1361 | { | ||
1362 | return TMF_RESP_FUNC_FAILED; | ||
1363 | } | ||
1364 | |||
1365 | |||
1366 | /** | ||
1367 | * isci_task_clear_aca() - This function is one of the SAS Domain Template | ||
1368 | * functions. This is one of the Task Management functoins called by libsas. | ||
1369 | * @d_device: This parameter specifies the domain device associated with this | ||
1370 | * request. | ||
1371 | * @lun: This parameter specifies the lun associated with this request. | ||
1372 | * | ||
1373 | * status, zero indicates success. | ||
1374 | */ | ||
1375 | int isci_task_clear_aca( | ||
1376 | struct domain_device *d_device, | ||
1377 | u8 *lun) | ||
1378 | { | ||
1379 | return TMF_RESP_FUNC_FAILED; | ||
1380 | } | ||
1381 | |||
1382 | |||
1383 | |||
1384 | /** | ||
1385 | * isci_task_clear_task_set() - This function is one of the SAS Domain Template | ||
1386 | * functions. This is one of the Task Management functoins called by libsas. | ||
1387 | * @d_device: This parameter specifies the domain device associated with this | ||
1388 | * request. | ||
1389 | * @lun: This parameter specifies the lun associated with this request. | ||
1390 | * | ||
1391 | * status, zero indicates success. | ||
1392 | */ | ||
1393 | int isci_task_clear_task_set( | ||
1394 | struct domain_device *d_device, | ||
1395 | u8 *lun) | ||
1396 | { | ||
1397 | return TMF_RESP_FUNC_FAILED; | ||
1398 | } | ||
1399 | |||
1400 | |||
1401 | /** | ||
1402 | * isci_task_query_task() - This function is implemented to cause libsas to | ||
1403 | * correctly escalate the failed abort to a LUN or target reset (this is | ||
1404 | * because sas_scsi_find_task libsas function does not correctly interpret | ||
1405 | * all return codes from the abort task call). When TMF_RESP_FUNC_SUCC is | ||
1406 | * returned, libsas turns this into a LUN reset; when FUNC_FAILED is | ||
1407 | * returned, libsas will turn this into a target reset | ||
1408 | * @task: This parameter specifies the sas task being queried. | ||
1409 | * @lun: This parameter specifies the lun associated with this request. | ||
1410 | * | ||
1411 | * status, zero indicates success. | ||
1412 | */ | ||
1413 | int isci_task_query_task( | ||
1414 | struct sas_task *task) | ||
1415 | { | ||
1416 | /* See if there is a pending device reset for this device. */ | ||
1417 | if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) | ||
1418 | return TMF_RESP_FUNC_FAILED; | ||
1419 | else | ||
1420 | return TMF_RESP_FUNC_SUCC; | ||
1421 | } | ||
1422 | |||
1423 | /** | ||
1424 | * isci_task_request_complete() - This function is called by the sci core when | ||
1425 | * an task request completes. | ||
1426 | * @isci_host: This parameter specifies the ISCI host object | ||
1427 | * @request: This parameter is the completed isci_request object. | ||
1428 | * @completion_status: This parameter specifies the completion status from the | ||
1429 | * sci core. | ||
1430 | * | ||
1431 | * none. | ||
1432 | */ | ||
1433 | void isci_task_request_complete( | ||
1434 | struct isci_host *isci_host, | ||
1435 | struct isci_request *request, | ||
1436 | enum sci_task_status completion_status) | ||
1437 | { | ||
1438 | struct isci_remote_device *isci_device = request->isci_device; | ||
1439 | enum isci_request_status old_state; | ||
1440 | struct isci_tmf *tmf = isci_request_access_tmf(request); | ||
1441 | struct completion *tmf_complete; | ||
1442 | |||
1443 | dev_dbg(&isci_host->pdev->dev, | ||
1444 | "%s: request = %p, status=%d\n", | ||
1445 | __func__, request, completion_status); | ||
1446 | |||
1447 | old_state = isci_request_change_state(request, completed); | ||
1448 | |||
1449 | tmf->status = completion_status; | ||
1450 | request->complete_in_target = true; | ||
1451 | |||
1452 | if (SAS_PROTOCOL_SSP == tmf->proto) { | ||
1453 | |||
1454 | memcpy(&tmf->resp.resp_iu, | ||
1455 | scic_io_request_get_response_iu_address( | ||
1456 | request->sci_request_handle | ||
1457 | ), | ||
1458 | sizeof(struct sci_ssp_response_iu)); | ||
1459 | |||
1460 | } else if (SAS_PROTOCOL_SATA == tmf->proto) { | ||
1461 | |||
1462 | memcpy(&tmf->resp.d2h_fis, | ||
1463 | scic_stp_io_request_get_d2h_reg_address( | ||
1464 | request->sci_request_handle | ||
1465 | ), | ||
1466 | sizeof(struct sata_fis_reg_d2h) | ||
1467 | ); | ||
1468 | } | ||
1469 | |||
1470 | /* Manage the timer if it is still running. */ | ||
1471 | if (tmf->timeout_timer) { | ||
1472 | |||
1473 | isci_timer_stop(tmf->timeout_timer); | ||
1474 | isci_timer_free(&isci_host->timer_list_struct, | ||
1475 | tmf->timeout_timer); | ||
1476 | tmf->timeout_timer = NULL; | ||
1477 | } | ||
1478 | |||
1479 | /* PRINT_TMF( ((struct isci_tmf *)request->task)); */ | ||
1480 | tmf_complete = tmf->complete; | ||
1481 | |||
1482 | scic_controller_complete_task( | ||
1483 | isci_host->core_controller, | ||
1484 | isci_device->sci_device_handle, | ||
1485 | request->sci_request_handle | ||
1486 | ); | ||
1487 | /* NULL the request handle to make sure it cannot be terminated | ||
1488 | * or completed again. | ||
1489 | */ | ||
1490 | request->sci_request_handle = NULL; | ||
1491 | |||
1492 | isci_request_change_state(request, unallocated); | ||
1493 | list_del_init(&request->dev_node); | ||
1494 | |||
1495 | /* The task management part completes last. */ | ||
1496 | complete(tmf_complete); | ||
1497 | } | ||
1498 | |||
1499 | |||
1500 | /** | ||
1501 | * isci_task_ssp_request_get_lun() - This function is called by the sci core to | ||
1502 | * retrieve the lun for a given task request. | ||
1503 | * @request: This parameter is the isci_request object. | ||
1504 | * | ||
1505 | * lun for specified task request. | ||
1506 | */ | ||
1507 | u32 isci_task_ssp_request_get_lun(struct isci_request *request) | ||
1508 | { | ||
1509 | struct isci_tmf *isci_tmf = isci_request_access_tmf(request); | ||
1510 | |||
1511 | dev_dbg(&request->isci_host->pdev->dev, | ||
1512 | "%s: lun = %d\n", __func__, isci_tmf->lun[0]); | ||
1513 | /* @todo: build lun from array of bytes to 32 bit */ | ||
1514 | return isci_tmf->lun[0]; | ||
1515 | } | ||
1516 | |||
1517 | /** | ||
1518 | * isci_task_ssp_request_get_function() - This function is called by the sci | ||
1519 | * core to retrieve the function for a given task request. | ||
1520 | * @request: This parameter is the isci_request object. | ||
1521 | * | ||
1522 | * function code for specified task request. | ||
1523 | */ | ||
1524 | u8 isci_task_ssp_request_get_function(struct isci_request *request) | ||
1525 | { | ||
1526 | struct isci_tmf *isci_tmf = isci_request_access_tmf(request); | ||
1527 | |||
1528 | dev_dbg(&request->isci_host->pdev->dev, | ||
1529 | "%s: func = %d\n", __func__, isci_tmf->tmf_code); | ||
1530 | |||
1531 | return isci_tmf->tmf_code; | ||
1532 | } | ||
1533 | |||
1534 | /** | ||
1535 | * isci_task_ssp_request_get_io_tag_to_manage() - This function is called by | ||
1536 | * the sci core to retrieve the io tag for a given task request. | ||
1537 | * @request: This parameter is the isci_request object. | ||
1538 | * | ||
1539 | * io tag for specified task request. | ||
1540 | */ | ||
1541 | u16 isci_task_ssp_request_get_io_tag_to_manage(struct isci_request *request) | ||
1542 | { | ||
1543 | u16 io_tag = SCI_CONTROLLER_INVALID_IO_TAG; | ||
1544 | |||
1545 | if (tmf_task == request->ttype) { | ||
1546 | struct isci_tmf *tmf = isci_request_access_tmf(request); | ||
1547 | io_tag = tmf->io_tag; | ||
1548 | } | ||
1549 | |||
1550 | dev_dbg(&request->isci_host->pdev->dev, | ||
1551 | "%s: request = %p, io_tag = %d\n", | ||
1552 | __func__, request, io_tag); | ||
1553 | |||
1554 | return io_tag; | ||
1555 | } | ||
1556 | |||
1557 | /** | ||
1558 | * isci_task_ssp_request_get_response_data_address() - This function is called | ||
1559 | * by the sci core to retrieve the response data address for a given task | ||
1560 | * request. | ||
1561 | * @request: This parameter is the isci_request object. | ||
1562 | * | ||
1563 | * response data address for specified task request. | ||
1564 | */ | ||
1565 | void *isci_task_ssp_request_get_response_data_address( | ||
1566 | struct isci_request *request) | ||
1567 | { | ||
1568 | struct isci_tmf *isci_tmf = isci_request_access_tmf(request); | ||
1569 | |||
1570 | return &isci_tmf->resp.resp_iu; | ||
1571 | } | ||
1572 | |||
1573 | /** | ||
1574 | * isci_task_ssp_request_get_response_data_length() - This function is called | ||
1575 | * by the sci core to retrieve the response data length for a given task | ||
1576 | * request. | ||
1577 | * @request: This parameter is the isci_request object. | ||
1578 | * | ||
1579 | * response data length for specified task request. | ||
1580 | */ | ||
1581 | u32 isci_task_ssp_request_get_response_data_length( | ||
1582 | struct isci_request *request) | ||
1583 | { | ||
1584 | struct isci_tmf *isci_tmf = isci_request_access_tmf(request); | ||
1585 | |||
1586 | return sizeof(isci_tmf->resp.resp_iu); | ||
1587 | } | ||
1588 | |||
1589 | /** | ||
1590 | * isci_bus_reset_handler() - This function performs a target reset of the | ||
1591 | * device referenced by "cmd'. This function is exported through the | ||
1592 | * "struct scsi_host_template" structure such that it is called when an I/O | ||
1593 | * recovery process has escalated to a target reset. Note that this function | ||
1594 | * is called from the scsi error handler event thread, so may block on calls. | ||
1595 | * @scsi_cmd: This parameter specifies the target to be reset. | ||
1596 | * | ||
1597 | * SUCCESS if the reset process was successful, else FAILED. | ||
1598 | */ | ||
1599 | int isci_bus_reset_handler(struct scsi_cmnd *cmd) | ||
1600 | { | ||
1601 | unsigned long flags = 0; | ||
1602 | struct isci_host *isci_host = NULL; | ||
1603 | enum sci_status status; | ||
1604 | int base_status; | ||
1605 | struct isci_remote_device *isci_dev | ||
1606 | = isci_dev_from_domain_dev( | ||
1607 | sdev_to_domain_dev(cmd->device)); | ||
1608 | |||
1609 | dev_dbg(&cmd->device->sdev_gendev, | ||
1610 | "%s: cmd %p, isci_dev %p\n", | ||
1611 | __func__, cmd, isci_dev); | ||
1612 | |||
1613 | if (!isci_dev) { | ||
1614 | dev_warn(&cmd->device->sdev_gendev, | ||
1615 | "%s: isci_dev is GONE!\n", | ||
1616 | __func__); | ||
1617 | |||
1618 | return TMF_RESP_FUNC_COMPLETE; /* Nothing to reset. */ | ||
1619 | } | ||
1620 | |||
1621 | if (isci_dev->isci_port != NULL) | ||
1622 | isci_host = isci_dev->isci_port->isci_host; | ||
1623 | |||
1624 | if (isci_host != NULL) | ||
1625 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
1626 | |||
1627 | status = scic_remote_device_reset(isci_dev->sci_device_handle); | ||
1628 | if (status != SCI_SUCCESS) { | ||
1629 | |||
1630 | if (isci_host != NULL) | ||
1631 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
1632 | |||
1633 | scmd_printk(KERN_WARNING, cmd, | ||
1634 | "%s: scic_remote_device_reset(%p) returned %d!\n", | ||
1635 | __func__, isci_dev, status); | ||
1636 | |||
1637 | return TMF_RESP_FUNC_FAILED; | ||
1638 | } | ||
1639 | if (isci_host != NULL) | ||
1640 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
1641 | |||
1642 | /* Stop I/O to the remote device. */ | ||
1643 | isci_device_set_host_quiesce_lock_state(isci_dev, true); | ||
1644 | |||
1645 | /* Make sure all pending requests are able to be fully terminated. */ | ||
1646 | isci_device_clear_reset_pending(isci_dev); | ||
1647 | |||
1648 | /* Terminate in-progress I/O now. */ | ||
1649 | isci_remote_device_nuke_requests(isci_dev); | ||
1650 | |||
1651 | /* Call into the libsas default handler (which calls sas_phy_reset). */ | ||
1652 | base_status = sas_eh_bus_reset_handler(cmd); | ||
1653 | |||
1654 | if (base_status != SUCCESS) { | ||
1655 | |||
1656 | /* There can be cases where the resets to individual devices | ||
1657 | * behind an expander will fail because of an unplug of the | ||
1658 | * expander itself. | ||
1659 | */ | ||
1660 | scmd_printk(KERN_WARNING, cmd, | ||
1661 | "%s: sas_eh_bus_reset_handler(%p) returned %d!\n", | ||
1662 | __func__, cmd, base_status); | ||
1663 | } | ||
1664 | |||
1665 | /* WHAT TO DO HERE IF sas_phy_reset FAILS? */ | ||
1666 | |||
1667 | if (isci_host != NULL) | ||
1668 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
1669 | status | ||
1670 | = scic_remote_device_reset_complete(isci_dev->sci_device_handle); | ||
1671 | |||
1672 | if (isci_host != NULL) | ||
1673 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
1674 | |||
1675 | if (status != SCI_SUCCESS) { | ||
1676 | scmd_printk(KERN_WARNING, cmd, | ||
1677 | "%s: scic_remote_device_reset_complete(%p) " | ||
1678 | "returned %d!\n", | ||
1679 | __func__, isci_dev, status); | ||
1680 | } | ||
1681 | /* WHAT TO DO HERE IF scic_remote_device_reset_complete FAILS? */ | ||
1682 | |||
1683 | dev_dbg(&cmd->device->sdev_gendev, | ||
1684 | "%s: cmd %p, isci_dev %p complete.\n", | ||
1685 | __func__, cmd, isci_dev); | ||
1686 | |||
1687 | /* Resume I/O to the remote device. */ | ||
1688 | isci_device_set_host_quiesce_lock_state(isci_dev, false); | ||
1689 | |||
1690 | return TMF_RESP_FUNC_COMPLETE; | ||
1691 | } | ||
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h new file mode 100644 index 000000000000..ced6a8be1b31 --- /dev/null +++ b/drivers/scsi/isci/task.h | |||
@@ -0,0 +1,368 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #if !defined(_ISCI_TASK_H_) | ||
57 | #define _ISCI_TASK_H_ | ||
58 | |||
59 | struct isci_request; | ||
60 | struct isci_host; | ||
61 | |||
62 | /** | ||
63 | * enum isci_tmf_cb_state - This enum defines the possible states in which the | ||
64 | * TMF callback function is invoked during the TMF execution process. | ||
65 | * | ||
66 | * | ||
67 | */ | ||
68 | enum isci_tmf_cb_state { | ||
69 | |||
70 | isci_tmf_init_state = 0, | ||
71 | isci_tmf_started, | ||
72 | isci_tmf_timed_out | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * enum isci_tmf_function_codes - This enum defines the possible preparations | ||
77 | * of task management requests. | ||
78 | * | ||
79 | * | ||
80 | */ | ||
81 | enum isci_tmf_function_codes { | ||
82 | |||
83 | isci_tmf_func_none = 0, | ||
84 | isci_tmf_ssp_task_abort = TMF_ABORT_TASK, | ||
85 | isci_tmf_ssp_lun_reset = TMF_LU_RESET, | ||
86 | isci_tmf_sata_srst_high = TMF_LU_RESET + 0x100, /* Non SCSI */ | ||
87 | isci_tmf_sata_srst_low = TMF_LU_RESET + 0x101 /* Non SCSI */ | ||
88 | }; | ||
89 | /** | ||
90 | * struct isci_tmf - This class represents the task management object which | ||
91 | * acts as an interface to libsas for processing task management requests | ||
92 | * | ||
93 | * | ||
94 | */ | ||
95 | struct isci_tmf { | ||
96 | |||
97 | struct completion *complete; | ||
98 | enum sas_protocol proto; | ||
99 | union { | ||
100 | struct sci_ssp_response_iu resp_iu; | ||
101 | struct dev_to_host_fis d2h_fis; | ||
102 | } resp; | ||
103 | unsigned char lun[8]; | ||
104 | u16 io_tag; | ||
105 | struct isci_remote_device *device; | ||
106 | enum isci_tmf_function_codes tmf_code; | ||
107 | int status; | ||
108 | |||
109 | struct isci_timer *timeout_timer; | ||
110 | |||
111 | /* The optional callback function allows the user process to | ||
112 | * track the TMF transmit / timeout conditions. | ||
113 | */ | ||
114 | void (*cb_state_func)( | ||
115 | enum isci_tmf_cb_state, | ||
116 | struct isci_tmf *, void *); | ||
117 | void *cb_data; | ||
118 | |||
119 | }; | ||
120 | |||
121 | static inline void isci_print_tmf( | ||
122 | struct isci_tmf *tmf) | ||
123 | { | ||
124 | if (SAS_PROTOCOL_SATA == tmf->proto) | ||
125 | dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev, | ||
126 | "%s: status = %x\n" | ||
127 | "tmf->resp.d2h_fis.status = %x\n" | ||
128 | "tmf->resp.d2h_fis.error = %x\n", | ||
129 | __func__, | ||
130 | tmf->status, | ||
131 | tmf->resp.d2h_fis.status, | ||
132 | tmf->resp.d2h_fis.error); | ||
133 | else | ||
134 | dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev, | ||
135 | "%s: status = %x\n" | ||
136 | "tmf->resp.resp_iu.data_present = %x\n" | ||
137 | "tmf->resp.resp_iu.status = %x\n" | ||
138 | "tmf->resp.resp_iu.data_length = %x\n" | ||
139 | "tmf->resp.resp_iu.data[0] = %x\n" | ||
140 | "tmf->resp.resp_iu.data[1] = %x\n" | ||
141 | "tmf->resp.resp_iu.data[2] = %x\n" | ||
142 | "tmf->resp.resp_iu.data[3] = %x\n", | ||
143 | __func__, | ||
144 | tmf->status, | ||
145 | tmf->resp.resp_iu.data_present, | ||
146 | tmf->resp.resp_iu.status, | ||
147 | (tmf->resp.resp_iu.response_data_length[0] << 24) + | ||
148 | (tmf->resp.resp_iu.response_data_length[1] << 16) + | ||
149 | (tmf->resp.resp_iu.response_data_length[2] << 8) + | ||
150 | tmf->resp.resp_iu.response_data_length[3], | ||
151 | tmf->resp.resp_iu.data[0], | ||
152 | tmf->resp.resp_iu.data[1], | ||
153 | tmf->resp.resp_iu.data[2], | ||
154 | tmf->resp.resp_iu.data[3]); | ||
155 | } | ||
156 | |||
157 | |||
158 | int isci_task_execute_task( | ||
159 | struct sas_task *task, | ||
160 | int num, | ||
161 | gfp_t gfp_flags); | ||
162 | |||
163 | int isci_task_abort_task( | ||
164 | struct sas_task *task); | ||
165 | |||
166 | int isci_task_abort_task_set( | ||
167 | struct domain_device *d_device, | ||
168 | u8 *lun); | ||
169 | |||
170 | int isci_task_clear_aca( | ||
171 | struct domain_device *d_device, | ||
172 | u8 *lun); | ||
173 | |||
174 | int isci_task_clear_task_set( | ||
175 | struct domain_device *d_device, | ||
176 | u8 *lun); | ||
177 | |||
178 | int isci_task_query_task( | ||
179 | struct sas_task *task); | ||
180 | |||
181 | int isci_task_lu_reset( | ||
182 | struct domain_device *d_device, | ||
183 | u8 *lun); | ||
184 | |||
185 | int isci_task_clear_nexus_port( | ||
186 | struct asd_sas_port *port); | ||
187 | |||
188 | int isci_task_clear_nexus_ha( | ||
189 | struct sas_ha_struct *ha); | ||
190 | |||
191 | int isci_task_I_T_nexus_reset( | ||
192 | struct domain_device *d_device); | ||
193 | |||
194 | void isci_task_request_complete( | ||
195 | struct isci_host *isci_host, | ||
196 | struct isci_request *request, | ||
197 | enum sci_task_status completion_status); | ||
198 | |||
199 | u16 isci_task_ssp_request_get_io_tag_to_manage( | ||
200 | struct isci_request *request); | ||
201 | |||
202 | u8 isci_task_ssp_request_get_function( | ||
203 | struct isci_request *request); | ||
204 | |||
205 | u32 isci_task_ssp_request_get_lun( | ||
206 | struct isci_request *request); | ||
207 | |||
208 | void *isci_task_ssp_request_get_response_data_address( | ||
209 | struct isci_request *request); | ||
210 | |||
211 | u32 isci_task_ssp_request_get_response_data_length( | ||
212 | struct isci_request *request); | ||
213 | |||
214 | int isci_queuecommand( | ||
215 | struct scsi_cmnd *scsi_cmd, | ||
216 | void (*donefunc)(struct scsi_cmnd *)); | ||
217 | |||
218 | int isci_bus_reset_handler(struct scsi_cmnd *cmd); | ||
219 | |||
220 | void isci_task_build_tmf( | ||
221 | struct isci_tmf *tmf, | ||
222 | struct isci_remote_device *isci_device, | ||
223 | enum isci_tmf_function_codes code, | ||
224 | void (*tmf_sent_cb)( | ||
225 | enum isci_tmf_cb_state, | ||
226 | struct isci_tmf *, void *), | ||
227 | void *cb_data); | ||
228 | |||
229 | int isci_task_execute_tmf( | ||
230 | struct isci_host *isci_host, | ||
231 | struct isci_tmf *tmf, | ||
232 | unsigned long timeout_ms); | ||
233 | |||
234 | /** | ||
235 | * enum isci_completion_selection - This enum defines the possible actions to | ||
236 | * take with respect to a given request's notification back to libsas. | ||
237 | * | ||
238 | * | ||
239 | */ | ||
240 | enum isci_completion_selection { | ||
241 | |||
242 | isci_perform_normal_io_completion, /* Normal notify (task_done) */ | ||
243 | isci_perform_aborted_io_completion, /* No notification. */ | ||
244 | isci_perform_error_io_completion /* Use sas_task_abort */ | ||
245 | }; | ||
246 | |||
247 | static inline void isci_set_task_doneflags( | ||
248 | struct sas_task *task) | ||
249 | { | ||
250 | /* Since no futher action will be taken on this task, | ||
251 | * make sure to mark it complete from the lldd perspective. | ||
252 | */ | ||
253 | task->task_state_flags |= SAS_TASK_STATE_DONE; | ||
254 | task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
255 | task->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
256 | } | ||
257 | /** | ||
258 | * isci_task_all_done() - This function clears the task bits to indicate the | ||
259 | * LLDD is done with the task. | ||
260 | * | ||
261 | * | ||
262 | */ | ||
263 | static inline void isci_task_all_done( | ||
264 | struct sas_task *task) | ||
265 | { | ||
266 | unsigned long flags; | ||
267 | |||
268 | /* Since no futher action will be taken on this task, | ||
269 | * make sure to mark it complete from the lldd perspective. | ||
270 | */ | ||
271 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
272 | isci_set_task_doneflags(task); | ||
273 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * isci_task_set_completion_status() - This function sets the completion status | ||
278 | * for the request. | ||
279 | * @task: This parameter is the completed request. | ||
280 | * @response: This parameter is the response code for the completed task. | ||
281 | * @status: This parameter is the status code for the completed task. | ||
282 | * | ||
283 | * none. | ||
284 | */ | ||
285 | static inline void isci_task_set_completion_status( | ||
286 | struct sas_task *task, | ||
287 | enum service_response response, | ||
288 | enum exec_status status, | ||
289 | enum isci_completion_selection task_notification_selection) | ||
290 | { | ||
291 | unsigned long flags; | ||
292 | |||
293 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
294 | |||
295 | task->task_status.resp = response; | ||
296 | task->task_status.stat = status; | ||
297 | |||
298 | /* Don't set DONE (or clear AT_INITIATOR) for any task going into the | ||
299 | * error path, because the EH interprets that as a handled error condition. | ||
300 | * Also don't take action if there is a reset pending. | ||
301 | */ | ||
302 | if ((task_notification_selection != isci_perform_error_io_completion) | ||
303 | && !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET)) | ||
304 | isci_set_task_doneflags(task); | ||
305 | |||
306 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
307 | } | ||
308 | /** | ||
309 | * isci_task_complete_for_upper_layer() - This function completes the request | ||
310 | * to the upper layer driver. | ||
311 | * @host: This parameter is a pointer to the host on which the the request | ||
312 | * should be queued (either as an error or success). | ||
313 | * @request: This parameter is the completed request. | ||
314 | * @response: This parameter is the response code for the completed task. | ||
315 | * @status: This parameter is the status code for the completed task. | ||
316 | * | ||
317 | * none. | ||
318 | */ | ||
319 | static inline void isci_task_complete_for_upper_layer( | ||
320 | struct sas_task *task, | ||
321 | enum service_response response, | ||
322 | enum exec_status status, | ||
323 | enum isci_completion_selection task_notification_selection) | ||
324 | { | ||
325 | isci_task_set_completion_status(task, response, status, | ||
326 | task_notification_selection); | ||
327 | |||
328 | |||
329 | /* Tasks aborted specifically by a call to the lldd_abort_task | ||
330 | * function should not be completed to the host in the regular path. | ||
331 | */ | ||
332 | switch (task_notification_selection) { | ||
333 | case isci_perform_normal_io_completion: | ||
334 | /* Normal notification (task_done) */ | ||
335 | dev_dbg(task->dev->port->ha->dev, | ||
336 | "%s: Normal - task = %p, response=%d, status=%d\n", | ||
337 | __func__, task, response, status); | ||
338 | task->task_done(task); | ||
339 | task->lldd_task = NULL; | ||
340 | break; | ||
341 | |||
342 | case isci_perform_aborted_io_completion: | ||
343 | /* No notification because this request is already in the | ||
344 | * abort path. | ||
345 | */ | ||
346 | dev_warn(task->dev->port->ha->dev, | ||
347 | "%s: Aborted - task = %p, response=%d, status=%d\n", | ||
348 | __func__, task, response, status); | ||
349 | break; | ||
350 | |||
351 | case isci_perform_error_io_completion: | ||
352 | /* Use sas_task_abort */ | ||
353 | dev_warn(task->dev->port->ha->dev, | ||
354 | "%s: Error - task = %p, response=%d, status=%d\n", | ||
355 | __func__, task, response, status); | ||
356 | sas_task_abort(task); | ||
357 | break; | ||
358 | |||
359 | default: | ||
360 | dev_warn(task->dev->port->ha->dev, | ||
361 | "%s: isci task notification default case!", | ||
362 | __func__); | ||
363 | sas_task_abort(task); | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | #endif /* !defined(_SCI_TASK_H_) */ | ||
diff --git a/drivers/scsi/isci/timers.c b/drivers/scsi/isci/timers.c new file mode 100644 index 000000000000..ca723089ee88 --- /dev/null +++ b/drivers/scsi/isci/timers.c | |||
@@ -0,0 +1,319 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #include "isci.h" | ||
57 | #include "timers.h" | ||
58 | |||
59 | |||
60 | /** | ||
61 | * isci_timer_list_construct() - This method contrucst the SCI Timer List | ||
62 | * object used by the SCI Module class. The construction process involves | ||
63 | * creating isci_timer objects and adding them to the SCI Timer List | ||
64 | * object's list member. The number of isci_timer objects is determined by | ||
65 | * the timer_list_size parameter. | ||
66 | * @isci_timer_list: This parameter points to the SCI Timer List object being | ||
67 | * constructed. The calling routine is responsible for allocating the memory | ||
68 | * for isci_timer_list and initializing the timer list_head member of | ||
69 | * isci_timer_list. | ||
70 | * @timer_list_size: This parameter specifies the number of isci_timer objects | ||
71 | * contained by the SCI Timer List. which this timer is to be associated. | ||
72 | * | ||
73 | * This method returns an error code indicating sucess or failure. The user | ||
74 | * should check for possible memory allocation error return otherwise, a zero | ||
75 | * indicates success. | ||
76 | */ | ||
77 | int isci_timer_list_construct( | ||
78 | struct isci_timer_list *isci_timer_list, | ||
79 | int timer_list_size) | ||
80 | { | ||
81 | struct isci_timer *isci_timer; | ||
82 | int i; | ||
83 | int err = 0; | ||
84 | |||
85 | |||
86 | for (i = 0; i < timer_list_size; i++) { | ||
87 | |||
88 | isci_timer = kzalloc(sizeof(*isci_timer), GFP_KERNEL); | ||
89 | |||
90 | if (!isci_timer) { | ||
91 | |||
92 | err = -ENOMEM; | ||
93 | break; | ||
94 | } | ||
95 | isci_timer->used = 0; | ||
96 | isci_timer->stopped = 1; | ||
97 | isci_timer->parent = isci_timer_list; | ||
98 | list_add(&isci_timer->node, &isci_timer_list->timers); | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | |||
103 | } | ||
104 | |||
105 | |||
106 | /** | ||
107 | * isci_timer_list_destroy() - This method destroys the SCI Timer List object | ||
108 | * used by the SCI Module class. The destruction process involves freeing | ||
109 | * memory allocated for isci_timer objects on the SCI Timer List object's | ||
110 | * timers list_head member. If any isci_timer objects are mark as "in use", | ||
111 | * they are not freed and the function returns an error code of -EBUSY. | ||
112 | * @isci_timer_list: This parameter points to the SCI Timer List object being | ||
113 | * destroyed. | ||
114 | * | ||
115 | * This method returns an error code indicating sucess or failure. The user | ||
116 | * should check for possible -EBUSY error return, in the event of one or more | ||
117 | * isci_timers still "in use", otherwise, a zero indicates success. | ||
118 | */ | ||
119 | int isci_timer_list_destroy( | ||
120 | struct isci_timer_list *isci_timer_list) | ||
121 | { | ||
122 | struct isci_timer *timer, *tmp; | ||
123 | |||
124 | list_for_each_entry_safe(timer, tmp, &isci_timer_list->timers, node) { | ||
125 | isci_timer_free(isci_timer_list, timer); | ||
126 | list_del(&timer->node); | ||
127 | kfree(timer); | ||
128 | } | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | |||
133 | |||
134 | static void isci_timer_restart(struct isci_timer *isci_timer) | ||
135 | { | ||
136 | struct timer_list *timer = | ||
137 | &isci_timer->timer; | ||
138 | unsigned long timeout; | ||
139 | |||
140 | dev_dbg(&isci_timer->isci_host->pdev->dev, | ||
141 | "%s: isci_timer = %p\n", __func__, isci_timer); | ||
142 | |||
143 | isci_timer->restart = 0; | ||
144 | isci_timer->stopped = 0; | ||
145 | timeout = isci_timer->timeout_value; | ||
146 | timeout = (timeout * HZ) / 1000; | ||
147 | timeout = timeout ? timeout : 1; | ||
148 | mod_timer(timer, jiffies + timeout); | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * This method pulls an isci_timer object off of the list for the SCI Timer | ||
153 | * List object specified, marks the isci_timer as "in use" and initializes | ||
154 | * it with user callback function and cookie data. The timer is not start at | ||
155 | * this time, just reserved for the user. | ||
156 | * @isci_timer_list: This parameter points to the SCI Timer List from which the | ||
157 | * timer is reserved. | ||
158 | * @cookie: This parameter specifies a piece of information that the user must | ||
159 | * retain. This cookie is to be supplied by the user anytime a timeout | ||
160 | * occurs for the created timer. | ||
161 | * @timer_callback: This parameter specifies the callback method to be invoked | ||
162 | * whenever the timer expires. | ||
163 | * | ||
164 | * This method returns a pointer to an isci_timer object reserved from the SCI | ||
165 | * Timer List. The pointer will be utilized for all further interactions | ||
166 | * relating to this timer. | ||
167 | */ | ||
168 | |||
169 | static void timer_function(unsigned long data) | ||
170 | { | ||
171 | |||
172 | struct isci_timer *timer = (struct isci_timer *)data; | ||
173 | struct isci_host *isci_host = timer->isci_host; | ||
174 | unsigned long flags; | ||
175 | |||
176 | dev_dbg(&isci_host->pdev->dev, | ||
177 | "%s: isci_timer = %p\n", __func__, timer); | ||
178 | |||
179 | if (isci_stopped == isci_host_get_state(isci_host)) { | ||
180 | timer->stopped = 1; | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
185 | |||
186 | if (!timer->stopped) { | ||
187 | timer->stopped = 1; | ||
188 | timer->timer_callback(timer->cookie); | ||
189 | |||
190 | if (timer->restart) | ||
191 | isci_timer_restart(timer); | ||
192 | } | ||
193 | |||
194 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
195 | } | ||
196 | |||
197 | |||
198 | struct isci_timer *isci_timer_create( | ||
199 | struct isci_timer_list *isci_timer_list, | ||
200 | struct isci_host *isci_host, | ||
201 | void *cookie, | ||
202 | void (*timer_callback)(void *)) | ||
203 | { | ||
204 | |||
205 | struct timer_list *timer; | ||
206 | struct isci_timer *isci_timer; | ||
207 | struct list_head *timer_list = | ||
208 | &isci_timer_list->timers; | ||
209 | unsigned long flags; | ||
210 | |||
211 | spin_lock_irqsave(&isci_host->scic_lock, flags); | ||
212 | |||
213 | if (list_empty(timer_list)) { | ||
214 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | isci_timer = list_entry(timer_list->next, struct isci_timer, node); | ||
219 | |||
220 | if (isci_timer->used) { | ||
221 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
222 | return NULL; | ||
223 | } | ||
224 | isci_timer->used = 1; | ||
225 | isci_timer->stopped = 1; | ||
226 | list_move_tail(&isci_timer->node, timer_list); | ||
227 | |||
228 | spin_unlock_irqrestore(&isci_host->scic_lock, flags); | ||
229 | |||
230 | timer = &isci_timer->timer; | ||
231 | timer->data = (unsigned long)isci_timer; | ||
232 | timer->function = timer_function; | ||
233 | isci_timer->cookie = cookie; | ||
234 | isci_timer->timer_callback = timer_callback; | ||
235 | isci_timer->isci_host = isci_host; | ||
236 | |||
237 | dev_dbg(&isci_host->pdev->dev, | ||
238 | "%s: isci_timer = %p\n", __func__, isci_timer); | ||
239 | |||
240 | return isci_timer; | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * isci_timer_free() - This method frees the isci_timer, marking it "free to | ||
245 | * use", then places its back at the head of the timers list for the SCI | ||
246 | * Timer List object specified. | ||
247 | * @isci_timer_list: This parameter points to the SCI Timer List from which the | ||
248 | * timer is reserved. | ||
249 | * @isci_timer: This parameter specifies the timer to be freed. | ||
250 | * | ||
251 | */ | ||
252 | void isci_timer_free( | ||
253 | struct isci_timer_list *isci_timer_list, | ||
254 | struct isci_timer *isci_timer) | ||
255 | { | ||
256 | struct list_head *timer_list = &isci_timer_list->timers; | ||
257 | |||
258 | dev_dbg(&isci_timer->isci_host->pdev->dev, | ||
259 | "%s: isci_timer = %p\n", __func__, isci_timer); | ||
260 | |||
261 | if (list_empty(timer_list)) | ||
262 | return; | ||
263 | |||
264 | isci_timer->used = 0; | ||
265 | list_move(&isci_timer->node, timer_list); | ||
266 | |||
267 | if (!isci_timer->stopped) { | ||
268 | del_timer(&isci_timer->timer); | ||
269 | isci_timer->stopped = 1; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * isci_timer_start() - This method starts the specified isci_timer, with the | ||
275 | * specified timeout value. | ||
276 | * @isci_timer: This parameter specifies the timer to be started. | ||
277 | * @timeout: This parameter specifies the timeout, in milliseconds, after which | ||
278 | * the associated callback function will be called. | ||
279 | * | ||
280 | */ | ||
281 | void isci_timer_start( | ||
282 | struct isci_timer *isci_timer, | ||
283 | unsigned long timeout) | ||
284 | { | ||
285 | struct timer_list *timer = &isci_timer->timer; | ||
286 | |||
287 | dev_dbg(&isci_timer->isci_host->pdev->dev, | ||
288 | "%s: isci_timer = %p\n", __func__, isci_timer); | ||
289 | |||
290 | isci_timer->timeout_value = timeout; | ||
291 | init_timer(timer); | ||
292 | timeout = (timeout * HZ) / 1000; | ||
293 | timeout = timeout ? timeout : 1; | ||
294 | |||
295 | timer->expires = jiffies + timeout; | ||
296 | timer->data = (unsigned long)isci_timer; | ||
297 | timer->function = timer_function; | ||
298 | isci_timer->stopped = 0; | ||
299 | isci_timer->restart = 0; | ||
300 | add_timer(timer); | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * isci_timer_stop() - This method stops the supplied isci_timer. | ||
305 | * @isci_timer: This parameter specifies the isci_timer to be stopped. | ||
306 | * | ||
307 | */ | ||
308 | void isci_timer_stop(struct isci_timer *isci_timer) | ||
309 | { | ||
310 | dev_dbg(&isci_timer->isci_host->pdev->dev, | ||
311 | "%s: isci_timer = %p\n", __func__, isci_timer); | ||
312 | |||
313 | if (isci_timer->stopped) | ||
314 | return; | ||
315 | |||
316 | isci_timer->stopped = 1; | ||
317 | |||
318 | del_timer(&isci_timer->timer); | ||
319 | } | ||
diff --git a/drivers/scsi/isci/timers.h b/drivers/scsi/isci/timers.h new file mode 100644 index 000000000000..ca5c2159a1c2 --- /dev/null +++ b/drivers/scsi/isci/timers.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
3 | * redistributing this file, you may do so under either license. | ||
4 | * | ||
5 | * GPL LICENSE SUMMARY | ||
6 | * | ||
7 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of version 2 of the GNU General Public License as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * BSD LICENSE | ||
25 | * | ||
26 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * | ||
33 | * * Redistributions of source code must retain the above copyright | ||
34 | * notice, this list of conditions and the following disclaimer. | ||
35 | * * Redistributions in binary form must reproduce the above copyright | ||
36 | * notice, this list of conditions and the following disclaimer in | ||
37 | * the documentation and/or other materials provided with the | ||
38 | * distribution. | ||
39 | * * Neither the name of Intel Corporation nor the names of its | ||
40 | * contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
44 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
45 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
46 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
47 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
48 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
49 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
53 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
54 | */ | ||
55 | |||
56 | #if !defined(_SCI_TIMER_H_) | ||
57 | #define _SCI_TIMER_H_ | ||
58 | |||
59 | #include <linux/timer.h> | ||
60 | #include <linux/types.h> | ||
61 | |||
62 | /*************************************************** | ||
63 | * isci_timer | ||
64 | *************************************************** | ||
65 | */ | ||
66 | /** | ||
67 | * struct isci_timer_list - This class is the container for all isci_timer | ||
68 | * objects | ||
69 | * | ||
70 | * | ||
71 | */ | ||
72 | struct isci_timer_list { | ||
73 | |||
74 | struct list_head timers; | ||
75 | }; | ||
76 | |||
77 | /** | ||
78 | * struct isci_timer - This class represents the timer object used by SCIC. It | ||
79 | * wraps the Linux timer_list object. | ||
80 | * | ||
81 | * | ||
82 | */ | ||
83 | struct isci_timer { | ||
84 | int used; | ||
85 | int stopped; | ||
86 | int restart; | ||
87 | int timeout_value; | ||
88 | void *cookie; | ||
89 | void (*timer_callback)(void *); | ||
90 | struct list_head node; | ||
91 | struct timer_list timer; | ||
92 | struct isci_timer_list *parent; | ||
93 | struct isci_host *isci_host; | ||
94 | }; | ||
95 | |||
96 | #define to_isci_timer(t) \ | ||
97 | container_of(t, struct isci_timer, timer); | ||
98 | |||
99 | int isci_timer_list_construct( | ||
100 | struct isci_timer_list *isci_timer_list, | ||
101 | int timer_list_size); | ||
102 | |||
103 | |||
104 | int isci_timer_list_destroy( | ||
105 | struct isci_timer_list *isci_timer_list); | ||
106 | |||
107 | struct isci_timer *isci_timer_create( | ||
108 | struct isci_timer_list *isci_timer_list, | ||
109 | struct isci_host *isci_host, | ||
110 | void *cookie, | ||
111 | void (*timer_callback)(void *)); | ||
112 | |||
113 | void isci_timer_free( | ||
114 | struct isci_timer_list *isci_timer_list, | ||
115 | struct isci_timer *isci_timer); | ||
116 | |||
117 | void isci_timer_start( | ||
118 | struct isci_timer *isci_timer, | ||
119 | unsigned long timeout); | ||
120 | |||
121 | void isci_timer_stop( | ||
122 | struct isci_timer *isci_timer); | ||
123 | |||
124 | |||
125 | #endif /* !defined (_SCI_TIMER_H_) */ | ||
126 | |||
diff --git a/firmware/Makefile b/firmware/Makefile index 0d15a3d113a2..5f43bfba3c7a 100644 --- a/firmware/Makefile +++ b/firmware/Makefile | |||
@@ -82,6 +82,7 @@ fw-shipped-$(CONFIG_SERIAL_8250_CS) += cis/MT5634ZLX.cis cis/RS-COM-2P.cis \ | |||
82 | fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin | 82 | fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin |
83 | fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \ | 83 | fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \ |
84 | advansys/3550.bin advansys/38C0800.bin | 84 | advansys/3550.bin advansys/38C0800.bin |
85 | fw-shipped-$(CONFIG_SCSI_ISCI) += isci/isci_firmware.bin | ||
85 | fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \ | 86 | fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \ |
86 | qlogic/12160.bin | 87 | qlogic/12160.bin |
87 | fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin | 88 | fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin |
diff --git a/firmware/isci/isci_firmware.bin.ihex b/firmware/isci/isci_firmware.bin.ihex new file mode 100644 index 000000000000..9fc9e60f399c --- /dev/null +++ b/firmware/isci/isci_firmware.bin.ihex | |||
@@ -0,0 +1,11 @@ | |||
1 | :1000000023534355204D4147494323000100010834 | ||
2 | :1000100001000000020000000400000008000000D1 | ||
3 | :1000200001000000020000000400000008000000C1 | ||
4 | :1000300002080300000003000000030000000300AA | ||
5 | :1000400000000300000003000000030000000300A4 | ||
6 | :1000500000000308000000F0FFFFCF5F000000F188 | ||
7 | :10006000FFFFCF5F000000F2FFFFCF5F000000F353 | ||
8 | :10007000FFFFCF5F000000F4FFFFCF5F000000F53F | ||
9 | :10008000FFFFCF5F000000F6FFFFCF5F000000F72B | ||
10 | :05009000FFFFCF5FFF40 | ||
11 | :00000001FF | ||