diff options
Diffstat (limited to 'drivers/scsi/pm8001/pm80xx_hwi.c')
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 523 |
1 files changed, 492 insertions, 31 deletions
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9f91030211e8..8987b1706216 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
@@ -45,6 +45,228 @@ | |||
45 | 45 | ||
46 | #define SMP_DIRECT 1 | 46 | #define SMP_DIRECT 1 |
47 | #define SMP_INDIRECT 2 | 47 | #define SMP_INDIRECT 2 |
48 | |||
49 | |||
50 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value) | ||
51 | { | ||
52 | u32 reg_val; | ||
53 | unsigned long start; | ||
54 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, shift_value); | ||
55 | /* confirm the setting is written */ | ||
56 | start = jiffies + HZ; /* 1 sec */ | ||
57 | do { | ||
58 | reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER); | ||
59 | } while ((reg_val != shift_value) && time_before(jiffies, start)); | ||
60 | if (reg_val != shift_value) { | ||
61 | PM8001_FAIL_DBG(pm8001_ha, | ||
62 | pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" | ||
63 | " = 0x%x\n", reg_val)); | ||
64 | return -1; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset, | ||
70 | const void *destination, | ||
71 | u32 dw_count, u32 bus_base_number) | ||
72 | { | ||
73 | u32 index, value, offset; | ||
74 | u32 *destination1; | ||
75 | destination1 = (u32 *)destination; | ||
76 | |||
77 | for (index = 0; index < dw_count; index += 4, destination1++) { | ||
78 | offset = (soffset + index / 4); | ||
79 | if (offset < (64 * 1024)) { | ||
80 | value = pm8001_cr32(pm8001_ha, bus_base_number, offset); | ||
81 | *destination1 = cpu_to_le32(value); | ||
82 | } | ||
83 | } | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, | ||
88 | struct device_attribute *attr, char *buf) | ||
89 | { | ||
90 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
91 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | ||
92 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | ||
93 | void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr; | ||
94 | u32 status = 1; | ||
95 | u32 accum_len , reg_val, index, *temp; | ||
96 | unsigned long start; | ||
97 | u8 *direct_data; | ||
98 | char *fatal_error_data = buf; | ||
99 | |||
100 | pm8001_ha->forensic_info.data_buf.direct_data = buf; | ||
101 | if (pm8001_ha->chip_id == chip_8001) { | ||
102 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
103 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
104 | "Not supported for SPC controller"); | ||
105 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
106 | (char *)buf; | ||
107 | } | ||
108 | if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { | ||
109 | PM8001_IO_DBG(pm8001_ha, | ||
110 | pm8001_printk("forensic_info TYPE_NON_FATAL..............\n")); | ||
111 | direct_data = (u8 *)fatal_error_data; | ||
112 | pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL; | ||
113 | pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET; | ||
114 | pm8001_ha->forensic_info.data_buf.direct_offset = 0; | ||
115 | pm8001_ha->forensic_info.data_buf.read_len = 0; | ||
116 | |||
117 | pm8001_ha->forensic_info.data_buf.direct_data = direct_data; | ||
118 | } | ||
119 | |||
120 | if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { | ||
121 | /* start to get data */ | ||
122 | /* Program the MEMBASE II Shifting Register with 0x00.*/ | ||
123 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
124 | pm8001_ha->fatal_forensic_shift_offset); | ||
125 | pm8001_ha->forensic_last_offset = 0; | ||
126 | pm8001_ha->forensic_fatal_step = 0; | ||
127 | pm8001_ha->fatal_bar_loc = 0; | ||
128 | } | ||
129 | /* Read until accum_len is retrived */ | ||
130 | accum_len = pm8001_mr32(fatal_table_address, | ||
131 | MPI_FATAL_EDUMP_TABLE_ACCUM_LEN); | ||
132 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n", | ||
133 | accum_len)); | ||
134 | if (accum_len == 0xFFFFFFFF) { | ||
135 | PM8001_IO_DBG(pm8001_ha, | ||
136 | pm8001_printk("Possible PCI issue 0x%x not expected\n", | ||
137 | accum_len)); | ||
138 | return status; | ||
139 | } | ||
140 | if (accum_len == 0 || accum_len >= 0x100000) { | ||
141 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
142 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
143 | "%08x ", 0xFFFFFFFF); | ||
144 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
145 | (char *)buf; | ||
146 | } | ||
147 | temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr; | ||
148 | if (pm8001_ha->forensic_fatal_step == 0) { | ||
149 | moreData: | ||
150 | if (pm8001_ha->forensic_info.data_buf.direct_data) { | ||
151 | /* Data is in bar, copy to host memory */ | ||
152 | pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc, | ||
153 | pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr, | ||
154 | pm8001_ha->forensic_info.data_buf.direct_len , | ||
155 | 1); | ||
156 | } | ||
157 | pm8001_ha->fatal_bar_loc += | ||
158 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
159 | pm8001_ha->forensic_info.data_buf.direct_offset += | ||
160 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
161 | pm8001_ha->forensic_last_offset += | ||
162 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
163 | pm8001_ha->forensic_info.data_buf.read_len = | ||
164 | pm8001_ha->forensic_info.data_buf.direct_len; | ||
165 | |||
166 | if (pm8001_ha->forensic_last_offset >= accum_len) { | ||
167 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
168 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
169 | "%08x ", 3); | ||
170 | for (index = 0; index < (SYSFS_OFFSET / 4); index++) { | ||
171 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
172 | sprintf(pm8001_ha-> | ||
173 | forensic_info.data_buf.direct_data, | ||
174 | "%08x ", *(temp + index)); | ||
175 | } | ||
176 | |||
177 | pm8001_ha->fatal_bar_loc = 0; | ||
178 | pm8001_ha->forensic_fatal_step = 1; | ||
179 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
180 | pm8001_ha->forensic_last_offset = 0; | ||
181 | status = 0; | ||
182 | return (char *)pm8001_ha-> | ||
183 | forensic_info.data_buf.direct_data - | ||
184 | (char *)buf; | ||
185 | } | ||
186 | if (pm8001_ha->fatal_bar_loc < (64 * 1024)) { | ||
187 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
188 | sprintf(pm8001_ha-> | ||
189 | forensic_info.data_buf.direct_data, | ||
190 | "%08x ", 2); | ||
191 | for (index = 0; index < (SYSFS_OFFSET / 4); index++) { | ||
192 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
193 | sprintf(pm8001_ha-> | ||
194 | forensic_info.data_buf.direct_data, | ||
195 | "%08x ", *(temp + index)); | ||
196 | } | ||
197 | status = 0; | ||
198 | return (char *)pm8001_ha-> | ||
199 | forensic_info.data_buf.direct_data - | ||
200 | (char *)buf; | ||
201 | } | ||
202 | |||
203 | /* Increment the MEMBASE II Shifting Register value by 0x100.*/ | ||
204 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
205 | sprintf(pm8001_ha->forensic_info.data_buf.direct_data, | ||
206 | "%08x ", 2); | ||
207 | for (index = 0; index < 256; index++) { | ||
208 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
209 | sprintf(pm8001_ha-> | ||
210 | forensic_info.data_buf.direct_data, | ||
211 | "%08x ", *(temp + index)); | ||
212 | } | ||
213 | pm8001_ha->fatal_forensic_shift_offset += 0x100; | ||
214 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
215 | pm8001_ha->fatal_forensic_shift_offset); | ||
216 | pm8001_ha->fatal_bar_loc = 0; | ||
217 | status = 0; | ||
218 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
219 | (char *)buf; | ||
220 | } | ||
221 | if (pm8001_ha->forensic_fatal_step == 1) { | ||
222 | pm8001_ha->fatal_forensic_shift_offset = 0; | ||
223 | /* Read 64K of the debug data. */ | ||
224 | pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, | ||
225 | pm8001_ha->fatal_forensic_shift_offset); | ||
226 | pm8001_mw32(fatal_table_address, | ||
227 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE, | ||
228 | MPI_FATAL_EDUMP_HANDSHAKE_RDY); | ||
229 | |||
230 | /* Poll FDDHSHK until clear */ | ||
231 | start = jiffies + (2 * HZ); /* 2 sec */ | ||
232 | |||
233 | do { | ||
234 | reg_val = pm8001_mr32(fatal_table_address, | ||
235 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE); | ||
236 | } while ((reg_val) && time_before(jiffies, start)); | ||
237 | |||
238 | if (reg_val != 0) { | ||
239 | PM8001_FAIL_DBG(pm8001_ha, | ||
240 | pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" | ||
241 | " = 0x%x\n", reg_val)); | ||
242 | return -1; | ||
243 | } | ||
244 | |||
245 | /* Read the next 64K of the debug data. */ | ||
246 | pm8001_ha->forensic_fatal_step = 0; | ||
247 | if (pm8001_mr32(fatal_table_address, | ||
248 | MPI_FATAL_EDUMP_TABLE_STATUS) != | ||
249 | MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) { | ||
250 | pm8001_mw32(fatal_table_address, | ||
251 | MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0); | ||
252 | goto moreData; | ||
253 | } else { | ||
254 | pm8001_ha->forensic_info.data_buf.direct_data += | ||
255 | sprintf(pm8001_ha-> | ||
256 | forensic_info.data_buf.direct_data, | ||
257 | "%08x ", 4); | ||
258 | pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF; | ||
259 | pm8001_ha->forensic_info.data_buf.direct_len = 0; | ||
260 | pm8001_ha->forensic_info.data_buf.direct_offset = 0; | ||
261 | pm8001_ha->forensic_info.data_buf.read_len = 0; | ||
262 | status = 0; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | return (char *)pm8001_ha->forensic_info.data_buf.direct_data - | ||
267 | (char *)buf; | ||
268 | } | ||
269 | |||
48 | /** | 270 | /** |
49 | * read_main_config_table - read the configure table and save it. | 271 | * read_main_config_table - read the configure table and save it. |
50 | * @pm8001_ha: our hba card information | 272 | * @pm8001_ha: our hba card information |
@@ -430,7 +652,11 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) | |||
430 | table is updated */ | 652 | table is updated */ |
431 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); | 653 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); |
432 | /* wait until Inbound DoorBell Clear Register toggled */ | 654 | /* wait until Inbound DoorBell Clear Register toggled */ |
433 | max_wait_count = 2 * 1000 * 1000;/* 2 sec for spcv/ve */ | 655 | if (IS_SPCV_12G(pm8001_ha->pdev)) { |
656 | max_wait_count = 4 * 1000 * 1000;/* 4 sec */ | ||
657 | } else { | ||
658 | max_wait_count = 2 * 1000 * 1000;/* 2 sec */ | ||
659 | } | ||
434 | do { | 660 | do { |
435 | udelay(1); | 661 | udelay(1); |
436 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | 662 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); |
@@ -579,6 +805,9 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) | |||
579 | pm8001_ha->pspa_q_tbl_addr = | 805 | pm8001_ha->pspa_q_tbl_addr = |
580 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & | 806 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & |
581 | 0xFFFFFF); | 807 | 0xFFFFFF); |
808 | pm8001_ha->fatal_tbl_addr = | ||
809 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) & | ||
810 | 0xFFFFFF); | ||
582 | 811 | ||
583 | PM8001_INIT_DBG(pm8001_ha, | 812 | PM8001_INIT_DBG(pm8001_ha, |
584 | pm8001_printk("GST OFFSET 0x%x\n", | 813 | pm8001_printk("GST OFFSET 0x%x\n", |
@@ -913,7 +1142,11 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) | |||
913 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET); | 1142 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET); |
914 | 1143 | ||
915 | /* wait until Inbound DoorBell Clear Register toggled */ | 1144 | /* wait until Inbound DoorBell Clear Register toggled */ |
916 | max_wait_count = 2 * 1000 * 1000; /* 2 sec for spcv/ve */ | 1145 | if (IS_SPCV_12G(pm8001_ha->pdev)) { |
1146 | max_wait_count = 4 * 1000 * 1000;/* 4 sec */ | ||
1147 | } else { | ||
1148 | max_wait_count = 2 * 1000 * 1000;/* 2 sec */ | ||
1149 | } | ||
917 | do { | 1150 | do { |
918 | udelay(1); | 1151 | udelay(1); |
919 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | 1152 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); |
@@ -959,6 +1192,7 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
959 | { | 1192 | { |
960 | u32 regval; | 1193 | u32 regval; |
961 | u32 bootloader_state; | 1194 | u32 bootloader_state; |
1195 | u32 ibutton0, ibutton1; | ||
962 | 1196 | ||
963 | /* Check if MPI is in ready state to reset */ | 1197 | /* Check if MPI is in ready state to reset */ |
964 | if (mpi_uninit_check(pm8001_ha) != 0) { | 1198 | if (mpi_uninit_check(pm8001_ha) != 0) { |
@@ -1017,7 +1251,27 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
1017 | if (-1 == check_fw_ready(pm8001_ha)) { | 1251 | if (-1 == check_fw_ready(pm8001_ha)) { |
1018 | PM8001_FAIL_DBG(pm8001_ha, | 1252 | PM8001_FAIL_DBG(pm8001_ha, |
1019 | pm8001_printk("Firmware is not ready!\n")); | 1253 | pm8001_printk("Firmware is not ready!\n")); |
1020 | return -EBUSY; | 1254 | /* check iButton feature support for motherboard controller */ |
1255 | if (pm8001_ha->pdev->subsystem_vendor != | ||
1256 | PCI_VENDOR_ID_ADAPTEC2 && | ||
1257 | pm8001_ha->pdev->subsystem_vendor != 0) { | ||
1258 | ibutton0 = pm8001_cr32(pm8001_ha, 0, | ||
1259 | MSGU_HOST_SCRATCH_PAD_6); | ||
1260 | ibutton1 = pm8001_cr32(pm8001_ha, 0, | ||
1261 | MSGU_HOST_SCRATCH_PAD_7); | ||
1262 | if (!ibutton0 && !ibutton1) { | ||
1263 | PM8001_FAIL_DBG(pm8001_ha, | ||
1264 | pm8001_printk("iButton Feature is" | ||
1265 | " not Available!!!\n")); | ||
1266 | return -EBUSY; | ||
1267 | } | ||
1268 | if (ibutton0 == 0xdeadbeef && ibutton1 == 0xdeadbeef) { | ||
1269 | PM8001_FAIL_DBG(pm8001_ha, | ||
1270 | pm8001_printk("CRC Check for iButton" | ||
1271 | " Feature Failed!!!\n")); | ||
1272 | return -EBUSY; | ||
1273 | } | ||
1274 | } | ||
1021 | } | 1275 | } |
1022 | PM8001_INIT_DBG(pm8001_ha, | 1276 | PM8001_INIT_DBG(pm8001_ha, |
1023 | pm8001_printk("SPCv soft reset Complete\n")); | 1277 | pm8001_printk("SPCv soft reset Complete\n")); |
@@ -1268,6 +1522,13 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
1268 | if (unlikely(!t || !t->lldd_task || !t->dev)) | 1522 | if (unlikely(!t || !t->lldd_task || !t->dev)) |
1269 | return; | 1523 | return; |
1270 | ts = &t->task_status; | 1524 | ts = &t->task_status; |
1525 | /* Print sas address of IO failed device */ | ||
1526 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
1527 | (status != IO_UNDERFLOW)) | ||
1528 | PM8001_FAIL_DBG(pm8001_ha, | ||
1529 | pm8001_printk("SAS Address of IO Failure Drive" | ||
1530 | ":%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
1531 | |||
1271 | switch (status) { | 1532 | switch (status) { |
1272 | case IO_SUCCESS: | 1533 | case IO_SUCCESS: |
1273 | PM8001_IO_DBG(pm8001_ha, | 1534 | PM8001_IO_DBG(pm8001_ha, |
@@ -1691,6 +1952,10 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1691 | u32 param; | 1952 | u32 param; |
1692 | u32 status; | 1953 | u32 status; |
1693 | u32 tag; | 1954 | u32 tag; |
1955 | int i, j; | ||
1956 | u8 sata_addr_low[4]; | ||
1957 | u32 temp_sata_addr_low, temp_sata_addr_hi; | ||
1958 | u8 sata_addr_hi[4]; | ||
1694 | struct sata_completion_resp *psataPayload; | 1959 | struct sata_completion_resp *psataPayload; |
1695 | struct task_status_struct *ts; | 1960 | struct task_status_struct *ts; |
1696 | struct ata_task_resp *resp ; | 1961 | struct ata_task_resp *resp ; |
@@ -1740,7 +2005,47 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1740 | pm8001_printk("ts null\n")); | 2005 | pm8001_printk("ts null\n")); |
1741 | return; | 2006 | return; |
1742 | } | 2007 | } |
2008 | /* Print sas address of IO failed device */ | ||
2009 | if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && | ||
2010 | (status != IO_UNDERFLOW)) { | ||
2011 | if (!((t->dev->parent) && | ||
2012 | (DEV_IS_EXPANDER(t->dev->parent->dev_type)))) { | ||
2013 | for (i = 0 , j = 4; i <= 3 && j <= 7; i++ , j++) | ||
2014 | sata_addr_low[i] = pm8001_ha->sas_addr[j]; | ||
2015 | for (i = 0 , j = 0; i <= 3 && j <= 3; i++ , j++) | ||
2016 | sata_addr_hi[i] = pm8001_ha->sas_addr[j]; | ||
2017 | memcpy(&temp_sata_addr_low, sata_addr_low, | ||
2018 | sizeof(sata_addr_low)); | ||
2019 | memcpy(&temp_sata_addr_hi, sata_addr_hi, | ||
2020 | sizeof(sata_addr_hi)); | ||
2021 | temp_sata_addr_hi = (((temp_sata_addr_hi >> 24) & 0xff) | ||
2022 | |((temp_sata_addr_hi << 8) & | ||
2023 | 0xff0000) | | ||
2024 | ((temp_sata_addr_hi >> 8) | ||
2025 | & 0xff00) | | ||
2026 | ((temp_sata_addr_hi << 24) & | ||
2027 | 0xff000000)); | ||
2028 | temp_sata_addr_low = ((((temp_sata_addr_low >> 24) | ||
2029 | & 0xff) | | ||
2030 | ((temp_sata_addr_low << 8) | ||
2031 | & 0xff0000) | | ||
2032 | ((temp_sata_addr_low >> 8) | ||
2033 | & 0xff00) | | ||
2034 | ((temp_sata_addr_low << 24) | ||
2035 | & 0xff000000)) + | ||
2036 | pm8001_dev->attached_phy + | ||
2037 | 0x10); | ||
2038 | PM8001_FAIL_DBG(pm8001_ha, | ||
2039 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2040 | "%08x%08x", temp_sata_addr_hi, | ||
2041 | temp_sata_addr_low)); | ||
1743 | 2042 | ||
2043 | } else { | ||
2044 | PM8001_FAIL_DBG(pm8001_ha, | ||
2045 | pm8001_printk("SAS Address of IO Failure Drive:" | ||
2046 | "%016llx", SAS_ADDR(t->dev->sas_addr))); | ||
2047 | } | ||
2048 | } | ||
1744 | switch (status) { | 2049 | switch (status) { |
1745 | case IO_SUCCESS: | 2050 | case IO_SUCCESS: |
1746 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); | 2051 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); |
@@ -3103,9 +3408,27 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
3103 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, | 3408 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, |
3104 | void *piomb) | 3409 | void *piomb) |
3105 | { | 3410 | { |
3106 | PM8001_MSG_DBG(pm8001_ha, | 3411 | u8 page_code; |
3107 | pm8001_printk(" pm80xx_addition_functionality\n")); | 3412 | struct set_phy_profile_resp *pPayload = |
3413 | (struct set_phy_profile_resp *)(piomb + 4); | ||
3414 | u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid); | ||
3415 | u32 status = le32_to_cpu(pPayload->status); | ||
3108 | 3416 | ||
3417 | page_code = (u8)((ppc_phyid & 0xFF00) >> 8); | ||
3418 | if (status) { | ||
3419 | /* status is FAILED */ | ||
3420 | PM8001_FAIL_DBG(pm8001_ha, | ||
3421 | pm8001_printk("PhyProfile command failed with status " | ||
3422 | "0x%08X \n", status)); | ||
3423 | return -1; | ||
3424 | } else { | ||
3425 | if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) { | ||
3426 | PM8001_FAIL_DBG(pm8001_ha, | ||
3427 | pm8001_printk("Invalid page code 0x%X\n", | ||
3428 | page_code)); | ||
3429 | return -1; | ||
3430 | } | ||
3431 | } | ||
3109 | return 0; | 3432 | return 0; |
3110 | } | 3433 | } |
3111 | 3434 | ||
@@ -3484,8 +3807,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | |||
3484 | else | 3807 | else |
3485 | pm8001_ha->smp_exp_mode = SMP_INDIRECT; | 3808 | pm8001_ha->smp_exp_mode = SMP_INDIRECT; |
3486 | 3809 | ||
3487 | /* DIRECT MODE support only in spcv/ve */ | ||
3488 | pm8001_ha->smp_exp_mode = SMP_DIRECT; | ||
3489 | 3810 | ||
3490 | tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req)); | 3811 | tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req)); |
3491 | preq_dma_addr = (char *)phys_to_virt(tmp_addr); | 3812 | preq_dma_addr = (char *)phys_to_virt(tmp_addr); |
@@ -3501,7 +3822,7 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | |||
3501 | /* exclude top 4 bytes for SMP req header */ | 3822 | /* exclude top 4 bytes for SMP req header */ |
3502 | smp_cmd.long_smp_req.long_req_addr = | 3823 | smp_cmd.long_smp_req.long_req_addr = |
3503 | cpu_to_le64((u64)sg_dma_address | 3824 | cpu_to_le64((u64)sg_dma_address |
3504 | (&task->smp_task.smp_req) - 4); | 3825 | (&task->smp_task.smp_req) + 4); |
3505 | /* exclude 4 bytes for SMP req header and CRC */ | 3826 | /* exclude 4 bytes for SMP req header and CRC */ |
3506 | smp_cmd.long_smp_req.long_req_size = | 3827 | smp_cmd.long_smp_req.long_req_size = |
3507 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8); | 3828 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8); |
@@ -3604,10 +3925,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3604 | struct ssp_ini_io_start_req ssp_cmd; | 3925 | struct ssp_ini_io_start_req ssp_cmd; |
3605 | u32 tag = ccb->ccb_tag; | 3926 | u32 tag = ccb->ccb_tag; |
3606 | int ret; | 3927 | int ret; |
3607 | u64 phys_addr; | 3928 | u64 phys_addr, start_addr, end_addr; |
3929 | u32 end_addr_high, end_addr_low; | ||
3608 | struct inbound_queue_table *circularQ; | 3930 | struct inbound_queue_table *circularQ; |
3609 | static u32 inb; | 3931 | u32 q_index; |
3610 | static u32 outb; | ||
3611 | u32 opc = OPC_INB_SSPINIIOSTART; | 3932 | u32 opc = OPC_INB_SSPINIIOSTART; |
3612 | memset(&ssp_cmd, 0, sizeof(ssp_cmd)); | 3933 | memset(&ssp_cmd, 0, sizeof(ssp_cmd)); |
3613 | memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); | 3934 | memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); |
@@ -3626,7 +3947,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3626 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); | 3947 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); |
3627 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, | 3948 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, |
3628 | task->ssp_task.cmd->cmd_len); | 3949 | task->ssp_task.cmd->cmd_len); |
3629 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 3950 | q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; |
3951 | circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; | ||
3630 | 3952 | ||
3631 | /* Check if encryption is set */ | 3953 | /* Check if encryption is set */ |
3632 | if (pm8001_ha->chip->encrypt && | 3954 | if (pm8001_ha->chip->encrypt && |
@@ -3658,6 +3980,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3658 | cpu_to_le32(upper_32_bits(dma_addr)); | 3980 | cpu_to_le32(upper_32_bits(dma_addr)); |
3659 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | 3981 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); |
3660 | ssp_cmd.enc_esgl = 0; | 3982 | ssp_cmd.enc_esgl = 0; |
3983 | /* Check 4G Boundary */ | ||
3984 | start_addr = cpu_to_le64(dma_addr); | ||
3985 | end_addr = (start_addr + ssp_cmd.enc_len) - 1; | ||
3986 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
3987 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
3988 | if (end_addr_high != ssp_cmd.enc_addr_high) { | ||
3989 | PM8001_FAIL_DBG(pm8001_ha, | ||
3990 | pm8001_printk("The sg list address " | ||
3991 | "start_addr=0x%016llx data_len=0x%x " | ||
3992 | "end_addr_high=0x%08x end_addr_low=" | ||
3993 | "0x%08x has crossed 4G boundary\n", | ||
3994 | start_addr, ssp_cmd.enc_len, | ||
3995 | end_addr_high, end_addr_low)); | ||
3996 | pm8001_chip_make_sg(task->scatter, 1, | ||
3997 | ccb->buf_prd); | ||
3998 | phys_addr = ccb->ccb_dma_handle + | ||
3999 | offsetof(struct pm8001_ccb_info, | ||
4000 | buf_prd[0]); | ||
4001 | ssp_cmd.enc_addr_low = | ||
4002 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
4003 | ssp_cmd.enc_addr_high = | ||
4004 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
4005 | ssp_cmd.enc_esgl = cpu_to_le32(1<<31); | ||
4006 | } | ||
3661 | } else if (task->num_scatter == 0) { | 4007 | } else if (task->num_scatter == 0) { |
3662 | ssp_cmd.enc_addr_low = 0; | 4008 | ssp_cmd.enc_addr_low = 0; |
3663 | ssp_cmd.enc_addr_high = 0; | 4009 | ssp_cmd.enc_addr_high = 0; |
@@ -3674,7 +4020,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3674 | } else { | 4020 | } else { |
3675 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | 4021 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( |
3676 | "Sending Normal SAS command 0x%x inb q %x\n", | 4022 | "Sending Normal SAS command 0x%x inb q %x\n", |
3677 | task->ssp_task.cmd->cmnd[0], inb)); | 4023 | task->ssp_task.cmd->cmnd[0], q_index)); |
3678 | /* fill in PRD (scatter/gather) table, if any */ | 4024 | /* fill in PRD (scatter/gather) table, if any */ |
3679 | if (task->num_scatter > 1) { | 4025 | if (task->num_scatter > 1) { |
3680 | pm8001_chip_make_sg(task->scatter, ccb->n_elem, | 4026 | pm8001_chip_make_sg(task->scatter, ccb->n_elem, |
@@ -3693,6 +4039,30 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3693 | cpu_to_le32(upper_32_bits(dma_addr)); | 4039 | cpu_to_le32(upper_32_bits(dma_addr)); |
3694 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); | 4040 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); |
3695 | ssp_cmd.esgl = 0; | 4041 | ssp_cmd.esgl = 0; |
4042 | /* Check 4G Boundary */ | ||
4043 | start_addr = cpu_to_le64(dma_addr); | ||
4044 | end_addr = (start_addr + ssp_cmd.len) - 1; | ||
4045 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4046 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4047 | if (end_addr_high != ssp_cmd.addr_high) { | ||
4048 | PM8001_FAIL_DBG(pm8001_ha, | ||
4049 | pm8001_printk("The sg list address " | ||
4050 | "start_addr=0x%016llx data_len=0x%x " | ||
4051 | "end_addr_high=0x%08x end_addr_low=" | ||
4052 | "0x%08x has crossed 4G boundary\n", | ||
4053 | start_addr, ssp_cmd.len, | ||
4054 | end_addr_high, end_addr_low)); | ||
4055 | pm8001_chip_make_sg(task->scatter, 1, | ||
4056 | ccb->buf_prd); | ||
4057 | phys_addr = ccb->ccb_dma_handle + | ||
4058 | offsetof(struct pm8001_ccb_info, | ||
4059 | buf_prd[0]); | ||
4060 | ssp_cmd.addr_low = | ||
4061 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
4062 | ssp_cmd.addr_high = | ||
4063 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
4064 | ssp_cmd.esgl = cpu_to_le32(1<<31); | ||
4065 | } | ||
3696 | } else if (task->num_scatter == 0) { | 4066 | } else if (task->num_scatter == 0) { |
3697 | ssp_cmd.addr_low = 0; | 4067 | ssp_cmd.addr_low = 0; |
3698 | ssp_cmd.addr_high = 0; | 4068 | ssp_cmd.addr_high = 0; |
@@ -3700,11 +4070,9 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
3700 | ssp_cmd.esgl = 0; | 4070 | ssp_cmd.esgl = 0; |
3701 | } | 4071 | } |
3702 | } | 4072 | } |
3703 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, outb++); | 4073 | q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; |
3704 | 4074 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | |
3705 | /* rotate the outb queue */ | 4075 | &ssp_cmd, q_index); |
3706 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
3707 | |||
3708 | return ret; | 4076 | return ret; |
3709 | } | 4077 | } |
3710 | 4078 | ||
@@ -3716,18 +4084,19 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3716 | struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; | 4084 | struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; |
3717 | u32 tag = ccb->ccb_tag; | 4085 | u32 tag = ccb->ccb_tag; |
3718 | int ret; | 4086 | int ret; |
3719 | static u32 inb; | 4087 | u32 q_index; |
3720 | static u32 outb; | ||
3721 | struct sata_start_req sata_cmd; | 4088 | struct sata_start_req sata_cmd; |
3722 | u32 hdr_tag, ncg_tag = 0; | 4089 | u32 hdr_tag, ncg_tag = 0; |
3723 | u64 phys_addr; | 4090 | u64 phys_addr, start_addr, end_addr; |
4091 | u32 end_addr_high, end_addr_low; | ||
3724 | u32 ATAP = 0x0; | 4092 | u32 ATAP = 0x0; |
3725 | u32 dir; | 4093 | u32 dir; |
3726 | struct inbound_queue_table *circularQ; | 4094 | struct inbound_queue_table *circularQ; |
3727 | unsigned long flags; | 4095 | unsigned long flags; |
3728 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | 4096 | u32 opc = OPC_INB_SATA_HOST_OPSTART; |
3729 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | 4097 | memset(&sata_cmd, 0, sizeof(sata_cmd)); |
3730 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4098 | q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; |
4099 | circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; | ||
3731 | 4100 | ||
3732 | if (task->data_dir == PCI_DMA_NONE) { | 4101 | if (task->data_dir == PCI_DMA_NONE) { |
3733 | ATAP = 0x04; /* no data*/ | 4102 | ATAP = 0x04; /* no data*/ |
@@ -3788,6 +4157,31 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3788 | sata_cmd.enc_addr_high = upper_32_bits(dma_addr); | 4157 | sata_cmd.enc_addr_high = upper_32_bits(dma_addr); |
3789 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | 4158 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); |
3790 | sata_cmd.enc_esgl = 0; | 4159 | sata_cmd.enc_esgl = 0; |
4160 | /* Check 4G Boundary */ | ||
4161 | start_addr = cpu_to_le64(dma_addr); | ||
4162 | end_addr = (start_addr + sata_cmd.enc_len) - 1; | ||
4163 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4164 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4165 | if (end_addr_high != sata_cmd.enc_addr_high) { | ||
4166 | PM8001_FAIL_DBG(pm8001_ha, | ||
4167 | pm8001_printk("The sg list address " | ||
4168 | "start_addr=0x%016llx data_len=0x%x " | ||
4169 | "end_addr_high=0x%08x end_addr_low" | ||
4170 | "=0x%08x has crossed 4G boundary\n", | ||
4171 | start_addr, sata_cmd.enc_len, | ||
4172 | end_addr_high, end_addr_low)); | ||
4173 | pm8001_chip_make_sg(task->scatter, 1, | ||
4174 | ccb->buf_prd); | ||
4175 | phys_addr = ccb->ccb_dma_handle + | ||
4176 | offsetof(struct pm8001_ccb_info, | ||
4177 | buf_prd[0]); | ||
4178 | sata_cmd.enc_addr_low = | ||
4179 | lower_32_bits(phys_addr); | ||
4180 | sata_cmd.enc_addr_high = | ||
4181 | upper_32_bits(phys_addr); | ||
4182 | sata_cmd.enc_esgl = | ||
4183 | cpu_to_le32(1 << 31); | ||
4184 | } | ||
3791 | } else if (task->num_scatter == 0) { | 4185 | } else if (task->num_scatter == 0) { |
3792 | sata_cmd.enc_addr_low = 0; | 4186 | sata_cmd.enc_addr_low = 0; |
3793 | sata_cmd.enc_addr_high = 0; | 4187 | sata_cmd.enc_addr_high = 0; |
@@ -3808,7 +4202,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3808 | } else { | 4202 | } else { |
3809 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | 4203 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( |
3810 | "Sending Normal SATA command 0x%x inb %x\n", | 4204 | "Sending Normal SATA command 0x%x inb %x\n", |
3811 | sata_cmd.sata_fis.command, inb)); | 4205 | sata_cmd.sata_fis.command, q_index)); |
3812 | /* dad (bit 0-1) is 0 */ | 4206 | /* dad (bit 0-1) is 0 */ |
3813 | sata_cmd.ncqtag_atap_dir_m_dad = | 4207 | sata_cmd.ncqtag_atap_dir_m_dad = |
3814 | cpu_to_le32(((ncg_tag & 0xff)<<16) | | 4208 | cpu_to_le32(((ncg_tag & 0xff)<<16) | |
@@ -3829,6 +4223,30 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3829 | sata_cmd.addr_high = upper_32_bits(dma_addr); | 4223 | sata_cmd.addr_high = upper_32_bits(dma_addr); |
3830 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); | 4224 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); |
3831 | sata_cmd.esgl = 0; | 4225 | sata_cmd.esgl = 0; |
4226 | /* Check 4G Boundary */ | ||
4227 | start_addr = cpu_to_le64(dma_addr); | ||
4228 | end_addr = (start_addr + sata_cmd.len) - 1; | ||
4229 | end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); | ||
4230 | end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); | ||
4231 | if (end_addr_high != sata_cmd.addr_high) { | ||
4232 | PM8001_FAIL_DBG(pm8001_ha, | ||
4233 | pm8001_printk("The sg list address " | ||
4234 | "start_addr=0x%016llx data_len=0x%x" | ||
4235 | "end_addr_high=0x%08x end_addr_low=" | ||
4236 | "0x%08x has crossed 4G boundary\n", | ||
4237 | start_addr, sata_cmd.len, | ||
4238 | end_addr_high, end_addr_low)); | ||
4239 | pm8001_chip_make_sg(task->scatter, 1, | ||
4240 | ccb->buf_prd); | ||
4241 | phys_addr = ccb->ccb_dma_handle + | ||
4242 | offsetof(struct pm8001_ccb_info, | ||
4243 | buf_prd[0]); | ||
4244 | sata_cmd.addr_low = | ||
4245 | lower_32_bits(phys_addr); | ||
4246 | sata_cmd.addr_high = | ||
4247 | upper_32_bits(phys_addr); | ||
4248 | sata_cmd.esgl = cpu_to_le32(1 << 31); | ||
4249 | } | ||
3832 | } else if (task->num_scatter == 0) { | 4250 | } else if (task->num_scatter == 0) { |
3833 | sata_cmd.addr_low = 0; | 4251 | sata_cmd.addr_low = 0; |
3834 | sata_cmd.addr_high = 0; | 4252 | sata_cmd.addr_high = 0; |
@@ -3905,12 +4323,9 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
3905 | } | 4323 | } |
3906 | } | 4324 | } |
3907 | } | 4325 | } |
3908 | 4326 | q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; | |
3909 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | 4327 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, |
3910 | &sata_cmd, outb++); | 4328 | &sata_cmd, q_index); |
3911 | |||
3912 | /* rotate the outb queue */ | ||
3913 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
3914 | return ret; | 4329 | return ret; |
3915 | } | 4330 | } |
3916 | 4331 | ||
@@ -3941,9 +4356,16 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) | |||
3941 | ** [14] 0b disable spin up hold; 1b enable spin up hold | 4356 | ** [14] 0b disable spin up hold; 1b enable spin up hold |
3942 | ** [15] ob no change in current PHY analig setup 1b enable using SPAST | 4357 | ** [15] ob no change in current PHY analig setup 1b enable using SPAST |
3943 | */ | 4358 | */ |
3944 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | 4359 | if (!IS_SPCV_12G(pm8001_ha->pdev)) |
3945 | LINKMODE_AUTO | LINKRATE_15 | | 4360 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | |
3946 | LINKRATE_30 | LINKRATE_60 | phy_id); | 4361 | LINKMODE_AUTO | LINKRATE_15 | |
4362 | LINKRATE_30 | LINKRATE_60 | phy_id); | ||
4363 | else | ||
4364 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | ||
4365 | LINKMODE_AUTO | LINKRATE_15 | | ||
4366 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120 | | ||
4367 | phy_id); | ||
4368 | |||
3947 | /* SSC Disable and SAS Analog ST configuration */ | 4369 | /* SSC Disable and SAS Analog ST configuration */ |
3948 | /** | 4370 | /** |
3949 | payload.ase_sh_lm_slr_phyid = | 4371 | payload.ase_sh_lm_slr_phyid = |
@@ -4102,6 +4524,45 @@ pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) | |||
4102 | return IRQ_HANDLED; | 4524 | return IRQ_HANDLED; |
4103 | } | 4525 | } |
4104 | 4526 | ||
4527 | void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, | ||
4528 | u32 operation, u32 phyid, u32 length, u32 *buf) | ||
4529 | { | ||
4530 | u32 tag , i, j = 0; | ||
4531 | int rc; | ||
4532 | struct set_phy_profile_req payload; | ||
4533 | struct inbound_queue_table *circularQ; | ||
4534 | u32 opc = OPC_INB_SET_PHY_PROFILE; | ||
4535 | |||
4536 | memset(&payload, 0, sizeof(payload)); | ||
4537 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
4538 | if (rc) | ||
4539 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n")); | ||
4540 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
4541 | payload.tag = cpu_to_le32(tag); | ||
4542 | payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid & 0xFF)); | ||
4543 | PM8001_INIT_DBG(pm8001_ha, | ||
4544 | pm8001_printk(" phy profile command for phy %x ,length is %d\n", | ||
4545 | payload.ppc_phyid, length)); | ||
4546 | for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) { | ||
4547 | payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); | ||
4548 | j++; | ||
4549 | } | ||
4550 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
4551 | } | ||
4552 | |||
4553 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | ||
4554 | u32 length, u8 *buf) | ||
4555 | { | ||
4556 | u32 page_code, i; | ||
4557 | |||
4558 | page_code = SAS_PHY_ANALOG_SETTINGS_PAGE; | ||
4559 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | ||
4560 | mpi_set_phy_profile_req(pm8001_ha, | ||
4561 | SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf); | ||
4562 | length = length + PHY_DWORD_LENGTH; | ||
4563 | } | ||
4564 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); | ||
4565 | } | ||
4105 | const struct pm8001_dispatch pm8001_80xx_dispatch = { | 4566 | const struct pm8001_dispatch pm8001_80xx_dispatch = { |
4106 | .name = "pmc80xx", | 4567 | .name = "pmc80xx", |
4107 | .chip_init = pm80xx_chip_init, | 4568 | .chip_init = pm80xx_chip_init, |