4920 lines · c
1/*2 * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver3 *4 * Copyright (c) 2008-2009 PMC-Sierra, Inc.,5 * All rights reserved.6 *7 * Redistribution and use in source and binary forms, with or without8 * modification, are permitted provided that the following conditions9 * are met:10 * 1. Redistributions of source code must retain the above copyright11 * notice, this list of conditions, and the following disclaimer,12 * without modification.13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer14 * substantially similar to the "NO WARRANTY" disclaimer below15 * ("Disclaimer") and any redistribution must be conditioned upon16 * including a substantially similar Disclaimer requirement for further17 * binary redistribution.18 * 3. Neither the names of the above-listed copyright holders nor the names19 * of any contributors may be used to endorse or promote products derived20 * from this software without specific prior written permission.21 *22 * Alternatively, this software may be distributed under the terms of the23 * GNU General Public License ("GPL") version 2 as published by the Free24 * Software Foundation.25 *26 * NO WARRANTY27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE37 * POSSIBILITY OF SUCH DAMAGES.38 *39 */40 #include <linux/slab.h>41 #include "pm8001_sas.h"42 #include "pm80xx_hwi.h"43 #include "pm8001_chips.h"44 #include "pm8001_ctl.h"45#include "pm80xx_tracepoints.h"46 47#define SMP_DIRECT 148#define SMP_INDIRECT 249 50 51int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value)52{53 u32 reg_val;54 unsigned long start;55 pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, shift_value);56 /* confirm the setting is written */57 start = jiffies + HZ; /* 1 sec */58 do {59 reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER);60 } while ((reg_val != shift_value) && time_before(jiffies, start));61 if (reg_val != shift_value) {62 pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:MEMBASE_II_SHIFT_REGISTER = 0x%x\n",63 reg_val);64 return -1;65 }66 return 0;67}68 69static void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset,70 __le32 *destination,71 u32 dw_count, u32 bus_base_number)72{73 u32 index, value, offset;74 75 for (index = 0; index < dw_count; index += 4, destination++) {76 offset = (soffset + index);77 if (offset < (64 * 1024)) {78 value = pm8001_cr32(pm8001_ha, bus_base_number, offset);79 *destination = cpu_to_le32(value);80 }81 }82 return;83}84 85ssize_t pm80xx_get_fatal_dump(struct device *cdev,86 struct device_attribute *attr, char *buf)87{88 struct Scsi_Host *shost = class_to_shost(cdev);89 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);90 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;91 void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;92 u32 accum_len, reg_val, index, *temp;93 u32 status = 1;94 unsigned long start;95 u8 *direct_data;96 char *fatal_error_data = buf;97 u32 length_to_read;98 u32 offset;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 /* initialize variables for very first call from host application */109 if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {110 pm8001_dbg(pm8001_ha, IO,111 "forensic_info TYPE_NON_FATAL..............\n");112 direct_data = (u8 *)fatal_error_data;113 pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;114 pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;115 pm8001_ha->forensic_info.data_buf.direct_offset = 0;116 pm8001_ha->forensic_info.data_buf.read_len = 0;117 pm8001_ha->forensic_preserved_accumulated_transfer = 0;118 119 /* Write signature to fatal dump table */120 pm8001_mw32(fatal_table_address,121 MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);122 123 pm8001_ha->forensic_info.data_buf.direct_data = direct_data;124 pm8001_dbg(pm8001_ha, IO, "ossaHwCB: status1 %d\n", status);125 pm8001_dbg(pm8001_ha, IO, "ossaHwCB: read_len 0x%x\n",126 pm8001_ha->forensic_info.data_buf.read_len);127 pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_len 0x%x\n",128 pm8001_ha->forensic_info.data_buf.direct_len);129 pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_offset 0x%x\n",130 pm8001_ha->forensic_info.data_buf.direct_offset);131 }132 if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {133 /* start to get data */134 /* Program the MEMBASE II Shifting Register with 0x00.*/135 pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,136 pm8001_ha->fatal_forensic_shift_offset);137 pm8001_ha->forensic_last_offset = 0;138 pm8001_ha->forensic_fatal_step = 0;139 pm8001_ha->fatal_bar_loc = 0;140 }141 142 /* Read until accum_len is retrieved */143 accum_len = pm8001_mr32(fatal_table_address,144 MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);145 /* Determine length of data between previously stored transfer length146 * and current accumulated transfer length147 */148 length_to_read =149 accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;150 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: accum_len 0x%x\n",151 accum_len);152 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: length_to_read 0x%x\n",153 length_to_read);154 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: last_offset 0x%x\n",155 pm8001_ha->forensic_last_offset);156 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: read_len 0x%x\n",157 pm8001_ha->forensic_info.data_buf.read_len);158 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_len 0x%x\n",159 pm8001_ha->forensic_info.data_buf.direct_len);160 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_offset 0x%x\n",161 pm8001_ha->forensic_info.data_buf.direct_offset);162 163 /* If accumulated length failed to read correctly fail the attempt.*/164 if (accum_len == 0xFFFFFFFF) {165 pm8001_dbg(pm8001_ha, IO,166 "Possible PCI issue 0x%x not expected\n",167 accum_len);168 return status;169 }170 /* If accumulated length is zero fail the attempt */171 if (accum_len == 0) {172 pm8001_ha->forensic_info.data_buf.direct_data +=173 sprintf(pm8001_ha->forensic_info.data_buf.direct_data,174 "%08x ", 0xFFFFFFFF);175 return (char *)pm8001_ha->forensic_info.data_buf.direct_data -176 (char *)buf;177 }178 /* Accumulated length is good so start capturing the first data */179 temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;180 if (pm8001_ha->forensic_fatal_step == 0) {181moreData:182 /* If data to read is less than SYSFS_OFFSET then reduce the183 * length of dataLen184 */185 if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET186 > length_to_read) {187 pm8001_ha->forensic_info.data_buf.direct_len =188 length_to_read -189 pm8001_ha->forensic_last_offset;190 } else {191 pm8001_ha->forensic_info.data_buf.direct_len =192 SYSFS_OFFSET;193 }194 if (pm8001_ha->forensic_info.data_buf.direct_data) {195 /* Data is in bar, copy to host memory */196 pm80xx_pci_mem_copy(pm8001_ha,197 pm8001_ha->fatal_bar_loc,198 pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,199 pm8001_ha->forensic_info.data_buf.direct_len, 1);200 }201 pm8001_ha->fatal_bar_loc +=202 pm8001_ha->forensic_info.data_buf.direct_len;203 pm8001_ha->forensic_info.data_buf.direct_offset +=204 pm8001_ha->forensic_info.data_buf.direct_len;205 pm8001_ha->forensic_last_offset +=206 pm8001_ha->forensic_info.data_buf.direct_len;207 pm8001_ha->forensic_info.data_buf.read_len =208 pm8001_ha->forensic_info.data_buf.direct_len;209 210 if (pm8001_ha->forensic_last_offset >= length_to_read) {211 pm8001_ha->forensic_info.data_buf.direct_data +=212 sprintf(pm8001_ha->forensic_info.data_buf.direct_data,213 "%08x ", 3);214 for (index = 0; index <215 (pm8001_ha->forensic_info.data_buf.direct_len216 / 4); index++) {217 pm8001_ha->forensic_info.data_buf.direct_data +=218 sprintf(219 pm8001_ha->forensic_info.data_buf.direct_data,220 "%08x ", *(temp + index));221 }222 223 pm8001_ha->fatal_bar_loc = 0;224 pm8001_ha->forensic_fatal_step = 1;225 pm8001_ha->fatal_forensic_shift_offset = 0;226 pm8001_ha->forensic_last_offset = 0;227 status = 0;228 offset = (int)229 ((char *)pm8001_ha->forensic_info.data_buf.direct_data230 - (char *)buf);231 pm8001_dbg(pm8001_ha, IO,232 "get_fatal_spcv:return1 0x%x\n", offset);233 return (char *)pm8001_ha->234 forensic_info.data_buf.direct_data -235 (char *)buf;236 }237 if (pm8001_ha->fatal_bar_loc < (64 * 1024)) {238 pm8001_ha->forensic_info.data_buf.direct_data +=239 sprintf(pm8001_ha->240 forensic_info.data_buf.direct_data,241 "%08x ", 2);242 for (index = 0; index <243 (pm8001_ha->forensic_info.data_buf.direct_len244 / 4); index++) {245 pm8001_ha->forensic_info.data_buf.direct_data246 += sprintf(pm8001_ha->247 forensic_info.data_buf.direct_data,248 "%08x ", *(temp + index));249 }250 status = 0;251 offset = (int)252 ((char *)pm8001_ha->forensic_info.data_buf.direct_data253 - (char *)buf);254 pm8001_dbg(pm8001_ha, IO,255 "get_fatal_spcv:return2 0x%x\n", offset);256 return (char *)pm8001_ha->257 forensic_info.data_buf.direct_data -258 (char *)buf;259 }260 261 /* Increment the MEMBASE II Shifting Register value by 0x100.*/262 pm8001_ha->forensic_info.data_buf.direct_data +=263 sprintf(pm8001_ha->forensic_info.data_buf.direct_data,264 "%08x ", 2);265 for (index = 0; index <266 (pm8001_ha->forensic_info.data_buf.direct_len267 / 4) ; index++) {268 pm8001_ha->forensic_info.data_buf.direct_data +=269 sprintf(pm8001_ha->270 forensic_info.data_buf.direct_data,271 "%08x ", *(temp + index));272 }273 pm8001_ha->fatal_forensic_shift_offset += 0x100;274 pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,275 pm8001_ha->fatal_forensic_shift_offset);276 pm8001_ha->fatal_bar_loc = 0;277 status = 0;278 offset = (int)279 ((char *)pm8001_ha->forensic_info.data_buf.direct_data280 - (char *)buf);281 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return3 0x%x\n",282 offset);283 return (char *)pm8001_ha->forensic_info.data_buf.direct_data -284 (char *)buf;285 }286 if (pm8001_ha->forensic_fatal_step == 1) {287 /* store previous accumulated length before triggering next288 * accumulated length update289 */290 pm8001_ha->forensic_preserved_accumulated_transfer =291 pm8001_mr32(fatal_table_address,292 MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);293 294 /* continue capturing the fatal log until Dump status is 0x3 */295 if (pm8001_mr32(fatal_table_address,296 MPI_FATAL_EDUMP_TABLE_STATUS) <297 MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {298 299 /* reset fddstat bit by writing to zero*/300 pm8001_mw32(fatal_table_address,301 MPI_FATAL_EDUMP_TABLE_STATUS, 0x0);302 303 /* set dump control value to '1' so that new data will304 * be transferred to shared memory305 */306 pm8001_mw32(fatal_table_address,307 MPI_FATAL_EDUMP_TABLE_HANDSHAKE,308 MPI_FATAL_EDUMP_HANDSHAKE_RDY);309 310 /*Poll FDDHSHK until clear */311 start = jiffies + (2 * HZ); /* 2 sec */312 313 do {314 reg_val = pm8001_mr32(fatal_table_address,315 MPI_FATAL_EDUMP_TABLE_HANDSHAKE);316 } while ((reg_val) && time_before(jiffies, start));317 318 if (reg_val != 0) {319 pm8001_dbg(pm8001_ha, FAIL,320 "TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n",321 reg_val);322 /* Fail the dump if a timeout occurs */323 pm8001_ha->forensic_info.data_buf.direct_data +=324 sprintf(325 pm8001_ha->forensic_info.data_buf.direct_data,326 "%08x ", 0xFFFFFFFF);327 return((char *)328 pm8001_ha->forensic_info.data_buf.direct_data329 - (char *)buf);330 }331 /* Poll status register until set to 2 or332 * 3 for up to 2 seconds333 */334 start = jiffies + (2 * HZ); /* 2 sec */335 336 do {337 reg_val = pm8001_mr32(fatal_table_address,338 MPI_FATAL_EDUMP_TABLE_STATUS);339 } while (((reg_val != 2) && (reg_val != 3)) &&340 time_before(jiffies, start));341 342 if (reg_val < 2) {343 pm8001_dbg(pm8001_ha, FAIL,344 "TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n",345 reg_val);346 /* Fail the dump if a timeout occurs */347 pm8001_ha->forensic_info.data_buf.direct_data +=348 sprintf(349 pm8001_ha->forensic_info.data_buf.direct_data,350 "%08x ", 0xFFFFFFFF);351 return((char *)pm8001_ha->forensic_info.data_buf.direct_data -352 (char *)buf);353 }354 /* reset fatal_forensic_shift_offset back to zero and reset MEMBASE 2 register to zero */355 pm8001_ha->fatal_forensic_shift_offset = 0; /* location in 64k region */356 pm8001_cw32(pm8001_ha, 0,357 MEMBASE_II_SHIFT_REGISTER,358 pm8001_ha->fatal_forensic_shift_offset);359 }360 /* Read the next block of the debug data.*/361 length_to_read = pm8001_mr32(fatal_table_address,362 MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) -363 pm8001_ha->forensic_preserved_accumulated_transfer;364 if (length_to_read != 0x0) {365 pm8001_ha->forensic_fatal_step = 0;366 goto moreData;367 } else {368 pm8001_ha->forensic_info.data_buf.direct_data +=369 sprintf(pm8001_ha->forensic_info.data_buf.direct_data,370 "%08x ", 4);371 pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF;372 pm8001_ha->forensic_info.data_buf.direct_len = 0;373 pm8001_ha->forensic_info.data_buf.direct_offset = 0;374 pm8001_ha->forensic_info.data_buf.read_len = 0;375 }376 }377 offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data378 - (char *)buf);379 pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return4 0x%x\n", offset);380 return ((char *)pm8001_ha->forensic_info.data_buf.direct_data -381 (char *)buf);382}383 384/* pm80xx_get_non_fatal_dump - dump the nonfatal data from the dma385 * location by the firmware.386 */387ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,388 struct device_attribute *attr, char *buf)389{390 struct Scsi_Host *shost = class_to_shost(cdev);391 struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);392 struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;393 void __iomem *nonfatal_table_address = pm8001_ha->fatal_tbl_addr;394 u32 accum_len = 0;395 u32 total_len = 0;396 u32 reg_val = 0;397 u32 *temp = NULL;398 u32 index = 0;399 u32 output_length;400 unsigned long start = 0;401 char *buf_copy = buf;402 403 temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;404 if (++pm8001_ha->non_fatal_count == 1) {405 if (pm8001_ha->chip_id == chip_8001) {406 snprintf(pm8001_ha->forensic_info.data_buf.direct_data,407 PAGE_SIZE, "Not supported for SPC controller");408 return 0;409 }410 pm8001_dbg(pm8001_ha, IO, "forensic_info TYPE_NON_FATAL...\n");411 /*412 * Step 1: Write the host buffer parameters in the MPI Fatal and413 * Non-Fatal Error Dump Capture Table.This is the buffer414 * where debug data will be DMAed to.415 */416 pm8001_mw32(nonfatal_table_address,417 MPI_FATAL_EDUMP_TABLE_LO_OFFSET,418 pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_lo);419 420 pm8001_mw32(nonfatal_table_address,421 MPI_FATAL_EDUMP_TABLE_HI_OFFSET,422 pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_hi);423 424 pm8001_mw32(nonfatal_table_address,425 MPI_FATAL_EDUMP_TABLE_LENGTH, SYSFS_OFFSET);426 427 /* Optionally, set the DUMPCTRL bit to 1 if the host428 * keeps sending active I/Os while capturing the non-fatal429 * debug data. Otherwise, leave this bit set to zero430 */431 pm8001_mw32(nonfatal_table_address,432 MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY);433 434 /*435 * Step 2: Clear Accumulative Length of Debug Data Transferred436 * [ACCDDLEN] field in the MPI Fatal and Non-Fatal Error Dump437 * Capture Table to zero.438 */439 pm8001_mw32(nonfatal_table_address,440 MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, 0);441 442 /* initiallize previous accumulated length to 0 */443 pm8001_ha->forensic_preserved_accumulated_transfer = 0;444 pm8001_ha->non_fatal_read_length = 0;445 }446 447 total_len = pm8001_mr32(nonfatal_table_address,448 MPI_FATAL_EDUMP_TABLE_TOTAL_LEN);449 /*450 * Step 3:Clear Fatal/Non-Fatal Debug Data Transfer Status [FDDTSTAT]451 * field and then request that the SPCv controller transfer the debug452 * data by setting bit 7 of the Inbound Doorbell Set Register.453 */454 pm8001_mw32(nonfatal_table_address, MPI_FATAL_EDUMP_TABLE_STATUS, 0);455 pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET,456 SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP);457 458 /*459 * Step 4.1: Read back the Inbound Doorbell Set Register (by polling for460 * 2 seconds) until register bit 7 is cleared.461 * This step only indicates the request is accepted by the controller.462 */463 start = jiffies + (2 * HZ); /* 2 sec */464 do {465 reg_val = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET) &466 SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP;467 } while ((reg_val != 0) && time_before(jiffies, start));468 469 /* Step 4.2: To check the completion of the transfer, poll the Fatal/Non470 * Fatal Debug Data Transfer Status [FDDTSTAT] field for 2 seconds in471 * the MPI Fatal and Non-Fatal Error Dump Capture Table.472 */473 start = jiffies + (2 * HZ); /* 2 sec */474 do {475 reg_val = pm8001_mr32(nonfatal_table_address,476 MPI_FATAL_EDUMP_TABLE_STATUS);477 } while ((!reg_val) && time_before(jiffies, start));478 479 if ((reg_val == 0x00) ||480 (reg_val == MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED) ||481 (reg_val > MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE)) {482 pm8001_ha->non_fatal_read_length = 0;483 buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 0xFFFFFFFF);484 pm8001_ha->non_fatal_count = 0;485 return (buf_copy - buf);486 } else if (reg_val ==487 MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA) {488 buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 2);489 } else if ((reg_val == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) ||490 (pm8001_ha->non_fatal_read_length >= total_len)) {491 pm8001_ha->non_fatal_read_length = 0;492 buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 4);493 pm8001_ha->non_fatal_count = 0;494 }495 accum_len = pm8001_mr32(nonfatal_table_address,496 MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);497 output_length = accum_len -498 pm8001_ha->forensic_preserved_accumulated_transfer;499 500 for (index = 0; index < output_length/4; index++)501 buf_copy += snprintf(buf_copy, PAGE_SIZE,502 "%08x ", *(temp+index));503 504 pm8001_ha->non_fatal_read_length += output_length;505 506 /* store current accumulated length to use in next iteration as507 * the previous accumulated length508 */509 pm8001_ha->forensic_preserved_accumulated_transfer = accum_len;510 return (buf_copy - buf);511}512 513/**514 * read_main_config_table - read the configure table and save it.515 * @pm8001_ha: our hba card information516 */517static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)518{519 void __iomem *address = pm8001_ha->main_cfg_tbl_addr;520 521 pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature =522 pm8001_mr32(address, MAIN_SIGNATURE_OFFSET);523 pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev =524 pm8001_mr32(address, MAIN_INTERFACE_REVISION);525 pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev =526 pm8001_mr32(address, MAIN_FW_REVISION);527 pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io =528 pm8001_mr32(address, MAIN_MAX_OUTSTANDING_IO_OFFSET);529 pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl =530 pm8001_mr32(address, MAIN_MAX_SGL_OFFSET);531 pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag =532 pm8001_mr32(address, MAIN_CNTRL_CAP_OFFSET);533 pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset =534 pm8001_mr32(address, MAIN_GST_OFFSET);535 pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset =536 pm8001_mr32(address, MAIN_IBQ_OFFSET);537 pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset =538 pm8001_mr32(address, MAIN_OBQ_OFFSET);539 540 /* read Error Dump Offset and Length */541 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset0 =542 pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET);543 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length0 =544 pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH);545 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset1 =546 pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET);547 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length1 =548 pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH);549 550 /* read GPIO LED settings from the configuration table */551 pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping =552 pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET);553 554 /* read analog Setting offset from the configuration table */555 pm8001_ha->main_cfg_tbl.pm80xx_tbl.analog_setup_table_offset =556 pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET);557 558 pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset =559 pm8001_mr32(address, MAIN_INT_VECTOR_TABLE_OFFSET);560 pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset =561 pm8001_mr32(address, MAIN_SAS_PHY_ATTR_TABLE_OFFSET);562 /* read port recover and reset timeout */563 pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer =564 pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER);565 /* read ILA and inactive firmware version */566 pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version =567 pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);568 pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =569 pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);570 571 pm8001_dbg(pm8001_ha, INIT,572 "Main cfg table: sign:%x interface rev:%x fw_rev:%x\n",573 pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature,574 pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev,575 pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev);576 577 pm8001_dbg(pm8001_ha, INIT,578 "table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n",579 pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset,580 pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset,581 pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset,582 pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset,583 pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset);584 585 pm8001_dbg(pm8001_ha, INIT,586 "Main cfg table; ila rev:%x Inactive fw rev:%x\n",587 pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version,588 pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version);589}590 591/**592 * read_general_status_table - read the general status table and save it.593 * @pm8001_ha: our hba card information594 */595static void read_general_status_table(struct pm8001_hba_info *pm8001_ha)596{597 void __iomem *address = pm8001_ha->general_stat_tbl_addr;598 pm8001_ha->gs_tbl.pm80xx_tbl.gst_len_mpistate =599 pm8001_mr32(address, GST_GSTLEN_MPIS_OFFSET);600 pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state0 =601 pm8001_mr32(address, GST_IQ_FREEZE_STATE0_OFFSET);602 pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state1 =603 pm8001_mr32(address, GST_IQ_FREEZE_STATE1_OFFSET);604 pm8001_ha->gs_tbl.pm80xx_tbl.msgu_tcnt =605 pm8001_mr32(address, GST_MSGUTCNT_OFFSET);606 pm8001_ha->gs_tbl.pm80xx_tbl.iop_tcnt =607 pm8001_mr32(address, GST_IOPTCNT_OFFSET);608 pm8001_ha->gs_tbl.pm80xx_tbl.gpio_input_val =609 pm8001_mr32(address, GST_GPIO_INPUT_VAL);610 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[0] =611 pm8001_mr32(address, GST_RERRINFO_OFFSET0);612 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[1] =613 pm8001_mr32(address, GST_RERRINFO_OFFSET1);614 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[2] =615 pm8001_mr32(address, GST_RERRINFO_OFFSET2);616 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[3] =617 pm8001_mr32(address, GST_RERRINFO_OFFSET3);618 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[4] =619 pm8001_mr32(address, GST_RERRINFO_OFFSET4);620 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[5] =621 pm8001_mr32(address, GST_RERRINFO_OFFSET5);622 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[6] =623 pm8001_mr32(address, GST_RERRINFO_OFFSET6);624 pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[7] =625 pm8001_mr32(address, GST_RERRINFO_OFFSET7);626}627/**628 * read_phy_attr_table - read the phy attribute table and save it.629 * @pm8001_ha: our hba card information630 */631static void read_phy_attr_table(struct pm8001_hba_info *pm8001_ha)632{633 void __iomem *address = pm8001_ha->pspa_q_tbl_addr;634 pm8001_ha->phy_attr_table.phystart1_16[0] =635 pm8001_mr32(address, PSPA_PHYSTATE0_OFFSET);636 pm8001_ha->phy_attr_table.phystart1_16[1] =637 pm8001_mr32(address, PSPA_PHYSTATE1_OFFSET);638 pm8001_ha->phy_attr_table.phystart1_16[2] =639 pm8001_mr32(address, PSPA_PHYSTATE2_OFFSET);640 pm8001_ha->phy_attr_table.phystart1_16[3] =641 pm8001_mr32(address, PSPA_PHYSTATE3_OFFSET);642 pm8001_ha->phy_attr_table.phystart1_16[4] =643 pm8001_mr32(address, PSPA_PHYSTATE4_OFFSET);644 pm8001_ha->phy_attr_table.phystart1_16[5] =645 pm8001_mr32(address, PSPA_PHYSTATE5_OFFSET);646 pm8001_ha->phy_attr_table.phystart1_16[6] =647 pm8001_mr32(address, PSPA_PHYSTATE6_OFFSET);648 pm8001_ha->phy_attr_table.phystart1_16[7] =649 pm8001_mr32(address, PSPA_PHYSTATE7_OFFSET);650 pm8001_ha->phy_attr_table.phystart1_16[8] =651 pm8001_mr32(address, PSPA_PHYSTATE8_OFFSET);652 pm8001_ha->phy_attr_table.phystart1_16[9] =653 pm8001_mr32(address, PSPA_PHYSTATE9_OFFSET);654 pm8001_ha->phy_attr_table.phystart1_16[10] =655 pm8001_mr32(address, PSPA_PHYSTATE10_OFFSET);656 pm8001_ha->phy_attr_table.phystart1_16[11] =657 pm8001_mr32(address, PSPA_PHYSTATE11_OFFSET);658 pm8001_ha->phy_attr_table.phystart1_16[12] =659 pm8001_mr32(address, PSPA_PHYSTATE12_OFFSET);660 pm8001_ha->phy_attr_table.phystart1_16[13] =661 pm8001_mr32(address, PSPA_PHYSTATE13_OFFSET);662 pm8001_ha->phy_attr_table.phystart1_16[14] =663 pm8001_mr32(address, PSPA_PHYSTATE14_OFFSET);664 pm8001_ha->phy_attr_table.phystart1_16[15] =665 pm8001_mr32(address, PSPA_PHYSTATE15_OFFSET);666 667 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[0] =668 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID0_OFFSET);669 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[1] =670 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID1_OFFSET);671 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[2] =672 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID2_OFFSET);673 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[3] =674 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID3_OFFSET);675 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[4] =676 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID4_OFFSET);677 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[5] =678 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID5_OFFSET);679 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[6] =680 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID6_OFFSET);681 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[7] =682 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID7_OFFSET);683 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[8] =684 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID8_OFFSET);685 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[9] =686 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID9_OFFSET);687 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[10] =688 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID10_OFFSET);689 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[11] =690 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID11_OFFSET);691 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[12] =692 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID12_OFFSET);693 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[13] =694 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID13_OFFSET);695 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[14] =696 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID14_OFFSET);697 pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[15] =698 pm8001_mr32(address, PSPA_OB_HW_EVENT_PID15_OFFSET);699 700}701 702/**703 * read_inbnd_queue_table - read the inbound queue table and save it.704 * @pm8001_ha: our hba card information705 */706static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)707{708 int i;709 void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;710 for (i = 0; i < PM8001_MAX_INB_NUM; i++) {711 u32 offset = i * 0x20;712 pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =713 get_pci_bar_index(pm8001_mr32(address,714 (offset + IB_PIPCI_BAR)));715 pm8001_ha->inbnd_q_tbl[i].pi_offset =716 pm8001_mr32(address, (offset + IB_PIPCI_BAR_OFFSET));717 }718}719 720/**721 * read_outbnd_queue_table - read the outbound queue table and save it.722 * @pm8001_ha: our hba card information723 */724static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)725{726 int i;727 void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;728 for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {729 u32 offset = i * 0x24;730 pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =731 get_pci_bar_index(pm8001_mr32(address,732 (offset + OB_CIPCI_BAR)));733 pm8001_ha->outbnd_q_tbl[i].ci_offset =734 pm8001_mr32(address, (offset + OB_CIPCI_BAR_OFFSET));735 }736}737 738/**739 * init_default_table_values - init the default table.740 * @pm8001_ha: our hba card information741 */742static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)743{744 int i;745 u32 offsetib, offsetob;746 void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;747 void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;748 u32 ib_offset = pm8001_ha->ib_offset;749 u32 ob_offset = pm8001_ha->ob_offset;750 u32 ci_offset = pm8001_ha->ci_offset;751 u32 pi_offset = pm8001_ha->pi_offset;752 753 pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr =754 pm8001_ha->memoryMap.region[AAP1].phys_addr_hi;755 pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr =756 pm8001_ha->memoryMap.region[AAP1].phys_addr_lo;757 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size =758 PM8001_EVENT_LOG_SIZE;759 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity = 0x01;760 pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr =761 pm8001_ha->memoryMap.region[IOP].phys_addr_hi;762 pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr =763 pm8001_ha->memoryMap.region[IOP].phys_addr_lo;764 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size =765 PM8001_EVENT_LOG_SIZE;766 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01;767 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01;768 769 /* Enable higher IQs and OQs, 32 to 63, bit 16 */770 if (pm8001_ha->max_q_num > 32)771 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=772 1 << 16;773 /* Disable end to end CRC checking */774 pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);775 776 for (i = 0; i < pm8001_ha->max_q_num; i++) {777 pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =778 PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);779 pm8001_ha->inbnd_q_tbl[i].upper_base_addr =780 pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi;781 pm8001_ha->inbnd_q_tbl[i].lower_base_addr =782 pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo;783 pm8001_ha->inbnd_q_tbl[i].base_virt =784 (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr;785 pm8001_ha->inbnd_q_tbl[i].total_length =786 pm8001_ha->memoryMap.region[ib_offset + i].total_len;787 pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr =788 pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi;789 pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr =790 pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo;791 pm8001_ha->inbnd_q_tbl[i].ci_virt =792 pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr;793 pm8001_write_32(pm8001_ha->inbnd_q_tbl[i].ci_virt, 0, 0);794 offsetib = i * 0x20;795 pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =796 get_pci_bar_index(pm8001_mr32(addressib,797 (offsetib + 0x14)));798 pm8001_ha->inbnd_q_tbl[i].pi_offset =799 pm8001_mr32(addressib, (offsetib + 0x18));800 pm8001_ha->inbnd_q_tbl[i].producer_idx = 0;801 pm8001_ha->inbnd_q_tbl[i].consumer_index = 0;802 803 pm8001_dbg(pm8001_ha, DEV,804 "IQ %d pi_bar 0x%x pi_offset 0x%x\n", i,805 pm8001_ha->inbnd_q_tbl[i].pi_pci_bar,806 pm8001_ha->inbnd_q_tbl[i].pi_offset);807 }808 for (i = 0; i < pm8001_ha->max_q_num; i++) {809 pm8001_ha->outbnd_q_tbl[i].element_size_cnt =810 PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);811 pm8001_ha->outbnd_q_tbl[i].upper_base_addr =812 pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi;813 pm8001_ha->outbnd_q_tbl[i].lower_base_addr =814 pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo;815 pm8001_ha->outbnd_q_tbl[i].base_virt =816 (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr;817 pm8001_ha->outbnd_q_tbl[i].total_length =818 pm8001_ha->memoryMap.region[ob_offset + i].total_len;819 pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr =820 pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi;821 pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =822 pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo;823 /* interrupt vector based on oq */824 pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24);825 pm8001_ha->outbnd_q_tbl[i].pi_virt =826 pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr;827 pm8001_write_32(pm8001_ha->outbnd_q_tbl[i].pi_virt, 0, 0);828 offsetob = i * 0x24;829 pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =830 get_pci_bar_index(pm8001_mr32(addressob,831 offsetob + 0x14));832 pm8001_ha->outbnd_q_tbl[i].ci_offset =833 pm8001_mr32(addressob, (offsetob + 0x18));834 pm8001_ha->outbnd_q_tbl[i].consumer_idx = 0;835 pm8001_ha->outbnd_q_tbl[i].producer_index = 0;836 837 pm8001_dbg(pm8001_ha, DEV,838 "OQ %d ci_bar 0x%x ci_offset 0x%x\n", i,839 pm8001_ha->outbnd_q_tbl[i].ci_pci_bar,840 pm8001_ha->outbnd_q_tbl[i].ci_offset);841 }842}843 844/**845 * update_main_config_table - update the main default table to the HBA.846 * @pm8001_ha: our hba card information847 */848static void update_main_config_table(struct pm8001_hba_info *pm8001_ha)849{850 void __iomem *address = pm8001_ha->main_cfg_tbl_addr;851 pm8001_mw32(address, MAIN_IQNPPD_HPPD_OFFSET,852 pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_q_nppd_hppd);853 pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_HI,854 pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr);855 pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_LO,856 pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr);857 pm8001_mw32(address, MAIN_EVENT_LOG_BUFF_SIZE,858 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size);859 pm8001_mw32(address, MAIN_EVENT_LOG_OPTION,860 pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity);861 pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_HI,862 pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr);863 pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_LO,864 pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr);865 pm8001_mw32(address, MAIN_PCS_EVENT_LOG_BUFF_SIZE,866 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);867 pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,868 pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);869 /* Update Fatal error interrupt vector */870 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=871 ((pm8001_ha->max_q_num - 1) << 8);872 pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,873 pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);874 pm8001_dbg(pm8001_ha, DEV,875 "Updated Fatal error interrupt vector 0x%x\n",876 pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT));877 878 pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,879 pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump);880 881 /* SPCv specific */882 pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping &= 0xCFFFFFFF;883 /* Set GPIOLED to 0x2 for LED indicator */884 pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000;885 pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET,886 pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping);887 pm8001_dbg(pm8001_ha, DEV,888 "Programming DW 0x21 in main cfg table with 0x%x\n",889 pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET));890 891 pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,892 pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);893 pm8001_mw32(address, MAIN_INT_REASSERTION_DELAY,894 pm8001_ha->main_cfg_tbl.pm80xx_tbl.interrupt_reassertion_delay);895 896 pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= 0xffff0000;897 pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=898 PORT_RECOVERY_TIMEOUT;899 if (pm8001_ha->chip_id == chip_8006) {900 pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &=901 0x0000ffff;902 pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=903 CHIP_8006_PORT_RECOVERY_TIMEOUT;904 }905 pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,906 pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);907}908 909/**910 * update_inbnd_queue_table - update the inbound queue table to the HBA.911 * @pm8001_ha: our hba card information912 * @number: entry in the queue913 */914static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,915 int number)916{917 void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;918 u16 offset = number * 0x20;919 pm8001_mw32(address, offset + IB_PROPERITY_OFFSET,920 pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt);921 pm8001_mw32(address, offset + IB_BASE_ADDR_HI_OFFSET,922 pm8001_ha->inbnd_q_tbl[number].upper_base_addr);923 pm8001_mw32(address, offset + IB_BASE_ADDR_LO_OFFSET,924 pm8001_ha->inbnd_q_tbl[number].lower_base_addr);925 pm8001_mw32(address, offset + IB_CI_BASE_ADDR_HI_OFFSET,926 pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr);927 pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET,928 pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);929 930 pm8001_dbg(pm8001_ha, DEV,931 "IQ %d: Element pri size 0x%x\n",932 number,933 pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt);934 935 pm8001_dbg(pm8001_ha, DEV,936 "IQ upr base addr 0x%x IQ lwr base addr 0x%x\n",937 pm8001_ha->inbnd_q_tbl[number].upper_base_addr,938 pm8001_ha->inbnd_q_tbl[number].lower_base_addr);939 940 pm8001_dbg(pm8001_ha, DEV,941 "CI upper base addr 0x%x CI lower base addr 0x%x\n",942 pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr,943 pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);944}945 946/**947 * update_outbnd_queue_table - update the outbound queue table to the HBA.948 * @pm8001_ha: our hba card information949 * @number: entry in the queue950 */951static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,952 int number)953{954 void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;955 u16 offset = number * 0x24;956 pm8001_mw32(address, offset + OB_PROPERITY_OFFSET,957 pm8001_ha->outbnd_q_tbl[number].element_size_cnt);958 pm8001_mw32(address, offset + OB_BASE_ADDR_HI_OFFSET,959 pm8001_ha->outbnd_q_tbl[number].upper_base_addr);960 pm8001_mw32(address, offset + OB_BASE_ADDR_LO_OFFSET,961 pm8001_ha->outbnd_q_tbl[number].lower_base_addr);962 pm8001_mw32(address, offset + OB_PI_BASE_ADDR_HI_OFFSET,963 pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr);964 pm8001_mw32(address, offset + OB_PI_BASE_ADDR_LO_OFFSET,965 pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);966 pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET,967 pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay);968 969 pm8001_dbg(pm8001_ha, DEV,970 "OQ %d: Element pri size 0x%x\n",971 number,972 pm8001_ha->outbnd_q_tbl[number].element_size_cnt);973 974 pm8001_dbg(pm8001_ha, DEV,975 "OQ upr base addr 0x%x OQ lwr base addr 0x%x\n",976 pm8001_ha->outbnd_q_tbl[number].upper_base_addr,977 pm8001_ha->outbnd_q_tbl[number].lower_base_addr);978 979 pm8001_dbg(pm8001_ha, DEV,980 "PI upper base addr 0x%x PI lower base addr 0x%x\n",981 pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr,982 pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);983}984 985/**986 * mpi_init_check - check firmware initialization status.987 * @pm8001_ha: our hba card information988 */989static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)990{991 u32 max_wait_count;992 u32 value;993 u32 gst_len_mpistate;994 995 /* Write bit0=1 to Inbound DoorBell Register to tell the SPC FW the996 table is updated */997 pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE);998 /* wait until Inbound DoorBell Clear Register toggled */999 if (IS_SPCV_12G(pm8001_ha->pdev)) {1000 max_wait_count = SPCV_DOORBELL_CLEAR_TIMEOUT;1001 } else {1002 max_wait_count = SPC_DOORBELL_CLEAR_TIMEOUT;1003 }1004 do {1005 msleep(FW_READY_INTERVAL);1006 value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);1007 value &= SPCv_MSGU_CFG_TABLE_UPDATE;1008 } while ((value != 0) && (--max_wait_count));1009 1010 if (!max_wait_count) {1011 /* additional check */1012 pm8001_dbg(pm8001_ha, FAIL,1013 "Inb doorbell clear not toggled[value:%x]\n",1014 value);1015 return -EBUSY;1016 }1017 /* check the MPI-State for initialization up to 100ms*/1018 max_wait_count = 5;/* 100 msec */1019 do {1020 msleep(FW_READY_INTERVAL);1021 gst_len_mpistate =1022 pm8001_mr32(pm8001_ha->general_stat_tbl_addr,1023 GST_GSTLEN_MPIS_OFFSET);1024 } while ((GST_MPI_STATE_INIT !=1025 (gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count));1026 if (!max_wait_count)1027 return -EBUSY;1028 1029 /* check MPI Initialization error */1030 gst_len_mpistate = gst_len_mpistate >> 16;1031 if (0x0000 != gst_len_mpistate)1032 return -EBUSY;1033 1034 /*1035 * As per controller datasheet, after successful MPI1036 * initialization minimum 500ms delay is required before1037 * issuing commands.1038 */1039 msleep(500);1040 1041 return 0;1042}1043 1044/**1045 * check_fw_ready - The LLDD check if the FW is ready, if not, return error.1046 * This function sleeps hence it must not be used in atomic context.1047 * @pm8001_ha: our hba card information1048 */1049static int check_fw_ready(struct pm8001_hba_info *pm8001_ha)1050{1051 u32 value;1052 u32 max_wait_count;1053 u32 max_wait_time;1054 u32 expected_mask;1055 int ret = 0;1056 1057 /* reset / PCIe ready */1058 max_wait_time = max_wait_count = 5; /* 100 milli sec */1059 do {1060 msleep(FW_READY_INTERVAL);1061 value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);1062 } while ((value == 0xFFFFFFFF) && (--max_wait_count));1063 1064 /* check ila, RAAE and iops status */1065 if ((pm8001_ha->chip_id != chip_8008) &&1066 (pm8001_ha->chip_id != chip_8009)) {1067 max_wait_time = max_wait_count = 180; /* 3600 milli sec */1068 expected_mask = SCRATCH_PAD_ILA_READY |1069 SCRATCH_PAD_RAAE_READY |1070 SCRATCH_PAD_IOP0_READY |1071 SCRATCH_PAD_IOP1_READY;1072 } else {1073 max_wait_time = max_wait_count = 170; /* 3400 milli sec */1074 expected_mask = SCRATCH_PAD_ILA_READY |1075 SCRATCH_PAD_RAAE_READY |1076 SCRATCH_PAD_IOP0_READY;1077 }1078 do {1079 msleep(FW_READY_INTERVAL);1080 value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);1081 } while (((value & expected_mask) !=1082 expected_mask) && (--max_wait_count));1083 if (!max_wait_count) {1084 pm8001_dbg(pm8001_ha, INIT,1085 "At least one FW component failed to load within %d millisec: Scratchpad1: 0x%x\n",1086 max_wait_time * FW_READY_INTERVAL, value);1087 ret = -1;1088 } else {1089 pm8001_dbg(pm8001_ha, MSG,1090 "All FW components ready by %d ms\n",1091 (max_wait_time - max_wait_count) * FW_READY_INTERVAL);1092 }1093 return ret;1094}1095 1096static int init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)1097{1098 void __iomem *base_addr;1099 u32 value;1100 u32 offset;1101 u32 pcibar;1102 u32 pcilogic;1103 1104 value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);1105 1106 /*1107 * lower 26 bits of SCRATCHPAD0 register describes offset within the1108 * PCIe BAR where the MPI configuration table is present1109 */1110 offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */1111 1112 pm8001_dbg(pm8001_ha, DEV, "Scratchpad 0 Offset: 0x%x value 0x%x\n",1113 offset, value);1114 /*1115 * Upper 6 bits describe the offset within PCI config space where BAR1116 * is located.1117 */1118 pcilogic = (value & 0xFC000000) >> 26;1119 pcibar = get_pci_bar_index(pcilogic);1120 pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 PCI BAR: %d\n", pcibar);1121 1122 /*1123 * Make sure the offset falls inside the ioremapped PCI BAR1124 */1125 if (offset > pm8001_ha->io_mem[pcibar].memsize) {1126 pm8001_dbg(pm8001_ha, FAIL,1127 "Main cfg tbl offset outside %u > %u\n",1128 offset, pm8001_ha->io_mem[pcibar].memsize);1129 return -EBUSY;1130 }1131 pm8001_ha->main_cfg_tbl_addr = base_addr =1132 pm8001_ha->io_mem[pcibar].memvirtaddr + offset;1133 1134 /*1135 * Validate main configuration table address: first DWord should read1136 * "PMCS"1137 */1138 value = pm8001_mr32(pm8001_ha->main_cfg_tbl_addr, 0);1139 if (memcmp(&value, "PMCS", 4) != 0) {1140 pm8001_dbg(pm8001_ha, FAIL,1141 "BAD main config signature 0x%x\n",1142 value);1143 return -EBUSY;1144 }1145 pm8001_dbg(pm8001_ha, INIT,1146 "VALID main config signature 0x%x\n", value);1147 pm8001_ha->general_stat_tbl_addr =1148 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x18) &1149 0xFFFFFF);1150 pm8001_ha->inbnd_q_tbl_addr =1151 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C) &1152 0xFFFFFF);1153 pm8001_ha->outbnd_q_tbl_addr =1154 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x20) &1155 0xFFFFFF);1156 pm8001_ha->ivt_tbl_addr =1157 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C) &1158 0xFFFFFF);1159 pm8001_ha->pspa_q_tbl_addr =1160 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) &1161 0xFFFFFF);1162 pm8001_ha->fatal_tbl_addr =1163 base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) &1164 0xFFFFFF);1165 1166 pm8001_dbg(pm8001_ha, INIT, "GST OFFSET 0x%x\n",1167 pm8001_cr32(pm8001_ha, pcibar, offset + 0x18));1168 pm8001_dbg(pm8001_ha, INIT, "INBND OFFSET 0x%x\n",1169 pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C));1170 pm8001_dbg(pm8001_ha, INIT, "OBND OFFSET 0x%x\n",1171 pm8001_cr32(pm8001_ha, pcibar, offset + 0x20));1172 pm8001_dbg(pm8001_ha, INIT, "IVT OFFSET 0x%x\n",1173 pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C));1174 pm8001_dbg(pm8001_ha, INIT, "PSPA OFFSET 0x%x\n",1175 pm8001_cr32(pm8001_ha, pcibar, offset + 0x90));1176 pm8001_dbg(pm8001_ha, INIT, "addr - main cfg %p general status %p\n",1177 pm8001_ha->main_cfg_tbl_addr,1178 pm8001_ha->general_stat_tbl_addr);1179 pm8001_dbg(pm8001_ha, INIT, "addr - inbnd %p obnd %p\n",1180 pm8001_ha->inbnd_q_tbl_addr,1181 pm8001_ha->outbnd_q_tbl_addr);1182 pm8001_dbg(pm8001_ha, INIT, "addr - pspa %p ivt %p\n",1183 pm8001_ha->pspa_q_tbl_addr,1184 pm8001_ha->ivt_tbl_addr);1185 return 0;1186}1187 1188/**1189 * pm80xx_set_thermal_config - support the thermal configuration1190 * @pm8001_ha: our hba card information.1191 */1192int1193pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)1194{1195 struct set_ctrl_cfg_req payload;1196 int rc;1197 u32 tag;1198 u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;1199 u32 page_code;1200 1201 memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));1202 rc = pm8001_tag_alloc(pm8001_ha, &tag);1203 if (rc)1204 return rc;1205 1206 payload.tag = cpu_to_le32(tag);1207 1208 if (IS_SPCV_12G(pm8001_ha->pdev))1209 page_code = THERMAL_PAGE_CODE_7H;1210 else1211 page_code = THERMAL_PAGE_CODE_8H;1212 1213 payload.cfg_pg[0] =1214 cpu_to_le32((THERMAL_LOG_ENABLE << 9) |1215 (THERMAL_ENABLE << 8) | page_code);1216 payload.cfg_pg[1] =1217 cpu_to_le32((LTEMPHIL << 24) | (RTEMPHIL << 8));1218 1219 pm8001_dbg(pm8001_ha, DEV,1220 "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",1221 payload.cfg_pg[0], payload.cfg_pg[1]);1222 1223 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,1224 sizeof(payload), 0);1225 if (rc)1226 pm8001_tag_free(pm8001_ha, tag);1227 return rc;1228 1229}1230 1231/**1232* pm80xx_set_sas_protocol_timer_config - support the SAS Protocol1233* Timer configuration page1234* @pm8001_ha: our hba card information.1235*/1236static int1237pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)1238{1239 struct set_ctrl_cfg_req payload;1240 SASProtocolTimerConfig_t SASConfigPage;1241 int rc;1242 u32 tag;1243 u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;1244 1245 memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));1246 memset(&SASConfigPage, 0, sizeof(SASProtocolTimerConfig_t));1247 1248 rc = pm8001_tag_alloc(pm8001_ha, &tag);1249 if (rc)1250 return rc;1251 1252 payload.tag = cpu_to_le32(tag);1253 1254 SASConfigPage.pageCode = cpu_to_le32(SAS_PROTOCOL_TIMER_CONFIG_PAGE);1255 SASConfigPage.MST_MSI = cpu_to_le32(3 << 15);1256 SASConfigPage.STP_SSP_MCT_TMO =1257 cpu_to_le32((STP_MCT_TMO << 16) | SSP_MCT_TMO);1258 SASConfigPage.STP_FRM_TMO =1259 cpu_to_le32((SAS_MAX_OPEN_TIME << 24) |1260 (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER);1261 SASConfigPage.STP_IDLE_TMO = cpu_to_le32(STP_IDLE_TIME);1262 1263 SASConfigPage.OPNRJT_RTRY_INTVL =1264 cpu_to_le32((SAS_MFD << 16) | SAS_OPNRJT_RTRY_INTVL);1265 SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO =1266 cpu_to_le32((SAS_DOPNRJT_RTRY_TMO << 16) | SAS_COPNRJT_RTRY_TMO);1267 SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR =1268 cpu_to_le32((SAS_DOPNRJT_RTRY_THR << 16) | SAS_COPNRJT_RTRY_THR);1269 SASConfigPage.MAX_AIP = cpu_to_le32(SAS_MAX_AIP);1270 1271 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.pageCode 0x%08x\n",1272 le32_to_cpu(SASConfigPage.pageCode));1273 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MST_MSI 0x%08x\n",1274 le32_to_cpu(SASConfigPage.MST_MSI));1275 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_SSP_MCT_TMO 0x%08x\n",1276 le32_to_cpu(SASConfigPage.STP_SSP_MCT_TMO));1277 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_FRM_TMO 0x%08x\n",1278 le32_to_cpu(SASConfigPage.STP_FRM_TMO));1279 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_IDLE_TMO 0x%08x\n",1280 le32_to_cpu(SASConfigPage.STP_IDLE_TMO));1281 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.OPNRJT_RTRY_INTVL 0x%08x\n",1282 le32_to_cpu(SASConfigPage.OPNRJT_RTRY_INTVL));1283 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO 0x%08x\n",1284 le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO));1285 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR 0x%08x\n",1286 le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR));1287 pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MAX_AIP 0x%08x\n",1288 le32_to_cpu(SASConfigPage.MAX_AIP));1289 1290 memcpy(&payload.cfg_pg, &SASConfigPage,1291 sizeof(SASProtocolTimerConfig_t));1292 1293 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,1294 sizeof(payload), 0);1295 if (rc)1296 pm8001_tag_free(pm8001_ha, tag);1297 1298 return rc;1299}1300 1301/**1302 * pm80xx_get_encrypt_info - Check for encryption1303 * @pm8001_ha: our hba card information.1304 */1305static int1306pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)1307{1308 u32 scratch3_value;1309 int ret = -1;1310 1311 /* Read encryption status from SCRATCH PAD 3 */1312 scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);1313 1314 if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==1315 SCRATCH_PAD3_ENC_READY) {1316 if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)1317 pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;1318 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1319 SCRATCH_PAD3_SMF_ENABLED)1320 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;1321 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1322 SCRATCH_PAD3_SMA_ENABLED)1323 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;1324 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1325 SCRATCH_PAD3_SMB_ENABLED)1326 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;1327 pm8001_ha->encrypt_info.status = 0;1328 pm8001_dbg(pm8001_ha, INIT,1329 "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X.Cipher mode 0x%x Sec mode 0x%x status 0x%x\n",1330 scratch3_value,1331 pm8001_ha->encrypt_info.cipher_mode,1332 pm8001_ha->encrypt_info.sec_mode,1333 pm8001_ha->encrypt_info.status);1334 ret = 0;1335 } else if ((scratch3_value & SCRATCH_PAD3_ENC_READY) ==1336 SCRATCH_PAD3_ENC_DISABLED) {1337 pm8001_dbg(pm8001_ha, INIT,1338 "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n",1339 scratch3_value);1340 pm8001_ha->encrypt_info.status = 0xFFFFFFFF;1341 pm8001_ha->encrypt_info.cipher_mode = 0;1342 pm8001_ha->encrypt_info.sec_mode = 0;1343 ret = 0;1344 } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==1345 SCRATCH_PAD3_ENC_DIS_ERR) {1346 pm8001_ha->encrypt_info.status =1347 (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;1348 if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)1349 pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;1350 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1351 SCRATCH_PAD3_SMF_ENABLED)1352 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;1353 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1354 SCRATCH_PAD3_SMA_ENABLED)1355 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;1356 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1357 SCRATCH_PAD3_SMB_ENABLED)1358 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;1359 pm8001_dbg(pm8001_ha, INIT,1360 "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n",1361 scratch3_value,1362 pm8001_ha->encrypt_info.cipher_mode,1363 pm8001_ha->encrypt_info.sec_mode,1364 pm8001_ha->encrypt_info.status);1365 } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==1366 SCRATCH_PAD3_ENC_ENA_ERR) {1367 1368 pm8001_ha->encrypt_info.status =1369 (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;1370 if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)1371 pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;1372 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1373 SCRATCH_PAD3_SMF_ENABLED)1374 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;1375 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1376 SCRATCH_PAD3_SMA_ENABLED)1377 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;1378 if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==1379 SCRATCH_PAD3_SMB_ENABLED)1380 pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;1381 1382 pm8001_dbg(pm8001_ha, INIT,1383 "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n",1384 scratch3_value,1385 pm8001_ha->encrypt_info.cipher_mode,1386 pm8001_ha->encrypt_info.sec_mode,1387 pm8001_ha->encrypt_info.status);1388 }1389 return ret;1390}1391 1392/**1393 * pm80xx_encrypt_update - update flash with encryption information1394 * @pm8001_ha: our hba card information.1395 */1396static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)1397{1398 struct kek_mgmt_req payload;1399 int rc;1400 u32 tag;1401 u32 opc = OPC_INB_KEK_MANAGEMENT;1402 1403 memset(&payload, 0, sizeof(struct kek_mgmt_req));1404 rc = pm8001_tag_alloc(pm8001_ha, &tag);1405 if (rc)1406 return rc;1407 1408 payload.tag = cpu_to_le32(tag);1409 /* Currently only one key is used. New KEK index is 1.1410 * Current KEK index is 1. Store KEK to NVRAM is 1.1411 */1412 payload.new_curidx_ksop =1413 cpu_to_le32(((1 << 24) | (1 << 16) | (1 << 8) |1414 KEK_MGMT_SUBOP_KEYCARDUPDATE));1415 1416 pm8001_dbg(pm8001_ha, DEV,1417 "Saving Encryption info to flash. payload 0x%x\n",1418 le32_to_cpu(payload.new_curidx_ksop));1419 1420 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,1421 sizeof(payload), 0);1422 if (rc)1423 pm8001_tag_free(pm8001_ha, tag);1424 1425 return rc;1426}1427 1428/**1429 * pm80xx_chip_init - the main init function that initializes whole PM8001 chip.1430 * @pm8001_ha: our hba card information1431 */1432static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)1433{1434 int ret;1435 u8 i = 0;1436 1437 /* check the firmware status */1438 if (-1 == check_fw_ready(pm8001_ha)) {1439 pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n");1440 return -EBUSY;1441 }1442 1443 /* Initialize the controller fatal error flag */1444 pm8001_ha->controller_fatal_error = false;1445 1446 /* Initialize pci space address eg: mpi offset */1447 ret = init_pci_device_addresses(pm8001_ha);1448 if (ret) {1449 pm8001_dbg(pm8001_ha, FAIL,1450 "Failed to init pci addresses");1451 return ret;1452 }1453 init_default_table_values(pm8001_ha);1454 read_main_config_table(pm8001_ha);1455 read_general_status_table(pm8001_ha);1456 read_inbnd_queue_table(pm8001_ha);1457 read_outbnd_queue_table(pm8001_ha);1458 read_phy_attr_table(pm8001_ha);1459 1460 /* update main config table ,inbound table and outbound table */1461 update_main_config_table(pm8001_ha);1462 for (i = 0; i < pm8001_ha->max_q_num; i++) {1463 update_inbnd_queue_table(pm8001_ha, i);1464 update_outbnd_queue_table(pm8001_ha, i);1465 }1466 /* notify firmware update finished and check initialization status */1467 if (0 == mpi_init_check(pm8001_ha)) {1468 pm8001_dbg(pm8001_ha, INIT, "MPI initialize successful!\n");1469 } else1470 return -EBUSY;1471 1472 return 0;1473}1474 1475static void pm80xx_chip_post_init(struct pm8001_hba_info *pm8001_ha)1476{1477 /* send SAS protocol timer configuration page to FW */1478 pm80xx_set_sas_protocol_timer_config(pm8001_ha);1479 1480 /* Check for encryption */1481 if (pm8001_ha->chip->encrypt) {1482 int ret;1483 1484 pm8001_dbg(pm8001_ha, INIT, "Checking for encryption\n");1485 ret = pm80xx_get_encrypt_info(pm8001_ha);1486 if (ret == -1) {1487 pm8001_dbg(pm8001_ha, INIT, "Encryption error !!\n");1488 if (pm8001_ha->encrypt_info.status == 0x81) {1489 pm8001_dbg(pm8001_ha, INIT,1490 "Encryption enabled with error.Saving encryption key to flash\n");1491 pm80xx_encrypt_update(pm8001_ha);1492 }1493 }1494 }1495}1496 1497static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)1498{1499 u32 max_wait_count;1500 u32 value;1501 u32 gst_len_mpistate;1502 int ret;1503 1504 ret = init_pci_device_addresses(pm8001_ha);1505 if (ret) {1506 pm8001_dbg(pm8001_ha, FAIL,1507 "Failed to init pci addresses");1508 return ret;1509 }1510 1511 /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the1512 table is stop */1513 pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET);1514 1515 /* wait until Inbound DoorBell Clear Register toggled */1516 if (IS_SPCV_12G(pm8001_ha->pdev)) {1517 max_wait_count = SPCV_DOORBELL_CLEAR_TIMEOUT;1518 } else {1519 max_wait_count = SPC_DOORBELL_CLEAR_TIMEOUT;1520 }1521 do {1522 msleep(FW_READY_INTERVAL);1523 value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);1524 value &= SPCv_MSGU_CFG_TABLE_RESET;1525 } while ((value != 0) && (--max_wait_count));1526 1527 if (!max_wait_count) {1528 pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:IBDB value/=%x\n", value);1529 return -1;1530 }1531 1532 /* check the MPI-State for termination in progress */1533 /* wait until Inbound DoorBell Clear Register toggled */1534 max_wait_count = 100; /* 2 sec for spcv/ve */1535 do {1536 msleep(FW_READY_INTERVAL);1537 gst_len_mpistate =1538 pm8001_mr32(pm8001_ha->general_stat_tbl_addr,1539 GST_GSTLEN_MPIS_OFFSET);1540 if (GST_MPI_STATE_UNINIT ==1541 (gst_len_mpistate & GST_MPI_STATE_MASK))1542 break;1543 } while (--max_wait_count);1544 if (!max_wait_count) {1545 pm8001_dbg(pm8001_ha, FAIL, " TIME OUT MPI State = 0x%x\n",1546 gst_len_mpistate & GST_MPI_STATE_MASK);1547 return -1;1548 }1549 1550 return 0;1551}1552 1553/**1554 * pm80xx_fatal_errors - returns non-zero *ONLY* when fatal errors1555 * @pm8001_ha: our hba card information1556 *1557 * Fatal errors are recoverable only after a host reboot.1558 */1559int1560pm80xx_fatal_errors(struct pm8001_hba_info *pm8001_ha)1561{1562 int ret = 0;1563 u32 scratch_pad_rsvd0 = pm8001_cr32(pm8001_ha, 0,1564 MSGU_SCRATCH_PAD_RSVD_0);1565 u32 scratch_pad_rsvd1 = pm8001_cr32(pm8001_ha, 0,1566 MSGU_SCRATCH_PAD_RSVD_1);1567 u32 scratch_pad1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);1568 u32 scratch_pad2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);1569 u32 scratch_pad3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);1570 1571 if (pm8001_ha->chip_id != chip_8006 &&1572 pm8001_ha->chip_id != chip_8074 &&1573 pm8001_ha->chip_id != chip_8076) {1574 return 0;1575 }1576 1577 if (MSGU_SCRATCHPAD1_STATE_FATAL_ERROR(scratch_pad1)) {1578 pm8001_dbg(pm8001_ha, FAIL,1579 "Fatal error SCRATCHPAD1 = 0x%x SCRATCHPAD2 = 0x%x SCRATCHPAD3 = 0x%x SCRATCHPAD_RSVD0 = 0x%x SCRATCHPAD_RSVD1 = 0x%x\n",1580 scratch_pad1, scratch_pad2, scratch_pad3,1581 scratch_pad_rsvd0, scratch_pad_rsvd1);1582 ret = 1;1583 }1584 1585 return ret;1586}1587 1588/**1589 * pm80xx_chip_soft_rst - soft reset the PM8001 chip, so that all1590 * FW register status are reset to the originated status.1591 * @pm8001_ha: our hba card information1592 */1593 1594static int1595pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)1596{1597 u32 regval;1598 u32 bootloader_state;1599 u32 ibutton0, ibutton1;1600 1601 /* Process MPI table uninitialization only if FW is ready */1602 if (!pm8001_ha->controller_fatal_error) {1603 /* Check if MPI is in ready state to reset */1604 if (mpi_uninit_check(pm8001_ha) != 0) {1605 u32 r0 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);1606 u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);1607 u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);1608 u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);1609 pm8001_dbg(pm8001_ha, FAIL,1610 "MPI state is not ready scratch: %x:%x:%x:%x\n",1611 r0, r1, r2, r3);1612 /* if things aren't ready but the bootloader is ok then1613 * try the reset anyway.1614 */1615 if (r1 & SCRATCH_PAD1_BOOTSTATE_MASK)1616 return -1;1617 }1618 }1619 /* checked for reset register normal state; 0x0 */1620 regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);1621 pm8001_dbg(pm8001_ha, INIT, "reset register before write : 0x%x\n",1622 regval);1623 1624 pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE);1625 msleep(500);1626 1627 regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);1628 pm8001_dbg(pm8001_ha, INIT, "reset register after write 0x%x\n",1629 regval);1630 1631 if ((regval & SPCv_SOFT_RESET_READ_MASK) ==1632 SPCv_SOFT_RESET_NORMAL_RESET_OCCURED) {1633 pm8001_dbg(pm8001_ha, MSG,1634 " soft reset successful [regval: 0x%x]\n",1635 regval);1636 } else {1637 pm8001_dbg(pm8001_ha, MSG,1638 " soft reset failed [regval: 0x%x]\n",1639 regval);1640 1641 /* check bootloader is successfully executed or in HDA mode */1642 bootloader_state =1643 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1) &1644 SCRATCH_PAD1_BOOTSTATE_MASK;1645 1646 if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM) {1647 pm8001_dbg(pm8001_ha, MSG,1648 "Bootloader state - HDA mode SEEPROM\n");1649 } else if (bootloader_state ==1650 SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP) {1651 pm8001_dbg(pm8001_ha, MSG,1652 "Bootloader state - HDA mode Bootstrap Pin\n");1653 } else if (bootloader_state ==1654 SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET) {1655 pm8001_dbg(pm8001_ha, MSG,1656 "Bootloader state - HDA mode soft reset\n");1657 } else if (bootloader_state ==1658 SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR) {1659 pm8001_dbg(pm8001_ha, MSG,1660 "Bootloader state-HDA mode critical error\n");1661 }1662 return -EBUSY;1663 }1664 1665 /* check the firmware status after reset */1666 if (-1 == check_fw_ready(pm8001_ha)) {1667 pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n");1668 /* check iButton feature support for motherboard controller */1669 if (pm8001_ha->pdev->subsystem_vendor !=1670 PCI_VENDOR_ID_ADAPTEC2 &&1671 pm8001_ha->pdev->subsystem_vendor !=1672 PCI_VENDOR_ID_ATTO &&1673 pm8001_ha->pdev->subsystem_vendor != 0) {1674 ibutton0 = pm8001_cr32(pm8001_ha, 0,1675 MSGU_SCRATCH_PAD_RSVD_0);1676 ibutton1 = pm8001_cr32(pm8001_ha, 0,1677 MSGU_SCRATCH_PAD_RSVD_1);1678 if (!ibutton0 && !ibutton1) {1679 pm8001_dbg(pm8001_ha, FAIL,1680 "iButton Feature is not Available!!!\n");1681 return -EBUSY;1682 }1683 if (ibutton0 == 0xdeadbeef && ibutton1 == 0xdeadbeef) {1684 pm8001_dbg(pm8001_ha, FAIL,1685 "CRC Check for iButton Feature Failed!!!\n");1686 return -EBUSY;1687 }1688 }1689 }1690 pm8001_dbg(pm8001_ha, INIT, "SPCv soft reset Complete\n");1691 return 0;1692}1693 1694static void pm80xx_hw_chip_rst(struct pm8001_hba_info *pm8001_ha)1695{1696 u32 i;1697 1698 pm8001_dbg(pm8001_ha, INIT, "chip reset start\n");1699 1700 /* do SPCv chip reset. */1701 pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, 0x11);1702 pm8001_dbg(pm8001_ha, INIT, "SPC soft reset Complete\n");1703 1704 /* Check this ..whether delay is required or no */1705 /* delay 10 usec */1706 udelay(10);1707 1708 /* wait for 20 msec until the firmware gets reloaded */1709 i = 20;1710 do {1711 mdelay(1);1712 } while ((--i) != 0);1713 1714 pm8001_dbg(pm8001_ha, INIT, "chip reset finished\n");1715}1716 1717/**1718 * pm80xx_chip_interrupt_enable - enable PM8001 chip interrupt1719 * @pm8001_ha: our hba card information1720 * @vec: interrupt number to enable1721 */1722static void1723pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)1724{1725 if (!pm8001_ha->use_msix) {1726 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_CLEAR_ALL);1727 pm8001_cw32(pm8001_ha, 0, MSGU_ODCR, ODCR_CLEAR_ALL);1728 return;1729 }1730 1731 if (vec < 32)1732 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, 1U << vec);1733 else1734 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR_U, 1U << (vec - 32));1735}1736 1737/**1738 * pm80xx_chip_interrupt_disable - disable PM8001 chip interrupt1739 * @pm8001_ha: our hba card information1740 * @vec: interrupt number to disable1741 */1742static void1743pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)1744{1745 if (!pm8001_ha->use_msix) {1746 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, ODMR_MASK_ALL);1747 return;1748 }1749 1750 if (vec == 0xFF) {1751 /* disable all vectors 0-31, 32-63 */1752 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 0xFFFFFFFF);1753 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U, 0xFFFFFFFF);1754 } else if (vec < 32) {1755 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 1U << vec);1756 } else {1757 pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U, 1U << (vec - 32));1758 }1759}1760 1761/**1762 * mpi_ssp_completion - process the event that FW response to the SSP request.1763 * @pm8001_ha: our hba card information1764 * @piomb: the message contents of this outbound message.1765 *1766 * When FW has completed a ssp request for example a IO request, after it has1767 * filled the SG data with the data, it will trigger this event representing1768 * that he has finished the job; please check the corresponding buffer.1769 * So we will tell the caller who maybe waiting the result to tell upper layer1770 * that the task has been finished.1771 */1772static void1773mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)1774{1775 struct sas_task *t;1776 struct pm8001_ccb_info *ccb;1777 unsigned long flags;1778 u32 status;1779 u32 param;1780 u32 tag;1781 struct ssp_completion_resp *psspPayload;1782 struct task_status_struct *ts;1783 struct ssp_response_iu *iu;1784 struct pm8001_device *pm8001_dev;1785 psspPayload = (struct ssp_completion_resp *)(piomb + 4);1786 status = le32_to_cpu(psspPayload->status);1787 tag = le32_to_cpu(psspPayload->tag);1788 ccb = &pm8001_ha->ccb_info[tag];1789 if ((status == IO_ABORTED) && ccb->open_retry) {1790 /* Being completed by another */1791 ccb->open_retry = 0;1792 return;1793 }1794 pm8001_dev = ccb->device;1795 param = le32_to_cpu(psspPayload->param);1796 t = ccb->task;1797 1798 if (status && status != IO_UNDERFLOW)1799 pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", status);1800 if (unlikely(!t || !t->lldd_task || !t->dev))1801 return;1802 ts = &t->task_status;1803 1804 pm8001_dbg(pm8001_ha, DEV,1805 "tag::0x%x, status::0x%x task::0x%p\n", tag, status, t);1806 1807 /* Print sas address of IO failed device */1808 if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&1809 (status != IO_UNDERFLOW))1810 pm8001_dbg(pm8001_ha, FAIL, "SAS Address of IO Failure Drive:%016llx\n",1811 SAS_ADDR(t->dev->sas_addr));1812 1813 switch (status) {1814 case IO_SUCCESS:1815 pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS ,param = 0x%x\n",1816 param);1817 if (param == 0) {1818 ts->resp = SAS_TASK_COMPLETE;1819 ts->stat = SAS_SAM_STAT_GOOD;1820 } else {1821 ts->resp = SAS_TASK_COMPLETE;1822 ts->stat = SAS_PROTO_RESPONSE;1823 ts->residual = param;1824 iu = &psspPayload->ssp_resp_iu;1825 sas_ssp_task_response(pm8001_ha->dev, t, iu);1826 }1827 if (pm8001_dev)1828 atomic_dec(&pm8001_dev->running_req);1829 break;1830 case IO_ABORTED:1831 pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");1832 ts->resp = SAS_TASK_COMPLETE;1833 ts->stat = SAS_ABORTED_TASK;1834 if (pm8001_dev)1835 atomic_dec(&pm8001_dev->running_req);1836 break;1837 case IO_UNDERFLOW:1838 /* SSP Completion with error */1839 pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW ,param = 0x%x\n",1840 param);1841 ts->resp = SAS_TASK_COMPLETE;1842 ts->stat = SAS_DATA_UNDERRUN;1843 ts->residual = param;1844 if (pm8001_dev)1845 atomic_dec(&pm8001_dev->running_req);1846 break;1847 case IO_NO_DEVICE:1848 pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");1849 ts->resp = SAS_TASK_UNDELIVERED;1850 ts->stat = SAS_PHY_DOWN;1851 if (pm8001_dev)1852 atomic_dec(&pm8001_dev->running_req);1853 break;1854 case IO_XFER_ERROR_BREAK:1855 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");1856 ts->resp = SAS_TASK_COMPLETE;1857 ts->stat = SAS_OPEN_REJECT;1858 /* Force the midlayer to retry */1859 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;1860 if (pm8001_dev)1861 atomic_dec(&pm8001_dev->running_req);1862 break;1863 case IO_XFER_ERROR_PHY_NOT_READY:1864 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");1865 ts->resp = SAS_TASK_COMPLETE;1866 ts->stat = SAS_OPEN_REJECT;1867 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;1868 if (pm8001_dev)1869 atomic_dec(&pm8001_dev->running_req);1870 break;1871 case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME:1872 pm8001_dbg(pm8001_ha, IO,1873 "IO_XFER_ERROR_INVALID_SSP_RSP_FRAME\n");1874 ts->resp = SAS_TASK_COMPLETE;1875 ts->stat = SAS_OPEN_REJECT;1876 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;1877 if (pm8001_dev)1878 atomic_dec(&pm8001_dev->running_req);1879 break;1880 case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:1881 pm8001_dbg(pm8001_ha, IO,1882 "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");1883 ts->resp = SAS_TASK_COMPLETE;1884 ts->stat = SAS_OPEN_REJECT;1885 ts->open_rej_reason = SAS_OREJ_EPROTO;1886 if (pm8001_dev)1887 atomic_dec(&pm8001_dev->running_req);1888 break;1889 case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:1890 pm8001_dbg(pm8001_ha, IO,1891 "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");1892 ts->resp = SAS_TASK_COMPLETE;1893 ts->stat = SAS_OPEN_REJECT;1894 ts->open_rej_reason = SAS_OREJ_UNKNOWN;1895 if (pm8001_dev)1896 atomic_dec(&pm8001_dev->running_req);1897 break;1898 case IO_OPEN_CNX_ERROR_BREAK:1899 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");1900 ts->resp = SAS_TASK_COMPLETE;1901 ts->stat = SAS_OPEN_REJECT;1902 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;1903 if (pm8001_dev)1904 atomic_dec(&pm8001_dev->running_req);1905 break;1906 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:1907 case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:1908 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:1909 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:1910 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:1911 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:1912 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");1913 ts->resp = SAS_TASK_COMPLETE;1914 ts->stat = SAS_OPEN_REJECT;1915 ts->open_rej_reason = SAS_OREJ_UNKNOWN;1916 if (!t->uldd_task)1917 pm8001_handle_event(pm8001_ha,1918 pm8001_dev,1919 IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);1920 break;1921 case IO_OPEN_CNX_ERROR_BAD_DESTINATION:1922 pm8001_dbg(pm8001_ha, IO,1923 "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");1924 ts->resp = SAS_TASK_COMPLETE;1925 ts->stat = SAS_OPEN_REJECT;1926 ts->open_rej_reason = SAS_OREJ_BAD_DEST;1927 if (pm8001_dev)1928 atomic_dec(&pm8001_dev->running_req);1929 break;1930 case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:1931 pm8001_dbg(pm8001_ha, IO,1932 "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");1933 ts->resp = SAS_TASK_COMPLETE;1934 ts->stat = SAS_OPEN_REJECT;1935 ts->open_rej_reason = SAS_OREJ_CONN_RATE;1936 if (pm8001_dev)1937 atomic_dec(&pm8001_dev->running_req);1938 break;1939 case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:1940 pm8001_dbg(pm8001_ha, IO,1941 "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");1942 ts->resp = SAS_TASK_UNDELIVERED;1943 ts->stat = SAS_OPEN_REJECT;1944 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;1945 if (pm8001_dev)1946 atomic_dec(&pm8001_dev->running_req);1947 break;1948 case IO_XFER_ERROR_NAK_RECEIVED:1949 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");1950 ts->resp = SAS_TASK_COMPLETE;1951 ts->stat = SAS_OPEN_REJECT;1952 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;1953 if (pm8001_dev)1954 atomic_dec(&pm8001_dev->running_req);1955 break;1956 case IO_XFER_ERROR_ACK_NAK_TIMEOUT:1957 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");1958 ts->resp = SAS_TASK_COMPLETE;1959 ts->stat = SAS_NAK_R_ERR;1960 if (pm8001_dev)1961 atomic_dec(&pm8001_dev->running_req);1962 break;1963 case IO_XFER_ERROR_DMA:1964 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");1965 ts->resp = SAS_TASK_COMPLETE;1966 ts->stat = SAS_OPEN_REJECT;1967 if (pm8001_dev)1968 atomic_dec(&pm8001_dev->running_req);1969 break;1970 case IO_XFER_OPEN_RETRY_TIMEOUT:1971 pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");1972 ts->resp = SAS_TASK_COMPLETE;1973 ts->stat = SAS_OPEN_REJECT;1974 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;1975 if (pm8001_dev)1976 atomic_dec(&pm8001_dev->running_req);1977 break;1978 case IO_XFER_ERROR_OFFSET_MISMATCH:1979 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");1980 ts->resp = SAS_TASK_COMPLETE;1981 ts->stat = SAS_OPEN_REJECT;1982 if (pm8001_dev)1983 atomic_dec(&pm8001_dev->running_req);1984 break;1985 case IO_PORT_IN_RESET:1986 pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");1987 ts->resp = SAS_TASK_COMPLETE;1988 ts->stat = SAS_OPEN_REJECT;1989 if (pm8001_dev)1990 atomic_dec(&pm8001_dev->running_req);1991 break;1992 case IO_DS_NON_OPERATIONAL:1993 pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");1994 ts->resp = SAS_TASK_COMPLETE;1995 ts->stat = SAS_OPEN_REJECT;1996 if (!t->uldd_task)1997 pm8001_handle_event(pm8001_ha,1998 pm8001_dev,1999 IO_DS_NON_OPERATIONAL);2000 break;2001 case IO_DS_IN_RECOVERY:2002 pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");2003 ts->resp = SAS_TASK_COMPLETE;2004 ts->stat = SAS_OPEN_REJECT;2005 if (pm8001_dev)2006 atomic_dec(&pm8001_dev->running_req);2007 break;2008 case IO_TM_TAG_NOT_FOUND:2009 pm8001_dbg(pm8001_ha, IO, "IO_TM_TAG_NOT_FOUND\n");2010 ts->resp = SAS_TASK_COMPLETE;2011 ts->stat = SAS_OPEN_REJECT;2012 if (pm8001_dev)2013 atomic_dec(&pm8001_dev->running_req);2014 break;2015 case IO_SSP_EXT_IU_ZERO_LEN_ERROR:2016 pm8001_dbg(pm8001_ha, IO, "IO_SSP_EXT_IU_ZERO_LEN_ERROR\n");2017 ts->resp = SAS_TASK_COMPLETE;2018 ts->stat = SAS_OPEN_REJECT;2019 if (pm8001_dev)2020 atomic_dec(&pm8001_dev->running_req);2021 break;2022 case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:2023 pm8001_dbg(pm8001_ha, IO,2024 "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");2025 ts->resp = SAS_TASK_COMPLETE;2026 ts->stat = SAS_OPEN_REJECT;2027 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;2028 if (pm8001_dev)2029 atomic_dec(&pm8001_dev->running_req);2030 break;2031 default:2032 pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);2033 /* not allowed case. Therefore, return failed status */2034 ts->resp = SAS_TASK_COMPLETE;2035 ts->stat = SAS_OPEN_REJECT;2036 if (pm8001_dev)2037 atomic_dec(&pm8001_dev->running_req);2038 break;2039 }2040 pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n",2041 psspPayload->ssp_resp_iu.status);2042 spin_lock_irqsave(&t->task_state_lock, flags);2043 t->task_state_flags &= ~SAS_TASK_STATE_PENDING;2044 t->task_state_flags |= SAS_TASK_STATE_DONE;2045 if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {2046 spin_unlock_irqrestore(&t->task_state_lock, flags);2047 pm8001_dbg(pm8001_ha, FAIL,2048 "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",2049 t, status, ts->resp, ts->stat);2050 pm8001_ccb_task_free(pm8001_ha, ccb);2051 if (t->slow_task)2052 complete(&t->slow_task->completion);2053 } else {2054 spin_unlock_irqrestore(&t->task_state_lock, flags);2055 pm8001_ccb_task_free_done(pm8001_ha, ccb);2056 }2057}2058 2059/*See the comments for mpi_ssp_completion */2060static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb)2061{2062 struct sas_task *t;2063 unsigned long flags;2064 struct task_status_struct *ts;2065 struct pm8001_ccb_info *ccb;2066 struct pm8001_device *pm8001_dev;2067 struct ssp_event_resp *psspPayload =2068 (struct ssp_event_resp *)(piomb + 4);2069 u32 event = le32_to_cpu(psspPayload->event);2070 u32 tag = le32_to_cpu(psspPayload->tag);2071 u32 port_id = le32_to_cpu(psspPayload->port_id);2072 2073 ccb = &pm8001_ha->ccb_info[tag];2074 t = ccb->task;2075 pm8001_dev = ccb->device;2076 if (event)2077 pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", event);2078 if (unlikely(!t || !t->lldd_task || !t->dev))2079 return;2080 ts = &t->task_status;2081 pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",2082 port_id, tag, event);2083 switch (event) {2084 case IO_OVERFLOW:2085 pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");2086 ts->resp = SAS_TASK_COMPLETE;2087 ts->stat = SAS_DATA_OVERRUN;2088 ts->residual = 0;2089 if (pm8001_dev)2090 atomic_dec(&pm8001_dev->running_req);2091 break;2092 case IO_XFER_ERROR_BREAK:2093 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");2094 pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK);2095 return;2096 case IO_XFER_ERROR_PHY_NOT_READY:2097 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");2098 ts->resp = SAS_TASK_COMPLETE;2099 ts->stat = SAS_OPEN_REJECT;2100 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;2101 break;2102 case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:2103 pm8001_dbg(pm8001_ha, IO,2104 "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");2105 ts->resp = SAS_TASK_COMPLETE;2106 ts->stat = SAS_OPEN_REJECT;2107 ts->open_rej_reason = SAS_OREJ_EPROTO;2108 break;2109 case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:2110 pm8001_dbg(pm8001_ha, IO,2111 "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");2112 ts->resp = SAS_TASK_COMPLETE;2113 ts->stat = SAS_OPEN_REJECT;2114 ts->open_rej_reason = SAS_OREJ_UNKNOWN;2115 break;2116 case IO_OPEN_CNX_ERROR_BREAK:2117 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");2118 ts->resp = SAS_TASK_COMPLETE;2119 ts->stat = SAS_OPEN_REJECT;2120 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;2121 break;2122 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:2123 case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:2124 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:2125 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:2126 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:2127 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:2128 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");2129 ts->resp = SAS_TASK_COMPLETE;2130 ts->stat = SAS_OPEN_REJECT;2131 ts->open_rej_reason = SAS_OREJ_UNKNOWN;2132 if (!t->uldd_task)2133 pm8001_handle_event(pm8001_ha,2134 pm8001_dev,2135 IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);2136 break;2137 case IO_OPEN_CNX_ERROR_BAD_DESTINATION:2138 pm8001_dbg(pm8001_ha, IO,2139 "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");2140 ts->resp = SAS_TASK_COMPLETE;2141 ts->stat = SAS_OPEN_REJECT;2142 ts->open_rej_reason = SAS_OREJ_BAD_DEST;2143 break;2144 case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:2145 pm8001_dbg(pm8001_ha, IO,2146 "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");2147 ts->resp = SAS_TASK_COMPLETE;2148 ts->stat = SAS_OPEN_REJECT;2149 ts->open_rej_reason = SAS_OREJ_CONN_RATE;2150 break;2151 case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:2152 pm8001_dbg(pm8001_ha, IO,2153 "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");2154 ts->resp = SAS_TASK_COMPLETE;2155 ts->stat = SAS_OPEN_REJECT;2156 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;2157 break;2158 case IO_XFER_ERROR_NAK_RECEIVED:2159 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");2160 ts->resp = SAS_TASK_COMPLETE;2161 ts->stat = SAS_OPEN_REJECT;2162 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;2163 break;2164 case IO_XFER_ERROR_ACK_NAK_TIMEOUT:2165 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");2166 ts->resp = SAS_TASK_COMPLETE;2167 ts->stat = SAS_NAK_R_ERR;2168 break;2169 case IO_XFER_OPEN_RETRY_TIMEOUT:2170 pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");2171 pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT);2172 return;2173 case IO_XFER_ERROR_UNEXPECTED_PHASE:2174 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");2175 ts->resp = SAS_TASK_COMPLETE;2176 ts->stat = SAS_DATA_OVERRUN;2177 break;2178 case IO_XFER_ERROR_XFER_RDY_OVERRUN:2179 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");2180 ts->resp = SAS_TASK_COMPLETE;2181 ts->stat = SAS_DATA_OVERRUN;2182 break;2183 case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:2184 pm8001_dbg(pm8001_ha, IO,2185 "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");2186 ts->resp = SAS_TASK_COMPLETE;2187 ts->stat = SAS_DATA_OVERRUN;2188 break;2189 case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:2190 pm8001_dbg(pm8001_ha, IO,2191 "IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n");2192 ts->resp = SAS_TASK_COMPLETE;2193 ts->stat = SAS_DATA_OVERRUN;2194 break;2195 case IO_XFER_ERROR_OFFSET_MISMATCH:2196 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");2197 ts->resp = SAS_TASK_COMPLETE;2198 ts->stat = SAS_DATA_OVERRUN;2199 break;2200 case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:2201 pm8001_dbg(pm8001_ha, IO,2202 "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");2203 ts->resp = SAS_TASK_COMPLETE;2204 ts->stat = SAS_DATA_OVERRUN;2205 break;2206 case IO_XFER_ERROR_INTERNAL_CRC_ERROR:2207 pm8001_dbg(pm8001_ha, IOERR,2208 "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n");2209 /* TBC: used default set values */2210 ts->resp = SAS_TASK_COMPLETE;2211 ts->stat = SAS_DATA_OVERRUN;2212 break;2213 case IO_XFER_CMD_FRAME_ISSUED:2214 pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");2215 return;2216 default:2217 pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event);2218 /* not allowed case. Therefore, return failed status */2219 ts->resp = SAS_TASK_COMPLETE;2220 ts->stat = SAS_DATA_OVERRUN;2221 break;2222 }2223 spin_lock_irqsave(&t->task_state_lock, flags);2224 t->task_state_flags &= ~SAS_TASK_STATE_PENDING;2225 t->task_state_flags |= SAS_TASK_STATE_DONE;2226 if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {2227 spin_unlock_irqrestore(&t->task_state_lock, flags);2228 pm8001_dbg(pm8001_ha, FAIL,2229 "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",2230 t, event, ts->resp, ts->stat);2231 pm8001_ccb_task_free(pm8001_ha, ccb);2232 } else {2233 spin_unlock_irqrestore(&t->task_state_lock, flags);2234 pm8001_ccb_task_free_done(pm8001_ha, ccb);2235 }2236}2237 2238/*See the comments for mpi_ssp_completion */2239static void2240mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,2241 struct outbound_queue_table *circularQ, void *piomb)2242{2243 struct sas_task *t;2244 struct pm8001_ccb_info *ccb;2245 u32 param;2246 u32 status;2247 u32 tag;2248 int i, j;2249 u8 sata_addr_low[4];2250 u32 temp_sata_addr_low, temp_sata_addr_hi;2251 u8 sata_addr_hi[4];2252 struct sata_completion_resp *psataPayload;2253 struct task_status_struct *ts;2254 struct ata_task_resp *resp ;2255 u32 *sata_resp;2256 struct pm8001_device *pm8001_dev;2257 unsigned long flags;2258 2259 psataPayload = (struct sata_completion_resp *)(piomb + 4);2260 status = le32_to_cpu(psataPayload->status);2261 param = le32_to_cpu(psataPayload->param);2262 tag = le32_to_cpu(psataPayload->tag);2263 2264 ccb = &pm8001_ha->ccb_info[tag];2265 t = ccb->task;2266 pm8001_dev = ccb->device;2267 2268 if (t) {2269 if (t->dev && (t->dev->lldd_dev))2270 pm8001_dev = t->dev->lldd_dev;2271 } else {2272 pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",2273 ccb->ccb_tag);2274 pm8001_ccb_free(pm8001_ha, ccb);2275 return;2276 }2277 2278 2279 if (pm8001_dev && unlikely(!t->lldd_task || !t->dev))2280 return;2281 2282 ts = &t->task_status;2283 2284 if (status != IO_SUCCESS) {2285 pm8001_dbg(pm8001_ha, FAIL,2286 "IO failed device_id %u status 0x%x tag %d\n",2287 pm8001_dev->device_id, status, tag);2288 }2289 2290 /* Print sas address of IO failed device */2291 if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&2292 (status != IO_UNDERFLOW)) {2293 if (!((t->dev->parent) &&2294 (dev_is_expander(t->dev->parent->dev_type)))) {2295 for (i = 0, j = 4; i <= 3 && j <= 7; i++, j++)2296 sata_addr_low[i] = pm8001_ha->sas_addr[j];2297 for (i = 0, j = 0; i <= 3 && j <= 3; i++, j++)2298 sata_addr_hi[i] = pm8001_ha->sas_addr[j];2299 memcpy(&temp_sata_addr_low, sata_addr_low,2300 sizeof(sata_addr_low));2301 memcpy(&temp_sata_addr_hi, sata_addr_hi,2302 sizeof(sata_addr_hi));2303 temp_sata_addr_hi = (((temp_sata_addr_hi >> 24) & 0xff)2304 |((temp_sata_addr_hi << 8) &2305 0xff0000) |2306 ((temp_sata_addr_hi >> 8)2307 & 0xff00) |2308 ((temp_sata_addr_hi << 24) &2309 0xff000000));2310 temp_sata_addr_low = ((((temp_sata_addr_low >> 24)2311 & 0xff) |2312 ((temp_sata_addr_low << 8)2313 & 0xff0000) |2314 ((temp_sata_addr_low >> 8)2315 & 0xff00) |2316 ((temp_sata_addr_low << 24)2317 & 0xff000000)) +2318 pm8001_dev->attached_phy +2319 0x10);2320 pm8001_dbg(pm8001_ha, FAIL,2321 "SAS Address of IO Failure Drive:%08x%08x\n",2322 temp_sata_addr_hi,2323 temp_sata_addr_low);2324 2325 } else {2326 pm8001_dbg(pm8001_ha, FAIL,2327 "SAS Address of IO Failure Drive:%016llx\n",2328 SAS_ADDR(t->dev->sas_addr));2329 }2330 }2331 switch (status) {2332 case IO_SUCCESS:2333 pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");2334 if (param == 0) {2335 ts->resp = SAS_TASK_COMPLETE;2336 ts->stat = SAS_SAM_STAT_GOOD;2337 } else {2338 u8 len;2339 ts->resp = SAS_TASK_COMPLETE;2340 ts->stat = SAS_PROTO_RESPONSE;2341 ts->residual = param;2342 pm8001_dbg(pm8001_ha, IO,2343 "SAS_PROTO_RESPONSE len = %d\n",2344 param);2345 sata_resp = &psataPayload->sata_resp[0];2346 resp = (struct ata_task_resp *)ts->buf;2347 if (t->ata_task.dma_xfer == 0 &&2348 t->data_dir == DMA_FROM_DEVICE) {2349 len = sizeof(struct pio_setup_fis);2350 pm8001_dbg(pm8001_ha, IO,2351 "PIO read len = %d\n", len);2352 } else if (t->ata_task.use_ncq &&2353 t->data_dir != DMA_NONE) {2354 len = sizeof(struct set_dev_bits_fis);2355 pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",2356 len);2357 } else {2358 len = sizeof(struct dev_to_host_fis);2359 pm8001_dbg(pm8001_ha, IO, "other len = %d\n",2360 len);2361 }2362 if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {2363 resp->frame_len = len;2364 memcpy(&resp->ending_fis[0], sata_resp, len);2365 ts->buf_valid_size = sizeof(*resp);2366 } else2367 pm8001_dbg(pm8001_ha, IO,2368 "response too large\n");2369 }2370 if (pm8001_dev)2371 atomic_dec(&pm8001_dev->running_req);2372 break;2373 case IO_ABORTED:2374 pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");2375 ts->resp = SAS_TASK_COMPLETE;2376 ts->stat = SAS_ABORTED_TASK;2377 if (pm8001_dev)2378 atomic_dec(&pm8001_dev->running_req);2379 break;2380 /* following cases are to do cases */2381 case IO_UNDERFLOW:2382 /* SATA Completion with error */2383 pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW param = %d\n", param);2384 ts->resp = SAS_TASK_COMPLETE;2385 ts->stat = SAS_DATA_UNDERRUN;2386 ts->residual = param;2387 if (pm8001_dev)2388 atomic_dec(&pm8001_dev->running_req);2389 break;2390 case IO_NO_DEVICE:2391 pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");2392 ts->resp = SAS_TASK_UNDELIVERED;2393 ts->stat = SAS_PHY_DOWN;2394 if (pm8001_dev)2395 atomic_dec(&pm8001_dev->running_req);2396 break;2397 case IO_XFER_ERROR_BREAK:2398 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");2399 ts->resp = SAS_TASK_COMPLETE;2400 ts->stat = SAS_INTERRUPTED;2401 if (pm8001_dev)2402 atomic_dec(&pm8001_dev->running_req);2403 break;2404 case IO_XFER_ERROR_PHY_NOT_READY:2405 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");2406 ts->resp = SAS_TASK_COMPLETE;2407 ts->stat = SAS_OPEN_REJECT;2408 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;2409 if (pm8001_dev)2410 atomic_dec(&pm8001_dev->running_req);2411 break;2412 case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:2413 pm8001_dbg(pm8001_ha, IO,2414 "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");2415 ts->resp = SAS_TASK_COMPLETE;2416 ts->stat = SAS_OPEN_REJECT;2417 ts->open_rej_reason = SAS_OREJ_EPROTO;2418 if (pm8001_dev)2419 atomic_dec(&pm8001_dev->running_req);2420 break;2421 case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:2422 pm8001_dbg(pm8001_ha, IO,2423 "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");2424 ts->resp = SAS_TASK_COMPLETE;2425 ts->stat = SAS_OPEN_REJECT;2426 ts->open_rej_reason = SAS_OREJ_UNKNOWN;2427 if (pm8001_dev)2428 atomic_dec(&pm8001_dev->running_req);2429 break;2430 case IO_OPEN_CNX_ERROR_BREAK:2431 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");2432 ts->resp = SAS_TASK_COMPLETE;2433 ts->stat = SAS_OPEN_REJECT;2434 ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;2435 if (pm8001_dev)2436 atomic_dec(&pm8001_dev->running_req);2437 break;2438 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:2439 case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:2440 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:2441 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:2442 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:2443 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:2444 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");2445 ts->resp = SAS_TASK_COMPLETE;2446 ts->stat = SAS_DEV_NO_RESPONSE;2447 if (!t->uldd_task) {2448 pm8001_handle_event(pm8001_ha,2449 pm8001_dev,2450 IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);2451 ts->resp = SAS_TASK_UNDELIVERED;2452 ts->stat = SAS_QUEUE_FULL;2453 spin_unlock_irqrestore(&circularQ->oq_lock,2454 circularQ->lock_flags);2455 pm8001_ccb_task_free_done(pm8001_ha, ccb);2456 spin_lock_irqsave(&circularQ->oq_lock,2457 circularQ->lock_flags);2458 return;2459 }2460 break;2461 case IO_OPEN_CNX_ERROR_BAD_DESTINATION:2462 pm8001_dbg(pm8001_ha, IO,2463 "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");2464 ts->resp = SAS_TASK_UNDELIVERED;2465 ts->stat = SAS_OPEN_REJECT;2466 ts->open_rej_reason = SAS_OREJ_BAD_DEST;2467 if (!t->uldd_task) {2468 pm8001_handle_event(pm8001_ha,2469 pm8001_dev,2470 IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);2471 ts->resp = SAS_TASK_UNDELIVERED;2472 ts->stat = SAS_QUEUE_FULL;2473 spin_unlock_irqrestore(&circularQ->oq_lock,2474 circularQ->lock_flags);2475 pm8001_ccb_task_free_done(pm8001_ha, ccb);2476 spin_lock_irqsave(&circularQ->oq_lock,2477 circularQ->lock_flags);2478 return;2479 }2480 break;2481 case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:2482 pm8001_dbg(pm8001_ha, IO,2483 "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");2484 ts->resp = SAS_TASK_COMPLETE;2485 ts->stat = SAS_OPEN_REJECT;2486 ts->open_rej_reason = SAS_OREJ_CONN_RATE;2487 if (pm8001_dev)2488 atomic_dec(&pm8001_dev->running_req);2489 break;2490 case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:2491 pm8001_dbg(pm8001_ha, IO,2492 "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n");2493 ts->resp = SAS_TASK_COMPLETE;2494 ts->stat = SAS_DEV_NO_RESPONSE;2495 if (!t->uldd_task) {2496 pm8001_handle_event(pm8001_ha,2497 pm8001_dev,2498 IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY);2499 ts->resp = SAS_TASK_UNDELIVERED;2500 ts->stat = SAS_QUEUE_FULL;2501 spin_unlock_irqrestore(&circularQ->oq_lock,2502 circularQ->lock_flags);2503 pm8001_ccb_task_free_done(pm8001_ha, ccb);2504 spin_lock_irqsave(&circularQ->oq_lock,2505 circularQ->lock_flags);2506 return;2507 }2508 break;2509 case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:2510 pm8001_dbg(pm8001_ha, IO,2511 "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");2512 ts->resp = SAS_TASK_COMPLETE;2513 ts->stat = SAS_OPEN_REJECT;2514 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;2515 if (pm8001_dev)2516 atomic_dec(&pm8001_dev->running_req);2517 break;2518 case IO_XFER_ERROR_NAK_RECEIVED:2519 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");2520 ts->resp = SAS_TASK_COMPLETE;2521 ts->stat = SAS_NAK_R_ERR;2522 if (pm8001_dev)2523 atomic_dec(&pm8001_dev->running_req);2524 break;2525 case IO_XFER_ERROR_ACK_NAK_TIMEOUT:2526 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");2527 ts->resp = SAS_TASK_COMPLETE;2528 ts->stat = SAS_NAK_R_ERR;2529 if (pm8001_dev)2530 atomic_dec(&pm8001_dev->running_req);2531 break;2532 case IO_XFER_ERROR_DMA:2533 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");2534 ts->resp = SAS_TASK_COMPLETE;2535 ts->stat = SAS_ABORTED_TASK;2536 if (pm8001_dev)2537 atomic_dec(&pm8001_dev->running_req);2538 break;2539 case IO_XFER_ERROR_SATA_LINK_TIMEOUT:2540 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_SATA_LINK_TIMEOUT\n");2541 ts->resp = SAS_TASK_UNDELIVERED;2542 ts->stat = SAS_DEV_NO_RESPONSE;2543 if (pm8001_dev)2544 atomic_dec(&pm8001_dev->running_req);2545 break;2546 case IO_XFER_ERROR_REJECTED_NCQ_MODE:2547 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");2548 ts->resp = SAS_TASK_COMPLETE;2549 ts->stat = SAS_DATA_UNDERRUN;2550 if (pm8001_dev)2551 atomic_dec(&pm8001_dev->running_req);2552 break;2553 case IO_XFER_OPEN_RETRY_TIMEOUT:2554 pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");2555 ts->resp = SAS_TASK_COMPLETE;2556 ts->stat = SAS_OPEN_TO;2557 if (pm8001_dev)2558 atomic_dec(&pm8001_dev->running_req);2559 break;2560 case IO_PORT_IN_RESET:2561 pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");2562 ts->resp = SAS_TASK_COMPLETE;2563 ts->stat = SAS_DEV_NO_RESPONSE;2564 if (pm8001_dev)2565 atomic_dec(&pm8001_dev->running_req);2566 break;2567 case IO_DS_NON_OPERATIONAL:2568 pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");2569 ts->resp = SAS_TASK_COMPLETE;2570 ts->stat = SAS_DEV_NO_RESPONSE;2571 if (!t->uldd_task) {2572 pm8001_handle_event(pm8001_ha, pm8001_dev,2573 IO_DS_NON_OPERATIONAL);2574 ts->resp = SAS_TASK_UNDELIVERED;2575 ts->stat = SAS_QUEUE_FULL;2576 spin_unlock_irqrestore(&circularQ->oq_lock,2577 circularQ->lock_flags);2578 pm8001_ccb_task_free_done(pm8001_ha, ccb);2579 spin_lock_irqsave(&circularQ->oq_lock,2580 circularQ->lock_flags);2581 return;2582 }2583 break;2584 case IO_DS_IN_RECOVERY:2585 pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");2586 ts->resp = SAS_TASK_COMPLETE;2587 ts->stat = SAS_DEV_NO_RESPONSE;2588 if (pm8001_dev)2589 atomic_dec(&pm8001_dev->running_req);2590 break;2591 case IO_DS_IN_ERROR:2592 pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_ERROR\n");2593 ts->resp = SAS_TASK_COMPLETE;2594 ts->stat = SAS_DEV_NO_RESPONSE;2595 if (!t->uldd_task) {2596 pm8001_handle_event(pm8001_ha, pm8001_dev,2597 IO_DS_IN_ERROR);2598 ts->resp = SAS_TASK_UNDELIVERED;2599 ts->stat = SAS_QUEUE_FULL;2600 spin_unlock_irqrestore(&circularQ->oq_lock,2601 circularQ->lock_flags);2602 pm8001_ccb_task_free_done(pm8001_ha, ccb);2603 spin_lock_irqsave(&circularQ->oq_lock,2604 circularQ->lock_flags);2605 return;2606 }2607 break;2608 case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:2609 pm8001_dbg(pm8001_ha, IO,2610 "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");2611 ts->resp = SAS_TASK_COMPLETE;2612 ts->stat = SAS_OPEN_REJECT;2613 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;2614 if (pm8001_dev)2615 atomic_dec(&pm8001_dev->running_req);2616 break;2617 default:2618 pm8001_dbg(pm8001_ha, DEVIO,2619 "Unknown status device_id %u status 0x%x tag %d\n",2620 pm8001_dev->device_id, status, tag);2621 /* not allowed case. Therefore, return failed status */2622 ts->resp = SAS_TASK_COMPLETE;2623 ts->stat = SAS_DEV_NO_RESPONSE;2624 if (pm8001_dev)2625 atomic_dec(&pm8001_dev->running_req);2626 break;2627 }2628 spin_lock_irqsave(&t->task_state_lock, flags);2629 t->task_state_flags &= ~SAS_TASK_STATE_PENDING;2630 t->task_state_flags |= SAS_TASK_STATE_DONE;2631 if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {2632 spin_unlock_irqrestore(&t->task_state_lock, flags);2633 pm8001_dbg(pm8001_ha, FAIL,2634 "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",2635 t, status, ts->resp, ts->stat);2636 pm8001_ccb_task_free(pm8001_ha, ccb);2637 if (t->slow_task)2638 complete(&t->slow_task->completion);2639 } else {2640 spin_unlock_irqrestore(&t->task_state_lock, flags);2641 spin_unlock_irqrestore(&circularQ->oq_lock,2642 circularQ->lock_flags);2643 pm8001_ccb_task_free_done(pm8001_ha, ccb);2644 spin_lock_irqsave(&circularQ->oq_lock,2645 circularQ->lock_flags);2646 }2647}2648 2649/*See the comments for mpi_ssp_completion */2650static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha,2651 struct outbound_queue_table *circularQ, void *piomb)2652{2653 struct sas_task *t;2654 struct task_status_struct *ts;2655 struct pm8001_ccb_info *ccb;2656 struct pm8001_device *pm8001_dev;2657 struct sata_event_resp *psataPayload =2658 (struct sata_event_resp *)(piomb + 4);2659 u32 event = le32_to_cpu(psataPayload->event);2660 u32 tag = le32_to_cpu(psataPayload->tag);2661 u32 port_id = le32_to_cpu(psataPayload->port_id);2662 u32 dev_id = le32_to_cpu(psataPayload->device_id);2663 2664 if (event)2665 pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event);2666 2667 /* Check if this is NCQ error */2668 if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {2669 /* find device using device id */2670 pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);2671 /* send read log extension by aborting the link - libata does what we want */2672 if (pm8001_dev)2673 pm8001_handle_event(pm8001_ha,2674 pm8001_dev,2675 IO_XFER_ERROR_ABORTED_NCQ_MODE);2676 return;2677 }2678 2679 ccb = &pm8001_ha->ccb_info[tag];2680 t = ccb->task;2681 pm8001_dev = ccb->device;2682 if (unlikely(!t)) {2683 pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",2684 ccb->ccb_tag);2685 pm8001_ccb_free(pm8001_ha, ccb);2686 return;2687 }2688 2689 if (unlikely(!t->lldd_task || !t->dev))2690 return;2691 2692 ts = &t->task_status;2693 pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",2694 port_id, tag, event);2695 switch (event) {2696 case IO_OVERFLOW:2697 pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");2698 ts->resp = SAS_TASK_COMPLETE;2699 ts->stat = SAS_DATA_OVERRUN;2700 ts->residual = 0;2701 break;2702 case IO_XFER_ERROR_BREAK:2703 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");2704 ts->resp = SAS_TASK_COMPLETE;2705 ts->stat = SAS_INTERRUPTED;2706 break;2707 case IO_XFER_ERROR_PHY_NOT_READY:2708 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");2709 ts->resp = SAS_TASK_COMPLETE;2710 ts->stat = SAS_OPEN_REJECT;2711 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;2712 break;2713 case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:2714 pm8001_dbg(pm8001_ha, IO,2715 "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");2716 ts->resp = SAS_TASK_COMPLETE;2717 ts->stat = SAS_OPEN_REJECT;2718 ts->open_rej_reason = SAS_OREJ_EPROTO;2719 break;2720 case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:2721 pm8001_dbg(pm8001_ha, IO,2722 "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");2723 ts->resp = SAS_TASK_COMPLETE;2724 ts->stat = SAS_OPEN_REJECT;2725 ts->open_rej_reason = SAS_OREJ_UNKNOWN;2726 break;2727 case IO_OPEN_CNX_ERROR_BREAK:2728 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");2729 ts->resp = SAS_TASK_COMPLETE;2730 ts->stat = SAS_OPEN_REJECT;2731 ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;2732 break;2733 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:2734 case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:2735 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:2736 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:2737 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:2738 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:2739 pm8001_dbg(pm8001_ha, FAIL,2740 "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");2741 ts->resp = SAS_TASK_UNDELIVERED;2742 ts->stat = SAS_DEV_NO_RESPONSE;2743 if (!t->uldd_task) {2744 pm8001_handle_event(pm8001_ha,2745 pm8001_dev,2746 IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);2747 ts->resp = SAS_TASK_COMPLETE;2748 ts->stat = SAS_QUEUE_FULL;2749 return;2750 }2751 break;2752 case IO_OPEN_CNX_ERROR_BAD_DESTINATION:2753 pm8001_dbg(pm8001_ha, IO,2754 "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");2755 ts->resp = SAS_TASK_UNDELIVERED;2756 ts->stat = SAS_OPEN_REJECT;2757 ts->open_rej_reason = SAS_OREJ_BAD_DEST;2758 break;2759 case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:2760 pm8001_dbg(pm8001_ha, IO,2761 "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");2762 ts->resp = SAS_TASK_COMPLETE;2763 ts->stat = SAS_OPEN_REJECT;2764 ts->open_rej_reason = SAS_OREJ_CONN_RATE;2765 break;2766 case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:2767 pm8001_dbg(pm8001_ha, IO,2768 "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");2769 ts->resp = SAS_TASK_COMPLETE;2770 ts->stat = SAS_OPEN_REJECT;2771 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;2772 break;2773 case IO_XFER_ERROR_NAK_RECEIVED:2774 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");2775 ts->resp = SAS_TASK_COMPLETE;2776 ts->stat = SAS_NAK_R_ERR;2777 break;2778 case IO_XFER_ERROR_PEER_ABORTED:2779 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PEER_ABORTED\n");2780 ts->resp = SAS_TASK_COMPLETE;2781 ts->stat = SAS_NAK_R_ERR;2782 break;2783 case IO_XFER_ERROR_REJECTED_NCQ_MODE:2784 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");2785 ts->resp = SAS_TASK_COMPLETE;2786 ts->stat = SAS_DATA_UNDERRUN;2787 break;2788 case IO_XFER_OPEN_RETRY_TIMEOUT:2789 pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");2790 ts->resp = SAS_TASK_COMPLETE;2791 ts->stat = SAS_OPEN_TO;2792 break;2793 case IO_XFER_ERROR_UNEXPECTED_PHASE:2794 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");2795 ts->resp = SAS_TASK_COMPLETE;2796 ts->stat = SAS_OPEN_TO;2797 break;2798 case IO_XFER_ERROR_XFER_RDY_OVERRUN:2799 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");2800 ts->resp = SAS_TASK_COMPLETE;2801 ts->stat = SAS_OPEN_TO;2802 break;2803 case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:2804 pm8001_dbg(pm8001_ha, IO,2805 "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");2806 ts->resp = SAS_TASK_COMPLETE;2807 ts->stat = SAS_OPEN_TO;2808 break;2809 case IO_XFER_ERROR_OFFSET_MISMATCH:2810 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");2811 ts->resp = SAS_TASK_COMPLETE;2812 ts->stat = SAS_OPEN_TO;2813 break;2814 case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:2815 pm8001_dbg(pm8001_ha, IO,2816 "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");2817 ts->resp = SAS_TASK_COMPLETE;2818 ts->stat = SAS_OPEN_TO;2819 break;2820 case IO_XFER_CMD_FRAME_ISSUED:2821 pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");2822 break;2823 case IO_XFER_PIO_SETUP_ERROR:2824 pm8001_dbg(pm8001_ha, IO, "IO_XFER_PIO_SETUP_ERROR\n");2825 ts->resp = SAS_TASK_COMPLETE;2826 ts->stat = SAS_OPEN_TO;2827 break;2828 case IO_XFER_ERROR_INTERNAL_CRC_ERROR:2829 pm8001_dbg(pm8001_ha, FAIL,2830 "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n");2831 /* TBC: used default set values */2832 ts->resp = SAS_TASK_COMPLETE;2833 ts->stat = SAS_OPEN_TO;2834 break;2835 case IO_XFER_DMA_ACTIVATE_TIMEOUT:2836 pm8001_dbg(pm8001_ha, FAIL, "IO_XFR_DMA_ACTIVATE_TIMEOUT\n");2837 /* TBC: used default set values */2838 ts->resp = SAS_TASK_COMPLETE;2839 ts->stat = SAS_OPEN_TO;2840 break;2841 default:2842 pm8001_dbg(pm8001_ha, IO, "Unknown status 0x%x\n", event);2843 /* not allowed case. Therefore, return failed status */2844 ts->resp = SAS_TASK_COMPLETE;2845 ts->stat = SAS_OPEN_TO;2846 break;2847 }2848}2849 2850/*See the comments for mpi_ssp_completion */2851static void2852mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)2853{2854 u32 param, i;2855 struct sas_task *t;2856 struct pm8001_ccb_info *ccb;2857 unsigned long flags;2858 u32 status;2859 u32 tag;2860 struct smp_completion_resp *psmpPayload;2861 struct task_status_struct *ts;2862 struct pm8001_device *pm8001_dev;2863 2864 psmpPayload = (struct smp_completion_resp *)(piomb + 4);2865 status = le32_to_cpu(psmpPayload->status);2866 tag = le32_to_cpu(psmpPayload->tag);2867 2868 ccb = &pm8001_ha->ccb_info[tag];2869 param = le32_to_cpu(psmpPayload->param);2870 t = ccb->task;2871 ts = &t->task_status;2872 pm8001_dev = ccb->device;2873 if (status)2874 pm8001_dbg(pm8001_ha, FAIL, "smp IO status 0x%x\n", status);2875 if (unlikely(!t || !t->lldd_task || !t->dev))2876 return;2877 2878 pm8001_dbg(pm8001_ha, DEV, "tag::0x%x status::0x%x\n", tag, status);2879 2880 switch (status) {2881 2882 case IO_SUCCESS:2883 pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");2884 ts->resp = SAS_TASK_COMPLETE;2885 ts->stat = SAS_SAM_STAT_GOOD;2886 if (pm8001_dev)2887 atomic_dec(&pm8001_dev->running_req);2888 if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {2889 struct scatterlist *sg_resp = &t->smp_task.smp_resp;2890 u8 *payload;2891 void *to;2892 2893 pm8001_dbg(pm8001_ha, IO,2894 "DIRECT RESPONSE Length:%d\n",2895 param);2896 to = kmap_atomic(sg_page(sg_resp));2897 payload = to + sg_resp->offset;2898 for (i = 0; i < param; i++) {2899 *(payload + i) = psmpPayload->_r_a[i];2900 pm8001_dbg(pm8001_ha, IO,2901 "SMP Byte%d DMA data 0x%x psmp 0x%x\n",2902 i, *(payload + i),2903 psmpPayload->_r_a[i]);2904 }2905 kunmap_atomic(to);2906 }2907 break;2908 case IO_ABORTED:2909 pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB\n");2910 ts->resp = SAS_TASK_COMPLETE;2911 ts->stat = SAS_ABORTED_TASK;2912 if (pm8001_dev)2913 atomic_dec(&pm8001_dev->running_req);2914 break;2915 case IO_OVERFLOW:2916 pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");2917 ts->resp = SAS_TASK_COMPLETE;2918 ts->stat = SAS_DATA_OVERRUN;2919 ts->residual = 0;2920 if (pm8001_dev)2921 atomic_dec(&pm8001_dev->running_req);2922 break;2923 case IO_NO_DEVICE:2924 pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");2925 ts->resp = SAS_TASK_COMPLETE;2926 ts->stat = SAS_PHY_DOWN;2927 break;2928 case IO_ERROR_HW_TIMEOUT:2929 pm8001_dbg(pm8001_ha, IO, "IO_ERROR_HW_TIMEOUT\n");2930 ts->resp = SAS_TASK_COMPLETE;2931 ts->stat = SAS_SAM_STAT_BUSY;2932 break;2933 case IO_XFER_ERROR_BREAK:2934 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");2935 ts->resp = SAS_TASK_COMPLETE;2936 ts->stat = SAS_SAM_STAT_BUSY;2937 break;2938 case IO_XFER_ERROR_PHY_NOT_READY:2939 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");2940 ts->resp = SAS_TASK_COMPLETE;2941 ts->stat = SAS_SAM_STAT_BUSY;2942 break;2943 case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:2944 pm8001_dbg(pm8001_ha, IO,2945 "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");2946 ts->resp = SAS_TASK_COMPLETE;2947 ts->stat = SAS_OPEN_REJECT;2948 ts->open_rej_reason = SAS_OREJ_UNKNOWN;2949 break;2950 case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:2951 pm8001_dbg(pm8001_ha, IO,2952 "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");2953 ts->resp = SAS_TASK_COMPLETE;2954 ts->stat = SAS_OPEN_REJECT;2955 ts->open_rej_reason = SAS_OREJ_UNKNOWN;2956 break;2957 case IO_OPEN_CNX_ERROR_BREAK:2958 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");2959 ts->resp = SAS_TASK_COMPLETE;2960 ts->stat = SAS_OPEN_REJECT;2961 ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;2962 break;2963 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:2964 case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:2965 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:2966 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:2967 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:2968 case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:2969 pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");2970 ts->resp = SAS_TASK_COMPLETE;2971 ts->stat = SAS_OPEN_REJECT;2972 ts->open_rej_reason = SAS_OREJ_UNKNOWN;2973 pm8001_handle_event(pm8001_ha,2974 pm8001_dev,2975 IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);2976 break;2977 case IO_OPEN_CNX_ERROR_BAD_DESTINATION:2978 pm8001_dbg(pm8001_ha, IO,2979 "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");2980 ts->resp = SAS_TASK_COMPLETE;2981 ts->stat = SAS_OPEN_REJECT;2982 ts->open_rej_reason = SAS_OREJ_BAD_DEST;2983 break;2984 case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:2985 pm8001_dbg(pm8001_ha, IO,2986 "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");2987 ts->resp = SAS_TASK_COMPLETE;2988 ts->stat = SAS_OPEN_REJECT;2989 ts->open_rej_reason = SAS_OREJ_CONN_RATE;2990 break;2991 case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:2992 pm8001_dbg(pm8001_ha, IO,2993 "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");2994 ts->resp = SAS_TASK_COMPLETE;2995 ts->stat = SAS_OPEN_REJECT;2996 ts->open_rej_reason = SAS_OREJ_WRONG_DEST;2997 break;2998 case IO_XFER_ERROR_RX_FRAME:2999 pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_RX_FRAME\n");3000 ts->resp = SAS_TASK_COMPLETE;3001 ts->stat = SAS_DEV_NO_RESPONSE;3002 break;3003 case IO_XFER_OPEN_RETRY_TIMEOUT:3004 pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");3005 ts->resp = SAS_TASK_COMPLETE;3006 ts->stat = SAS_OPEN_REJECT;3007 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;3008 break;3009 case IO_ERROR_INTERNAL_SMP_RESOURCE:3010 pm8001_dbg(pm8001_ha, IO, "IO_ERROR_INTERNAL_SMP_RESOURCE\n");3011 ts->resp = SAS_TASK_COMPLETE;3012 ts->stat = SAS_QUEUE_FULL;3013 break;3014 case IO_PORT_IN_RESET:3015 pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");3016 ts->resp = SAS_TASK_COMPLETE;3017 ts->stat = SAS_OPEN_REJECT;3018 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;3019 break;3020 case IO_DS_NON_OPERATIONAL:3021 pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");3022 ts->resp = SAS_TASK_COMPLETE;3023 ts->stat = SAS_DEV_NO_RESPONSE;3024 break;3025 case IO_DS_IN_RECOVERY:3026 pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");3027 ts->resp = SAS_TASK_COMPLETE;3028 ts->stat = SAS_OPEN_REJECT;3029 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;3030 break;3031 case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:3032 pm8001_dbg(pm8001_ha, IO,3033 "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");3034 ts->resp = SAS_TASK_COMPLETE;3035 ts->stat = SAS_OPEN_REJECT;3036 ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;3037 break;3038 default:3039 pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);3040 ts->resp = SAS_TASK_COMPLETE;3041 ts->stat = SAS_DEV_NO_RESPONSE;3042 /* not allowed case. Therefore, return failed status */3043 break;3044 }3045 spin_lock_irqsave(&t->task_state_lock, flags);3046 t->task_state_flags &= ~SAS_TASK_STATE_PENDING;3047 t->task_state_flags |= SAS_TASK_STATE_DONE;3048 if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {3049 spin_unlock_irqrestore(&t->task_state_lock, flags);3050 pm8001_dbg(pm8001_ha, FAIL,3051 "task 0x%p done with io_status 0x%x resp 0x%xstat 0x%x but aborted by upper layer!\n",3052 t, status, ts->resp, ts->stat);3053 pm8001_ccb_task_free(pm8001_ha, ccb);3054 } else {3055 spin_unlock_irqrestore(&t->task_state_lock, flags);3056 pm8001_ccb_task_free(pm8001_ha, ccb);3057 mb();/* in order to force CPU ordering */3058 t->task_done(t);3059 }3060}3061 3062/**3063 * pm80xx_hw_event_ack_req- For PM8001, some events need to acknowledge to FW.3064 * @pm8001_ha: our hba card information3065 * @Qnum: the outbound queue message number.3066 * @SEA: source of event to ack3067 * @port_id: port id.3068 * @phyId: phy id.3069 * @param0: parameter 0.3070 * @param1: parameter 1.3071 */3072static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,3073 u32 Qnum, u32 SEA, u32 port_id, u32 phyId, u32 param0, u32 param1)3074{3075 struct hw_event_ack_req payload;3076 u32 opc = OPC_INB_SAS_HW_EVENT_ACK;3077 3078 memset((u8 *)&payload, 0, sizeof(payload));3079 payload.tag = cpu_to_le32(1);3080 payload.phyid_sea_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) |3081 ((phyId & 0xFF) << 24) | (port_id & 0xFF));3082 payload.param0 = cpu_to_le32(param0);3083 payload.param1 = cpu_to_le32(param1);3084 3085 pm8001_mpi_build_cmd(pm8001_ha, Qnum, opc, &payload,3086 sizeof(payload), 0);3087}3088 3089static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,3090 u32 phyId, u32 phy_op);3091 3092static void hw_event_port_recover(struct pm8001_hba_info *pm8001_ha,3093 void *piomb)3094{3095 struct hw_event_resp *pPayload = (struct hw_event_resp *)(piomb + 4);3096 u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);3097 u8 phy_id = (u8)((phyid_npip_portstate & 0xFF0000) >> 16);3098 u32 lr_status_evt_portid =3099 le32_to_cpu(pPayload->lr_status_evt_portid);3100 u8 deviceType = pPayload->sas_identify.dev_type;3101 u8 link_rate = (u8)((lr_status_evt_portid & 0xF0000000) >> 28);3102 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];3103 u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);3104 struct pm8001_port *port = &pm8001_ha->port[port_id];3105 3106 if (deviceType == SAS_END_DEVICE) {3107 pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id,3108 PHY_NOTIFY_ENABLE_SPINUP);3109 }3110 3111 port->wide_port_phymap |= (1U << phy_id);3112 pm8001_get_lrate_mode(phy, link_rate);3113 phy->sas_phy.oob_mode = SAS_OOB_MODE;3114 phy->phy_state = PHY_STATE_LINK_UP_SPCV;3115 phy->phy_attached = 1;3116}3117 3118/**3119 * hw_event_sas_phy_up - FW tells me a SAS phy up event.3120 * @pm8001_ha: our hba card information3121 * @piomb: IO message buffer3122 */3123static void3124hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)3125{3126 struct hw_event_resp *pPayload =3127 (struct hw_event_resp *)(piomb + 4);3128 u32 lr_status_evt_portid =3129 le32_to_cpu(pPayload->lr_status_evt_portid);3130 u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);3131 3132 u8 link_rate =3133 (u8)((lr_status_evt_portid & 0xF0000000) >> 28);3134 u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);3135 u8 phy_id =3136 (u8)((phyid_npip_portstate & 0xFF0000) >> 16);3137 u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);3138 3139 struct pm8001_port *port = &pm8001_ha->port[port_id];3140 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];3141 unsigned long flags;3142 u8 deviceType = pPayload->sas_identify.dev_type;3143 phy->port = port;3144 port->port_id = port_id;3145 port->port_state = portstate;3146 port->wide_port_phymap |= (1U << phy_id);3147 phy->phy_state = PHY_STATE_LINK_UP_SPCV;3148 pm8001_dbg(pm8001_ha, MSG,3149 "portid:%d; phyid:%d; linkrate:%d; portstate:%x; devicetype:%x\n",3150 port_id, phy_id, link_rate, portstate, deviceType);3151 3152 switch (deviceType) {3153 case SAS_PHY_UNUSED:3154 pm8001_dbg(pm8001_ha, MSG, "device type no device.\n");3155 break;3156 case SAS_END_DEVICE:3157 pm8001_dbg(pm8001_ha, MSG, "end device.\n");3158 pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id,3159 PHY_NOTIFY_ENABLE_SPINUP);3160 port->port_attached = 1;3161 pm8001_get_lrate_mode(phy, link_rate);3162 break;3163 case SAS_EDGE_EXPANDER_DEVICE:3164 pm8001_dbg(pm8001_ha, MSG, "expander device.\n");3165 port->port_attached = 1;3166 pm8001_get_lrate_mode(phy, link_rate);3167 break;3168 case SAS_FANOUT_EXPANDER_DEVICE:3169 pm8001_dbg(pm8001_ha, MSG, "fanout expander device.\n");3170 port->port_attached = 1;3171 pm8001_get_lrate_mode(phy, link_rate);3172 break;3173 default:3174 pm8001_dbg(pm8001_ha, DEVIO, "unknown device type(%x)\n",3175 deviceType);3176 break;3177 }3178 phy->phy_type |= PORT_TYPE_SAS;3179 phy->identify.device_type = deviceType;3180 phy->phy_attached = 1;3181 if (phy->identify.device_type == SAS_END_DEVICE)3182 phy->identify.target_port_protocols = SAS_PROTOCOL_SSP;3183 else if (phy->identify.device_type != SAS_PHY_UNUSED)3184 phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;3185 phy->sas_phy.oob_mode = SAS_OOB_MODE;3186 sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);3187 spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);3188 memcpy(phy->frame_rcvd, &pPayload->sas_identify,3189 sizeof(struct sas_identify_frame)-4);3190 phy->frame_rcvd_size = sizeof(struct sas_identify_frame) - 4;3191 pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);3192 spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);3193 if (pm8001_ha->flags == PM8001F_RUN_TIME)3194 mdelay(200); /* delay a moment to wait for disk to spin up */3195 pm8001_bytes_dmaed(pm8001_ha, phy_id);3196}3197 3198/**3199 * hw_event_sata_phy_up - FW tells me a SATA phy up event.3200 * @pm8001_ha: our hba card information3201 * @piomb: IO message buffer3202 */3203static void3204hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)3205{3206 struct hw_event_resp *pPayload =3207 (struct hw_event_resp *)(piomb + 4);3208 u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);3209 u32 lr_status_evt_portid =3210 le32_to_cpu(pPayload->lr_status_evt_portid);3211 u8 link_rate =3212 (u8)((lr_status_evt_portid & 0xF0000000) >> 28);3213 u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);3214 u8 phy_id =3215 (u8)((phyid_npip_portstate & 0xFF0000) >> 16);3216 3217 u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);3218 3219 struct pm8001_port *port = &pm8001_ha->port[port_id];3220 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];3221 unsigned long flags;3222 pm8001_dbg(pm8001_ha, EVENT,3223 "HW_EVENT_SATA_PHY_UP phyid:%#x port_id:%#x link_rate:%d portstate:%#x\n",3224 phy_id, port_id, link_rate, portstate);3225 3226 phy->port = port;3227 port->port_id = port_id;3228 port->port_state = portstate;3229 phy->phy_state = PHY_STATE_LINK_UP_SPCV;3230 port->port_attached = 1;3231 pm8001_get_lrate_mode(phy, link_rate);3232 phy->phy_type |= PORT_TYPE_SATA;3233 phy->phy_attached = 1;3234 phy->sas_phy.oob_mode = SATA_OOB_MODE;3235 sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE, GFP_ATOMIC);3236 spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);3237 memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4),3238 sizeof(struct dev_to_host_fis));3239 phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);3240 phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;3241 phy->identify.device_type = SAS_SATA_DEV;3242 pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);3243 spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);3244 pm8001_bytes_dmaed(pm8001_ha, phy_id);3245}3246 3247/**3248 * hw_event_phy_down - we should notify the libsas the phy is down.3249 * @pm8001_ha: our hba card information3250 * @piomb: IO message buffer3251 */3252static void3253hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)3254{3255 struct hw_event_resp *pPayload =3256 (struct hw_event_resp *)(piomb + 4);3257 3258 u32 lr_status_evt_portid =3259 le32_to_cpu(pPayload->lr_status_evt_portid);3260 u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);3261 u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);3262 u8 phy_id =3263 (u8)((phyid_npip_portstate & 0xFF0000) >> 16);3264 u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);3265 3266 struct pm8001_port *port = &pm8001_ha->port[port_id];3267 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];3268 u32 port_sata = (phy->phy_type & PORT_TYPE_SATA);3269 port->port_state = portstate;3270 phy->identify.device_type = 0;3271 phy->phy_attached = 0;3272 switch (portstate) {3273 case PORT_VALID:3274 pm8001_dbg(pm8001_ha, EVENT,3275 "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_VALID\n",3276 phy_id, port_id);3277 break;3278 case PORT_INVALID:3279 pm8001_dbg(pm8001_ha, EVENT,3280 "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_INVALID\n",3281 phy_id, port_id);3282 pm8001_dbg(pm8001_ha, MSG,3283 " Last phy Down and port invalid\n");3284 if (port_sata) {3285 phy->phy_type = 0;3286 port->port_attached = 0;3287 pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,3288 port_id, phy_id, 0, 0);3289 }3290 sas_phy_disconnected(&phy->sas_phy);3291 break;3292 case PORT_IN_RESET:3293 pm8001_dbg(pm8001_ha, EVENT,3294 "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_IN_RESET\n",3295 phy_id, port_id);3296 break;3297 case PORT_NOT_ESTABLISHED:3298 pm8001_dbg(pm8001_ha, EVENT,3299 "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_NOT_ESTABLISHED\n",3300 phy_id, port_id);3301 port->port_attached = 0;3302 break;3303 case PORT_LOSTCOMM:3304 pm8001_dbg(pm8001_ha, EVENT,3305 "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate: PORT_LOSTCOMM\n",3306 phy_id, port_id);3307 pm8001_dbg(pm8001_ha, MSG, " Last phy Down and port invalid\n");3308 if (port_sata) {3309 port->port_attached = 0;3310 phy->phy_type = 0;3311 pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,3312 port_id, phy_id, 0, 0);3313 }3314 sas_phy_disconnected(&phy->sas_phy);3315 break;3316 default:3317 port->port_attached = 0;3318 pm8001_dbg(pm8001_ha, EVENT,3319 "HW_EVENT_PHY_DOWN phyid:%#x port_id:%#x portstate:%#x\n",3320 phy_id, port_id, portstate);3321 break;3322 3323 }3324 if (port_sata && (portstate != PORT_IN_RESET))3325 sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL,3326 GFP_ATOMIC);3327}3328 3329static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)3330{3331 struct phy_start_resp *pPayload =3332 (struct phy_start_resp *)(piomb + 4);3333 u32 status =3334 le32_to_cpu(pPayload->status);3335 u32 phy_id =3336 le32_to_cpu(pPayload->phyid) & 0xFF;3337 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];3338 3339 pm8001_dbg(pm8001_ha, INIT,3340 "phy start resp status:0x%x, phyid:0x%x\n",3341 status, phy_id);3342 if (status == 0)3343 phy->phy_state = PHY_LINK_DOWN;3344 3345 if (pm8001_ha->flags == PM8001F_RUN_TIME &&3346 phy->enable_completion != NULL) {3347 complete(phy->enable_completion);3348 phy->enable_completion = NULL;3349 }3350 return 0;3351 3352}3353 3354/**3355 * mpi_thermal_hw_event - a thermal hw event has come.3356 * @pm8001_ha: our hba card information3357 * @piomb: IO message buffer3358 */3359static int mpi_thermal_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)3360{3361 struct thermal_hw_event *pPayload =3362 (struct thermal_hw_event *)(piomb + 4);3363 3364 u32 thermal_event = le32_to_cpu(pPayload->thermal_event);3365 u32 rht_lht = le32_to_cpu(pPayload->rht_lht);3366 3367 if (thermal_event & 0x40) {3368 pm8001_dbg(pm8001_ha, IO,3369 "Thermal Event: Local high temperature violated!\n");3370 pm8001_dbg(pm8001_ha, IO,3371 "Thermal Event: Measured local high temperature %d\n",3372 ((rht_lht & 0xFF00) >> 8));3373 }3374 if (thermal_event & 0x10) {3375 pm8001_dbg(pm8001_ha, IO,3376 "Thermal Event: Remote high temperature violated!\n");3377 pm8001_dbg(pm8001_ha, IO,3378 "Thermal Event: Measured remote high temperature %d\n",3379 ((rht_lht & 0xFF000000) >> 24));3380 }3381 return 0;3382}3383 3384/**3385 * mpi_hw_event - The hw event has come.3386 * @pm8001_ha: our hba card information3387 * @piomb: IO message buffer3388 */3389static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)3390{3391 unsigned long flags, i;3392 struct hw_event_resp *pPayload =3393 (struct hw_event_resp *)(piomb + 4);3394 u32 lr_status_evt_portid =3395 le32_to_cpu(pPayload->lr_status_evt_portid);3396 u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);3397 u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);3398 u8 phy_id =3399 (u8)((phyid_npip_portstate & 0xFF0000) >> 16);3400 u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);3401 u16 eventType =3402 (u16)((lr_status_evt_portid & 0x00FFFF00) >> 8);3403 u8 status =3404 (u8)((lr_status_evt_portid & 0x0F000000) >> 24);3405 struct sas_ha_struct *sas_ha = pm8001_ha->sas;3406 struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];3407 struct pm8001_port *port = &pm8001_ha->port[port_id];3408 struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];3409 pm8001_dbg(pm8001_ha, DEV,3410 "portid:%d phyid:%d event:0x%x status:0x%x\n",3411 port_id, phy_id, eventType, status);3412 3413 switch (eventType) {3414 3415 case HW_EVENT_SAS_PHY_UP:3416 pm8001_dbg(pm8001_ha, EVENT,3417 "HW_EVENT_SAS_PHY_UP phyid:%#x port_id:%#x\n",3418 phy_id, port_id);3419 hw_event_sas_phy_up(pm8001_ha, piomb);3420 break;3421 case HW_EVENT_SATA_PHY_UP:3422 hw_event_sata_phy_up(pm8001_ha, piomb);3423 break;3424 case HW_EVENT_SATA_SPINUP_HOLD:3425 pm8001_dbg(pm8001_ha, EVENT,3426 "HW_EVENT_SATA_SPINUP_HOLD phyid:%#x port_id:%#x\n",3427 phy_id, port_id);3428 sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD,3429 GFP_ATOMIC);3430 break;3431 case HW_EVENT_PHY_DOWN:3432 hw_event_phy_down(pm8001_ha, piomb);3433 phy->phy_state = PHY_LINK_DISABLE;3434 break;3435 case HW_EVENT_PORT_INVALID:3436 pm8001_dbg(pm8001_ha, EVENT,3437 "HW_EVENT_PORT_INVALID phyid:%#x port_id:%#x\n",3438 phy_id, port_id);3439 sas_phy_disconnected(sas_phy);3440 phy->phy_attached = 0;3441 sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,3442 GFP_ATOMIC);3443 break;3444 /* the broadcast change primitive received, tell the LIBSAS this event3445 to revalidate the sas domain*/3446 case HW_EVENT_BROADCAST_CHANGE:3447 pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_CHANGE\n");3448 pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE,3449 port_id, phy_id, 1, 0);3450 spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);3451 sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;3452 spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);3453 sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,3454 GFP_ATOMIC);3455 break;3456 case HW_EVENT_PHY_ERROR:3457 pm8001_dbg(pm8001_ha, EVENT,3458 "HW_EVENT_PHY_ERROR phyid:%#x port_id:%#x\n",3459 phy_id, port_id);3460 sas_phy_disconnected(&phy->sas_phy);3461 phy->phy_attached = 0;3462 sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR, GFP_ATOMIC);3463 break;3464 case HW_EVENT_BROADCAST_EXP:3465 pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n");3466 spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);3467 sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP;3468 spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);3469 sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,3470 GFP_ATOMIC);3471 break;3472 case HW_EVENT_LINK_ERR_INVALID_DWORD:3473 pm8001_dbg(pm8001_ha, EVENT,3474 "HW_EVENT_LINK_ERR_INVALID_DWORD phyid:%#x port_id:%#x\n",3475 phy_id, port_id);3476 pm80xx_hw_event_ack_req(pm8001_ha, 0,3477 HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0);3478 break;3479 case HW_EVENT_LINK_ERR_DISPARITY_ERROR:3480 pm8001_dbg(pm8001_ha, EVENT,3481 "HW_EVENT_LINK_ERR_DISPARITY_ERROR phyid:%#x port_id:%#x\n",3482 phy_id, port_id);3483 pm80xx_hw_event_ack_req(pm8001_ha, 0,3484 HW_EVENT_LINK_ERR_DISPARITY_ERROR,3485 port_id, phy_id, 0, 0);3486 break;3487 case HW_EVENT_LINK_ERR_CODE_VIOLATION:3488 pm8001_dbg(pm8001_ha, EVENT,3489 "HW_EVENT_LINK_ERR_CODE_VIOLATION phyid:%#x port_id:%#x\n",3490 phy_id, port_id);3491 pm80xx_hw_event_ack_req(pm8001_ha, 0,3492 HW_EVENT_LINK_ERR_CODE_VIOLATION,3493 port_id, phy_id, 0, 0);3494 break;3495 case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:3496 pm8001_dbg(pm8001_ha, EVENT,3497 "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH phyid:%#x port_id:%#x\n",3498 phy_id, port_id);3499 pm80xx_hw_event_ack_req(pm8001_ha, 0,3500 HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,3501 port_id, phy_id, 0, 0);3502 break;3503 case HW_EVENT_MALFUNCTION:3504 pm8001_dbg(pm8001_ha, EVENT,3505 "HW_EVENT_MALFUNCTION phyid:%#x\n", phy_id);3506 break;3507 case HW_EVENT_BROADCAST_SES:3508 pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n");3509 spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);3510 sas_phy->sas_prim = HW_EVENT_BROADCAST_SES;3511 spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);3512 sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD,3513 GFP_ATOMIC);3514 break;3515 case HW_EVENT_INBOUND_CRC_ERROR:3516 pm8001_dbg(pm8001_ha, EVENT,3517 "HW_EVENT_INBOUND_CRC_ERROR phyid:%#x port_id:%#x\n",3518 phy_id, port_id);3519 pm80xx_hw_event_ack_req(pm8001_ha, 0,3520 HW_EVENT_INBOUND_CRC_ERROR,3521 port_id, phy_id, 0, 0);3522 break;3523 case HW_EVENT_HARD_RESET_RECEIVED:3524 pm8001_dbg(pm8001_ha, EVENT,3525 "HW_EVENT_HARD_RESET_RECEIVED phyid:%#x\n", phy_id);3526 sas_notify_port_event(sas_phy, PORTE_HARD_RESET, GFP_ATOMIC);3527 break;3528 case HW_EVENT_ID_FRAME_TIMEOUT:3529 pm8001_dbg(pm8001_ha, EVENT,3530 "HW_EVENT_ID_FRAME_TIMEOUT phyid:%#x\n", phy_id);3531 sas_phy_disconnected(sas_phy);3532 phy->phy_attached = 0;3533 sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,3534 GFP_ATOMIC);3535 break;3536 case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:3537 pm8001_dbg(pm8001_ha, EVENT,3538 "HW_EVENT_LINK_ERR_PHY_RESET_FAILED phyid:%#x port_id:%#x\n",3539 phy_id, port_id);3540 pm80xx_hw_event_ack_req(pm8001_ha, 0,3541 HW_EVENT_LINK_ERR_PHY_RESET_FAILED,3542 port_id, phy_id, 0, 0);3543 sas_phy_disconnected(sas_phy);3544 phy->phy_attached = 0;3545 sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,3546 GFP_ATOMIC);3547 break;3548 case HW_EVENT_PORT_RESET_TIMER_TMO:3549 pm8001_dbg(pm8001_ha, EVENT,3550 "HW_EVENT_PORT_RESET_TIMER_TMO phyid:%#x port_id:%#x portstate:%#x\n",3551 phy_id, port_id, portstate);3552 if (!pm8001_ha->phy[phy_id].reset_completion) {3553 pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,3554 port_id, phy_id, 0, 0);3555 }3556 sas_phy_disconnected(sas_phy);3557 phy->phy_attached = 0;3558 port->port_state = portstate;3559 sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR,3560 GFP_ATOMIC);3561 if (pm8001_ha->phy[phy_id].reset_completion) {3562 pm8001_ha->phy[phy_id].port_reset_status =3563 PORT_RESET_TMO;3564 complete(pm8001_ha->phy[phy_id].reset_completion);3565 pm8001_ha->phy[phy_id].reset_completion = NULL;3566 }3567 break;3568 case HW_EVENT_PORT_RECOVERY_TIMER_TMO:3569 pm8001_dbg(pm8001_ha, EVENT,3570 "HW_EVENT_PORT_RECOVERY_TIMER_TMO phyid:%#x port_id:%#x\n",3571 phy_id, port_id);3572 pm80xx_hw_event_ack_req(pm8001_ha, 0,3573 HW_EVENT_PORT_RECOVERY_TIMER_TMO,3574 port_id, phy_id, 0, 0);3575 for (i = 0; i < pm8001_ha->chip->n_phy; i++) {3576 if (port->wide_port_phymap & (1 << i)) {3577 phy = &pm8001_ha->phy[i];3578 sas_notify_phy_event(&phy->sas_phy,3579 PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);3580 port->wide_port_phymap &= ~(1 << i);3581 }3582 }3583 break;3584 case HW_EVENT_PORT_RECOVER:3585 pm8001_dbg(pm8001_ha, EVENT,3586 "HW_EVENT_PORT_RECOVER phyid:%#x port_id:%#x\n",3587 phy_id, port_id);3588 hw_event_port_recover(pm8001_ha, piomb);3589 break;3590 case HW_EVENT_PORT_RESET_COMPLETE:3591 pm8001_dbg(pm8001_ha, EVENT,3592 "HW_EVENT_PORT_RESET_COMPLETE phyid:%#x port_id:%#x portstate:%#x\n",3593 phy_id, port_id, portstate);3594 if (pm8001_ha->phy[phy_id].reset_completion) {3595 pm8001_ha->phy[phy_id].port_reset_status =3596 PORT_RESET_SUCCESS;3597 complete(pm8001_ha->phy[phy_id].reset_completion);3598 pm8001_ha->phy[phy_id].reset_completion = NULL;3599 }3600 phy->phy_attached = 1;3601 phy->phy_state = PHY_STATE_LINK_UP_SPCV;3602 port->port_state = portstate;3603 break;3604 case EVENT_BROADCAST_ASYNCH_EVENT:3605 pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n");3606 break;3607 default:3608 pm8001_dbg(pm8001_ha, DEVIO,3609 "Unknown event portid:%d phyid:%d event:0x%x status:0x%x\n",3610 port_id, phy_id, eventType, status);3611 break;3612 }3613 return 0;3614}3615 3616/**3617 * mpi_phy_stop_resp - SPCv specific3618 * @pm8001_ha: our hba card information3619 * @piomb: IO message buffer3620 */3621static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)3622{3623 struct phy_stop_resp *pPayload =3624 (struct phy_stop_resp *)(piomb + 4);3625 u32 status =3626 le32_to_cpu(pPayload->status);3627 u32 phyid =3628 le32_to_cpu(pPayload->phyid) & 0xFF;3629 struct pm8001_phy *phy = &pm8001_ha->phy[phyid];3630 pm8001_dbg(pm8001_ha, MSG, "phy:0x%x status:0x%x\n",3631 phyid, status);3632 if (status == PHY_STOP_SUCCESS ||3633 status == PHY_STOP_ERR_DEVICE_ATTACHED) {3634 phy->phy_state = PHY_LINK_DISABLE;3635 phy->sas_phy.phy->negotiated_linkrate = SAS_PHY_DISABLED;3636 phy->sas_phy.linkrate = SAS_PHY_DISABLED;3637 }3638 3639 return 0;3640}3641 3642/**3643 * mpi_set_controller_config_resp - SPCv specific3644 * @pm8001_ha: our hba card information3645 * @piomb: IO message buffer3646 */3647static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha,3648 void *piomb)3649{3650 struct set_ctrl_cfg_resp *pPayload =3651 (struct set_ctrl_cfg_resp *)(piomb + 4);3652 u32 status = le32_to_cpu(pPayload->status);3653 u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd);3654 u32 tag = le32_to_cpu(pPayload->tag);3655 3656 pm8001_dbg(pm8001_ha, MSG,3657 "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",3658 status, err_qlfr_pgcd);3659 pm8001_tag_free(pm8001_ha, tag);3660 3661 return 0;3662}3663 3664/**3665 * mpi_get_controller_config_resp - SPCv specific3666 * @pm8001_ha: our hba card information3667 * @piomb: IO message buffer3668 */3669static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha,3670 void *piomb)3671{3672 pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");3673 3674 return 0;3675}3676 3677/**3678 * mpi_get_phy_profile_resp - SPCv specific3679 * @pm8001_ha: our hba card information3680 * @piomb: IO message buffer3681 */3682static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,3683 void *piomb)3684{3685 pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");3686 3687 return 0;3688}3689 3690/**3691 * mpi_flash_op_ext_resp - SPCv specific3692 * @pm8001_ha: our hba card information3693 * @piomb: IO message buffer3694 */3695static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)3696{3697 pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");3698 3699 return 0;3700}3701 3702/**3703 * mpi_set_phy_profile_resp - SPCv specific3704 * @pm8001_ha: our hba card information3705 * @piomb: IO message buffer3706 */3707static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,3708 void *piomb)3709{3710 u32 tag;3711 u8 page_code;3712 int rc = 0;3713 struct set_phy_profile_resp *pPayload =3714 (struct set_phy_profile_resp *)(piomb + 4);3715 u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid);3716 u32 status = le32_to_cpu(pPayload->status);3717 3718 tag = le32_to_cpu(pPayload->tag);3719 page_code = (u8)((ppc_phyid & 0xFF00) >> 8);3720 if (status) {3721 /* status is FAILED */3722 pm8001_dbg(pm8001_ha, FAIL,3723 "PhyProfile command failed with status 0x%08X\n",3724 status);3725 rc = -1;3726 } else {3727 if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) {3728 pm8001_dbg(pm8001_ha, FAIL, "Invalid page code 0x%X\n",3729 page_code);3730 rc = -1;3731 }3732 }3733 pm8001_tag_free(pm8001_ha, tag);3734 return rc;3735}3736 3737/**3738 * mpi_kek_management_resp - SPCv specific3739 * @pm8001_ha: our hba card information3740 * @piomb: IO message buffer3741 */3742static int mpi_kek_management_resp(struct pm8001_hba_info *pm8001_ha,3743 void *piomb)3744{3745 struct kek_mgmt_resp *pPayload = (struct kek_mgmt_resp *)(piomb + 4);3746 3747 u32 status = le32_to_cpu(pPayload->status);3748 u32 kidx_new_curr_ksop = le32_to_cpu(pPayload->kidx_new_curr_ksop);3749 u32 err_qlfr = le32_to_cpu(pPayload->err_qlfr);3750 3751 pm8001_dbg(pm8001_ha, MSG,3752 "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n",3753 status, kidx_new_curr_ksop, err_qlfr);3754 3755 return 0;3756}3757 3758/**3759 * mpi_dek_management_resp - SPCv specific3760 * @pm8001_ha: our hba card information3761 * @piomb: IO message buffer3762 */3763static int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha,3764 void *piomb)3765{3766 pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");3767 3768 return 0;3769}3770 3771/**3772 * ssp_coalesced_comp_resp - SPCv specific3773 * @pm8001_ha: our hba card information3774 * @piomb: IO message buffer3775 */3776static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,3777 void *piomb)3778{3779 pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");3780 3781 return 0;3782}3783 3784/**3785 * process_one_iomb - process one outbound Queue memory block3786 * @pm8001_ha: our hba card information3787 * @circularQ: outbound circular queue3788 * @piomb: IO message buffer3789 */3790static void process_one_iomb(struct pm8001_hba_info *pm8001_ha,3791 struct outbound_queue_table *circularQ, void *piomb)3792{3793 __le32 pHeader = *(__le32 *)piomb;3794 u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF);3795 3796 switch (opc) {3797 case OPC_OUB_ECHO:3798 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_ECHO\n");3799 break;3800 case OPC_OUB_HW_EVENT:3801 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_HW_EVENT\n");3802 mpi_hw_event(pm8001_ha, piomb);3803 break;3804 case OPC_OUB_THERM_HW_EVENT:3805 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_THERMAL_EVENT\n");3806 mpi_thermal_hw_event(pm8001_ha, piomb);3807 break;3808 case OPC_OUB_SSP_COMP:3809 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_COMP\n");3810 mpi_ssp_completion(pm8001_ha, piomb);3811 break;3812 case OPC_OUB_SMP_COMP:3813 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_COMP\n");3814 mpi_smp_completion(pm8001_ha, piomb);3815 break;3816 case OPC_OUB_LOCAL_PHY_CNTRL:3817 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_LOCAL_PHY_CNTRL\n");3818 pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);3819 break;3820 case OPC_OUB_DEV_REGIST:3821 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_REGIST\n");3822 pm8001_mpi_reg_resp(pm8001_ha, piomb);3823 break;3824 case OPC_OUB_DEREG_DEV:3825 pm8001_dbg(pm8001_ha, MSG, "unregister the device\n");3826 pm8001_mpi_dereg_resp(pm8001_ha, piomb);3827 break;3828 case OPC_OUB_GET_DEV_HANDLE:3829 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEV_HANDLE\n");3830 break;3831 case OPC_OUB_SATA_COMP:3832 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n");3833 mpi_sata_completion(pm8001_ha, circularQ, piomb);3834 break;3835 case OPC_OUB_SATA_EVENT:3836 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n");3837 mpi_sata_event(pm8001_ha, circularQ, piomb);3838 break;3839 case OPC_OUB_SSP_EVENT:3840 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n");3841 mpi_ssp_event(pm8001_ha, piomb);3842 break;3843 case OPC_OUB_DEV_HANDLE_ARRIV:3844 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_HANDLE_ARRIV\n");3845 /*This is for target*/3846 break;3847 case OPC_OUB_SSP_RECV_EVENT:3848 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_RECV_EVENT\n");3849 /*This is for target*/3850 break;3851 case OPC_OUB_FW_FLASH_UPDATE:3852 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_FW_FLASH_UPDATE\n");3853 pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);3854 break;3855 case OPC_OUB_GPIO_RESPONSE:3856 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_RESPONSE\n");3857 break;3858 case OPC_OUB_GPIO_EVENT:3859 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_EVENT\n");3860 break;3861 case OPC_OUB_GENERAL_EVENT:3862 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GENERAL_EVENT\n");3863 pm8001_mpi_general_event(pm8001_ha, piomb);3864 break;3865 case OPC_OUB_SSP_ABORT_RSP:3866 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_ABORT_RSP\n");3867 pm8001_mpi_task_abort_resp(pm8001_ha, piomb);3868 break;3869 case OPC_OUB_SATA_ABORT_RSP:3870 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_ABORT_RSP\n");3871 pm8001_mpi_task_abort_resp(pm8001_ha, piomb);3872 break;3873 case OPC_OUB_SAS_DIAG_MODE_START_END:3874 pm8001_dbg(pm8001_ha, MSG,3875 "OPC_OUB_SAS_DIAG_MODE_START_END\n");3876 break;3877 case OPC_OUB_SAS_DIAG_EXECUTE:3878 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_DIAG_EXECUTE\n");3879 break;3880 case OPC_OUB_GET_TIME_STAMP:3881 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_TIME_STAMP\n");3882 break;3883 case OPC_OUB_SAS_HW_EVENT_ACK:3884 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_HW_EVENT_ACK\n");3885 break;3886 case OPC_OUB_PORT_CONTROL:3887 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_PORT_CONTROL\n");3888 break;3889 case OPC_OUB_SMP_ABORT_RSP:3890 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_ABORT_RSP\n");3891 pm8001_mpi_task_abort_resp(pm8001_ha, piomb);3892 break;3893 case OPC_OUB_GET_NVMD_DATA:3894 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_NVMD_DATA\n");3895 pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);3896 break;3897 case OPC_OUB_SET_NVMD_DATA:3898 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_NVMD_DATA\n");3899 pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);3900 break;3901 case OPC_OUB_DEVICE_HANDLE_REMOVAL:3902 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEVICE_HANDLE_REMOVAL\n");3903 break;3904 case OPC_OUB_SET_DEVICE_STATE:3905 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEVICE_STATE\n");3906 pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);3907 break;3908 case OPC_OUB_GET_DEVICE_STATE:3909 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEVICE_STATE\n");3910 break;3911 case OPC_OUB_SET_DEV_INFO:3912 pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEV_INFO\n");3913 break;3914 /* spcv specific commands */3915 case OPC_OUB_PHY_START_RESP:3916 pm8001_dbg(pm8001_ha, MSG,3917 "OPC_OUB_PHY_START_RESP opcode:%x\n", opc);3918 mpi_phy_start_resp(pm8001_ha, piomb);3919 break;3920 case OPC_OUB_PHY_STOP_RESP:3921 pm8001_dbg(pm8001_ha, MSG,3922 "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc);3923 mpi_phy_stop_resp(pm8001_ha, piomb);3924 break;3925 case OPC_OUB_SET_CONTROLLER_CONFIG:3926 pm8001_dbg(pm8001_ha, MSG,3927 "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc);3928 mpi_set_controller_config_resp(pm8001_ha, piomb);3929 break;3930 case OPC_OUB_GET_CONTROLLER_CONFIG:3931 pm8001_dbg(pm8001_ha, MSG,3932 "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc);3933 mpi_get_controller_config_resp(pm8001_ha, piomb);3934 break;3935 case OPC_OUB_GET_PHY_PROFILE:3936 pm8001_dbg(pm8001_ha, MSG,3937 "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc);3938 mpi_get_phy_profile_resp(pm8001_ha, piomb);3939 break;3940 case OPC_OUB_FLASH_OP_EXT:3941 pm8001_dbg(pm8001_ha, MSG,3942 "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc);3943 mpi_flash_op_ext_resp(pm8001_ha, piomb);3944 break;3945 case OPC_OUB_SET_PHY_PROFILE:3946 pm8001_dbg(pm8001_ha, MSG,3947 "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc);3948 mpi_set_phy_profile_resp(pm8001_ha, piomb);3949 break;3950 case OPC_OUB_KEK_MANAGEMENT_RESP:3951 pm8001_dbg(pm8001_ha, MSG,3952 "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc);3953 mpi_kek_management_resp(pm8001_ha, piomb);3954 break;3955 case OPC_OUB_DEK_MANAGEMENT_RESP:3956 pm8001_dbg(pm8001_ha, MSG,3957 "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc);3958 mpi_dek_management_resp(pm8001_ha, piomb);3959 break;3960 case OPC_OUB_SSP_COALESCED_COMP_RESP:3961 pm8001_dbg(pm8001_ha, MSG,3962 "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc);3963 ssp_coalesced_comp_resp(pm8001_ha, piomb);3964 break;3965 default:3966 pm8001_dbg(pm8001_ha, DEVIO,3967 "Unknown outbound Queue IOMB OPC = 0x%x\n", opc);3968 break;3969 }3970}3971 3972static void print_scratchpad_registers(struct pm8001_hba_info *pm8001_ha)3973{3974 pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_0: 0x%x\n",3975 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0));3976 pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_1:0x%x\n",3977 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1));3978 pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_2: 0x%x\n",3979 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2));3980 pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_3: 0x%x\n",3981 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3));3982 pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_0: 0x%x\n",3983 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0));3984 pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_1: 0x%x\n",3985 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1));3986 pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_2: 0x%x\n",3987 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2));3988 pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_3: 0x%x\n",3989 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3));3990 pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_4: 0x%x\n",3991 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4));3992 pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_5: 0x%x\n",3993 pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5));3994 pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n",3995 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_RSVD_0));3996 pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n",3997 pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_RSVD_1));3998}3999 4000static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)4001{4002 struct outbound_queue_table *circularQ;4003 void *pMsg1 = NULL;4004 u8 bc;4005 u32 ret = MPI_IO_STATUS_FAIL;4006 u32 regval;4007 4008 /*4009 * Fatal errors are programmed to be signalled in irq vector4010 * pm8001_ha->max_q_num - 1 through pm8001_ha->main_cfg_tbl.pm80xx_tbl.4011 * fatal_err_interrupt4012 */4013 if (vec == (pm8001_ha->max_q_num - 1)) {4014 u32 mipsall_ready;4015 4016 if (pm8001_ha->chip_id == chip_8008 ||4017 pm8001_ha->chip_id == chip_8009)4018 mipsall_ready = SCRATCH_PAD_MIPSALL_READY_8PORT;4019 else4020 mipsall_ready = SCRATCH_PAD_MIPSALL_READY_16PORT;4021 4022 regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);4023 if ((regval & mipsall_ready) != mipsall_ready) {4024 pm8001_ha->controller_fatal_error = true;4025 pm8001_dbg(pm8001_ha, FAIL,4026 "Firmware Fatal error! Regval:0x%x\n",4027 regval);4028 pm8001_handle_event(pm8001_ha, NULL, IO_FATAL_ERROR);4029 print_scratchpad_registers(pm8001_ha);4030 return ret;4031 } else {4032 /*read scratchpad rsvd 0 register*/4033 regval = pm8001_cr32(pm8001_ha, 0,4034 MSGU_SCRATCH_PAD_RSVD_0);4035 switch (regval) {4036 case NON_FATAL_SPBC_LBUS_ECC_ERR:4037 case NON_FATAL_BDMA_ERR:4038 case NON_FATAL_THERM_OVERTEMP_ERR:4039 /*Clear the register*/4040 pm8001_cw32(pm8001_ha, 0,4041 MSGU_SCRATCH_PAD_RSVD_0,4042 0x00000000);4043 break;4044 default:4045 break;4046 }4047 }4048 }4049 circularQ = &pm8001_ha->outbnd_q_tbl[vec];4050 spin_lock_irqsave(&circularQ->oq_lock, circularQ->lock_flags);4051 do {4052 /* spurious interrupt during setup if kexec-ing and4053 * driver doing a doorbell access w/ the pre-kexec oq4054 * interrupt setup.4055 */4056 if (!circularQ->pi_virt)4057 break;4058 ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);4059 if (MPI_IO_STATUS_SUCCESS == ret) {4060 /* process the outbound message */4061 process_one_iomb(pm8001_ha, circularQ,4062 (void *)(pMsg1 - 4));4063 /* free the message from the outbound circular buffer */4064 pm8001_mpi_msg_free_set(pm8001_ha, pMsg1,4065 circularQ, bc);4066 }4067 if (MPI_IO_STATUS_BUSY == ret) {4068 /* Update the producer index from SPC */4069 circularQ->producer_index =4070 cpu_to_le32(pm8001_read_32(circularQ->pi_virt));4071 if (le32_to_cpu(circularQ->producer_index) ==4072 circularQ->consumer_idx)4073 /* OQ is empty */4074 break;4075 }4076 } while (1);4077 spin_unlock_irqrestore(&circularQ->oq_lock, circularQ->lock_flags);4078 return ret;4079}4080 4081/* DMA_... to our direction translation. */4082static const u8 data_dir_flags[] = {4083 [DMA_BIDIRECTIONAL] = DATA_DIR_BYRECIPIENT, /* UNSPECIFIED */4084 [DMA_TO_DEVICE] = DATA_DIR_OUT, /* OUTBOUND */4085 [DMA_FROM_DEVICE] = DATA_DIR_IN, /* INBOUND */4086 [DMA_NONE] = DATA_DIR_NONE, /* NO TRANSFER */4087};4088 4089static void build_smp_cmd(u32 deviceID, __le32 hTag,4090 struct smp_req *psmp_cmd, int mode, int length)4091{4092 psmp_cmd->tag = hTag;4093 psmp_cmd->device_id = cpu_to_le32(deviceID);4094 if (mode == SMP_DIRECT) {4095 length = length - 4; /* subtract crc */4096 psmp_cmd->len_ip_ir = cpu_to_le32(length << 16);4097 } else {4098 psmp_cmd->len_ip_ir = cpu_to_le32(1|(1 << 1));4099 }4100}4101 4102/**4103 * pm80xx_chip_smp_req - send an SMP task to FW4104 * @pm8001_ha: our hba card information.4105 * @ccb: the ccb information this request used.4106 */4107static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,4108 struct pm8001_ccb_info *ccb)4109{4110 int elem, rc;4111 struct sas_task *task = ccb->task;4112 struct domain_device *dev = task->dev;4113 struct pm8001_device *pm8001_dev = dev->lldd_dev;4114 struct scatterlist *sg_req, *sg_resp, *smp_req;4115 u32 req_len, resp_len;4116 struct smp_req smp_cmd;4117 u32 opc;4118 u32 i, length;4119 u8 *payload;4120 u8 *to;4121 4122 memset(&smp_cmd, 0, sizeof(smp_cmd));4123 /*4124 * DMA-map SMP request, response buffers4125 */4126 sg_req = &task->smp_task.smp_req;4127 elem = dma_map_sg(pm8001_ha->dev, sg_req, 1, DMA_TO_DEVICE);4128 if (!elem)4129 return -ENOMEM;4130 req_len = sg_dma_len(sg_req);4131 4132 sg_resp = &task->smp_task.smp_resp;4133 elem = dma_map_sg(pm8001_ha->dev, sg_resp, 1, DMA_FROM_DEVICE);4134 if (!elem) {4135 rc = -ENOMEM;4136 goto err_out;4137 }4138 resp_len = sg_dma_len(sg_resp);4139 /* must be in dwords */4140 if ((req_len & 0x3) || (resp_len & 0x3)) {4141 rc = -EINVAL;4142 goto err_out_2;4143 }4144 4145 opc = OPC_INB_SMP_REQUEST;4146 smp_cmd.tag = cpu_to_le32(ccb->ccb_tag);4147 4148 length = sg_req->length;4149 pm8001_dbg(pm8001_ha, IO, "SMP Frame Length %d\n", sg_req->length);4150 if (!(length - 8))4151 pm8001_ha->smp_exp_mode = SMP_DIRECT;4152 else4153 pm8001_ha->smp_exp_mode = SMP_INDIRECT;4154 4155 4156 smp_req = &task->smp_task.smp_req;4157 to = kmap_atomic(sg_page(smp_req));4158 payload = to + smp_req->offset;4159 4160 /* INDIRECT MODE command settings. Use DMA */4161 if (pm8001_ha->smp_exp_mode == SMP_INDIRECT) {4162 pm8001_dbg(pm8001_ha, IO, "SMP REQUEST INDIRECT MODE\n");4163 /* for SPCv indirect mode. Place the top 4 bytes of4164 * SMP Request header here. */4165 for (i = 0; i < 4; i++)4166 smp_cmd.smp_req16[i] = *(payload + i);4167 /* exclude top 4 bytes for SMP req header */4168 smp_cmd.long_smp_req.long_req_addr =4169 cpu_to_le64((u64)sg_dma_address4170 (&task->smp_task.smp_req) + 4);4171 /* exclude 4 bytes for SMP req header and CRC */4172 smp_cmd.long_smp_req.long_req_size =4173 cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8);4174 smp_cmd.long_smp_req.long_resp_addr =4175 cpu_to_le64((u64)sg_dma_address4176 (&task->smp_task.smp_resp));4177 smp_cmd.long_smp_req.long_resp_size =4178 cpu_to_le32((u32)sg_dma_len4179 (&task->smp_task.smp_resp)-4);4180 } else { /* DIRECT MODE */4181 smp_cmd.long_smp_req.long_req_addr =4182 cpu_to_le64((u64)sg_dma_address4183 (&task->smp_task.smp_req));4184 smp_cmd.long_smp_req.long_req_size =4185 cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-4);4186 smp_cmd.long_smp_req.long_resp_addr =4187 cpu_to_le64((u64)sg_dma_address4188 (&task->smp_task.smp_resp));4189 smp_cmd.long_smp_req.long_resp_size =4190 cpu_to_le324191 ((u32)sg_dma_len(&task->smp_task.smp_resp)-4);4192 }4193 if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {4194 pm8001_dbg(pm8001_ha, IO, "SMP REQUEST DIRECT MODE\n");4195 for (i = 0; i < length; i++)4196 if (i < 16) {4197 smp_cmd.smp_req16[i] = *(payload + i);4198 pm8001_dbg(pm8001_ha, IO,4199 "Byte[%d]:%x (DMA data:%x)\n",4200 i, smp_cmd.smp_req16[i],4201 *(payload));4202 } else {4203 smp_cmd.smp_req[i] = *(payload + i);4204 pm8001_dbg(pm8001_ha, IO,4205 "Byte[%d]:%x (DMA data:%x)\n",4206 i, smp_cmd.smp_req[i],4207 *(payload));4208 }4209 }4210 kunmap_atomic(to);4211 build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,4212 &smp_cmd, pm8001_ha->smp_exp_mode, length);4213 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &smp_cmd,4214 sizeof(smp_cmd), 0);4215 if (rc)4216 goto err_out_2;4217 return 0;4218 4219err_out_2:4220 dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_resp, 1,4221 DMA_FROM_DEVICE);4222err_out:4223 dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_req, 1,4224 DMA_TO_DEVICE);4225 return rc;4226}4227 4228static int check_enc_sas_cmd(struct sas_task *task)4229{4230 u8 cmd = task->ssp_task.cmd->cmnd[0];4231 4232 if (cmd == READ_10 || cmd == WRITE_10 || cmd == WRITE_VERIFY)4233 return 1;4234 else4235 return 0;4236}4237 4238static int check_enc_sat_cmd(struct sas_task *task)4239{4240 int ret = 0;4241 switch (task->ata_task.fis.command) {4242 case ATA_CMD_FPDMA_READ:4243 case ATA_CMD_READ_EXT:4244 case ATA_CMD_READ:4245 case ATA_CMD_FPDMA_WRITE:4246 case ATA_CMD_WRITE_EXT:4247 case ATA_CMD_WRITE:4248 case ATA_CMD_PIO_READ:4249 case ATA_CMD_PIO_READ_EXT:4250 case ATA_CMD_PIO_WRITE:4251 case ATA_CMD_PIO_WRITE_EXT:4252 ret = 1;4253 break;4254 default:4255 ret = 0;4256 break;4257 }4258 return ret;4259}4260 4261static u32 pm80xx_chip_get_q_index(struct sas_task *task)4262{4263 struct request *rq = sas_task_find_rq(task);4264 4265 if (!rq)4266 return 0;4267 4268 return blk_mq_unique_tag_to_hwq(blk_mq_unique_tag(rq));4269}4270 4271/**4272 * pm80xx_chip_ssp_io_req - send an SSP task to FW4273 * @pm8001_ha: our hba card information.4274 * @ccb: the ccb information this request used.4275 */4276static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,4277 struct pm8001_ccb_info *ccb)4278{4279 struct sas_task *task = ccb->task;4280 struct domain_device *dev = task->dev;4281 struct pm8001_device *pm8001_dev = dev->lldd_dev;4282 struct ssp_ini_io_start_req ssp_cmd;4283 u32 tag = ccb->ccb_tag;4284 u64 phys_addr, end_addr;4285 u32 end_addr_high, end_addr_low;4286 u32 q_index;4287 u32 opc = OPC_INB_SSPINIIOSTART;4288 4289 memset(&ssp_cmd, 0, sizeof(ssp_cmd));4290 memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);4291 4292 /* data address domain added for spcv; set to 0 by host,4293 * used internally by controller4294 * 0 for SAS 1.1 and SAS 2.0 compatible TLR4295 */4296 ssp_cmd.dad_dir_m_tlr =4297 cpu_to_le32(data_dir_flags[task->data_dir] << 8 | 0x0);4298 ssp_cmd.data_len = cpu_to_le32(task->total_xfer_len);4299 ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);4300 ssp_cmd.tag = cpu_to_le32(tag);4301 ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);4302 memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,4303 task->ssp_task.cmd->cmd_len);4304 q_index = pm80xx_chip_get_q_index(task);4305 4306 /* Check if encryption is set */4307 if (pm8001_ha->chip->encrypt &&4308 !(pm8001_ha->encrypt_info.status) && check_enc_sas_cmd(task)) {4309 pm8001_dbg(pm8001_ha, IO,4310 "Encryption enabled.Sending Encrypt SAS command 0x%x\n",4311 task->ssp_task.cmd->cmnd[0]);4312 opc = OPC_INB_SSP_INI_DIF_ENC_IO;4313 /* enable encryption. 0 for SAS 1.1 and SAS 2.0 compatible TLR*/4314 ssp_cmd.dad_dir_m_tlr = cpu_to_le324315 ((data_dir_flags[task->data_dir] << 8) | 0x20 | 0x0);4316 4317 /* fill in PRD (scatter/gather) table, if any */4318 if (task->num_scatter > 1) {4319 pm8001_chip_make_sg(task->scatter,4320 ccb->n_elem, ccb->buf_prd);4321 phys_addr = ccb->ccb_dma_handle;4322 ssp_cmd.enc_addr_low =4323 cpu_to_le32(lower_32_bits(phys_addr));4324 ssp_cmd.enc_addr_high =4325 cpu_to_le32(upper_32_bits(phys_addr));4326 ssp_cmd.enc_esgl = cpu_to_le32(1<<31);4327 } else if (task->num_scatter == 1) {4328 u64 dma_addr = sg_dma_address(task->scatter);4329 4330 ssp_cmd.enc_addr_low =4331 cpu_to_le32(lower_32_bits(dma_addr));4332 ssp_cmd.enc_addr_high =4333 cpu_to_le32(upper_32_bits(dma_addr));4334 ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);4335 ssp_cmd.enc_esgl = 0;4336 4337 /* Check 4G Boundary */4338 end_addr = dma_addr + le32_to_cpu(ssp_cmd.enc_len) - 1;4339 end_addr_low = lower_32_bits(end_addr);4340 end_addr_high = upper_32_bits(end_addr);4341 4342 if (end_addr_high != le32_to_cpu(ssp_cmd.enc_addr_high)) {4343 pm8001_dbg(pm8001_ha, FAIL,4344 "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",4345 dma_addr,4346 le32_to_cpu(ssp_cmd.enc_len),4347 end_addr_high, end_addr_low);4348 pm8001_chip_make_sg(task->scatter, 1,4349 ccb->buf_prd);4350 phys_addr = ccb->ccb_dma_handle;4351 ssp_cmd.enc_addr_low =4352 cpu_to_le32(lower_32_bits(phys_addr));4353 ssp_cmd.enc_addr_high =4354 cpu_to_le32(upper_32_bits(phys_addr));4355 ssp_cmd.enc_esgl = cpu_to_le32(1U<<31);4356 }4357 } else if (task->num_scatter == 0) {4358 ssp_cmd.enc_addr_low = 0;4359 ssp_cmd.enc_addr_high = 0;4360 ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);4361 ssp_cmd.enc_esgl = 0;4362 }4363 4364 /* XTS mode. All other fields are 0 */4365 ssp_cmd.key_cmode = cpu_to_le32(0x6 << 4);4366 4367 /* set tweak values. Should be the start lba */4368 ssp_cmd.twk_val0 = cpu_to_le32((task->ssp_task.cmd->cmnd[2] << 24) |4369 (task->ssp_task.cmd->cmnd[3] << 16) |4370 (task->ssp_task.cmd->cmnd[4] << 8) |4371 (task->ssp_task.cmd->cmnd[5]));4372 } else {4373 pm8001_dbg(pm8001_ha, IO,4374 "Sending Normal SAS command 0x%x inb q %x\n",4375 task->ssp_task.cmd->cmnd[0], q_index);4376 /* fill in PRD (scatter/gather) table, if any */4377 if (task->num_scatter > 1) {4378 pm8001_chip_make_sg(task->scatter, ccb->n_elem,4379 ccb->buf_prd);4380 phys_addr = ccb->ccb_dma_handle;4381 ssp_cmd.addr_low =4382 cpu_to_le32(lower_32_bits(phys_addr));4383 ssp_cmd.addr_high =4384 cpu_to_le32(upper_32_bits(phys_addr));4385 ssp_cmd.esgl = cpu_to_le32(1<<31);4386 } else if (task->num_scatter == 1) {4387 u64 dma_addr = sg_dma_address(task->scatter);4388 4389 ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr));4390 ssp_cmd.addr_high =4391 cpu_to_le32(upper_32_bits(dma_addr));4392 ssp_cmd.len = cpu_to_le32(task->total_xfer_len);4393 ssp_cmd.esgl = 0;4394 4395 /* Check 4G Boundary */4396 end_addr = dma_addr + le32_to_cpu(ssp_cmd.len) - 1;4397 end_addr_low = lower_32_bits(end_addr);4398 end_addr_high = upper_32_bits(end_addr);4399 if (end_addr_high != le32_to_cpu(ssp_cmd.addr_high)) {4400 pm8001_dbg(pm8001_ha, FAIL,4401 "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",4402 dma_addr,4403 le32_to_cpu(ssp_cmd.len),4404 end_addr_high, end_addr_low);4405 pm8001_chip_make_sg(task->scatter, 1,4406 ccb->buf_prd);4407 phys_addr = ccb->ccb_dma_handle;4408 ssp_cmd.addr_low =4409 cpu_to_le32(lower_32_bits(phys_addr));4410 ssp_cmd.addr_high =4411 cpu_to_le32(upper_32_bits(phys_addr));4412 ssp_cmd.esgl = cpu_to_le32(1<<31);4413 }4414 } else if (task->num_scatter == 0) {4415 ssp_cmd.addr_low = 0;4416 ssp_cmd.addr_high = 0;4417 ssp_cmd.len = cpu_to_le32(task->total_xfer_len);4418 ssp_cmd.esgl = 0;4419 }4420 }4421 4422 return pm8001_mpi_build_cmd(pm8001_ha, q_index, opc, &ssp_cmd,4423 sizeof(ssp_cmd), q_index);4424}4425 4426static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,4427 struct pm8001_ccb_info *ccb)4428{4429 struct sas_task *task = ccb->task;4430 struct domain_device *dev = task->dev;4431 struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;4432 struct ata_queued_cmd *qc = task->uldd_task;4433 u32 tag = ccb->ccb_tag, q_index;4434 struct sata_start_req sata_cmd;4435 u32 hdr_tag, ncg_tag = 0;4436 u64 phys_addr, end_addr;4437 u32 end_addr_high, end_addr_low;4438 u32 ATAP = 0x0;4439 u32 dir, retfis = 0;4440 u32 opc = OPC_INB_SATA_HOST_OPSTART;4441 memset(&sata_cmd, 0, sizeof(sata_cmd));4442 4443 q_index = pm80xx_chip_get_q_index(task);4444 4445 if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {4446 ATAP = 0x04; /* no data*/4447 pm8001_dbg(pm8001_ha, IO, "no data\n");4448 } else if (likely(!task->ata_task.device_control_reg_update)) {4449 if (task->ata_task.use_ncq &&4450 dev->sata_dev.class != ATA_DEV_ATAPI) {4451 ATAP = 0x07; /* FPDMA */4452 pm8001_dbg(pm8001_ha, IO, "FPDMA\n");4453 } else if (task->ata_task.dma_xfer) {4454 ATAP = 0x06; /* DMA */4455 pm8001_dbg(pm8001_ha, IO, "DMA\n");4456 } else {4457 ATAP = 0x05; /* PIO*/4458 pm8001_dbg(pm8001_ha, IO, "PIO\n");4459 }4460 }4461 if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {4462 task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);4463 ncg_tag = hdr_tag;4464 }4465 dir = data_dir_flags[task->data_dir] << 8;4466 sata_cmd.tag = cpu_to_le32(tag);4467 sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);4468 sata_cmd.data_len = cpu_to_le32(task->total_xfer_len);4469 if (task->ata_task.return_fis_on_success)4470 retfis = 1;4471 sata_cmd.sata_fis = task->ata_task.fis;4472 if (likely(!task->ata_task.device_control_reg_update))4473 sata_cmd.sata_fis.flags |= 0x80;/* C=1: update ATA cmd reg */4474 sata_cmd.sata_fis.flags &= 0xF0;/* PM_PORT field shall be 0 */4475 4476 /* Check if encryption is set */4477 if (pm8001_ha->chip->encrypt &&4478 !(pm8001_ha->encrypt_info.status) && check_enc_sat_cmd(task)) {4479 pm8001_dbg(pm8001_ha, IO,4480 "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n",4481 sata_cmd.sata_fis.command);4482 opc = OPC_INB_SATA_DIF_ENC_IO;4483 /* set encryption bit; dad (bits 0-1) is 0 */4484 sata_cmd.retfis_ncqtag_atap_dir_m_dad =4485 cpu_to_le32((retfis << 24) | ((ncg_tag & 0xff) << 16) |4486 ((ATAP & 0x3f) << 10) | 0x20 | dir);4487 /* fill in PRD (scatter/gather) table, if any */4488 if (task->num_scatter > 1) {4489 pm8001_chip_make_sg(task->scatter,4490 ccb->n_elem, ccb->buf_prd);4491 phys_addr = ccb->ccb_dma_handle;4492 sata_cmd.enc_addr_low =4493 cpu_to_le32(lower_32_bits(phys_addr));4494 sata_cmd.enc_addr_high =4495 cpu_to_le32(upper_32_bits(phys_addr));4496 sata_cmd.enc_esgl = cpu_to_le32(1 << 31);4497 } else if (task->num_scatter == 1) {4498 u64 dma_addr = sg_dma_address(task->scatter);4499 4500 sata_cmd.enc_addr_low =4501 cpu_to_le32(lower_32_bits(dma_addr));4502 sata_cmd.enc_addr_high =4503 cpu_to_le32(upper_32_bits(dma_addr));4504 sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);4505 sata_cmd.enc_esgl = 0;4506 4507 /* Check 4G Boundary */4508 end_addr = dma_addr + le32_to_cpu(sata_cmd.enc_len) - 1;4509 end_addr_low = lower_32_bits(end_addr);4510 end_addr_high = upper_32_bits(end_addr);4511 if (end_addr_high != le32_to_cpu(sata_cmd.enc_addr_high)) {4512 pm8001_dbg(pm8001_ha, FAIL,4513 "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",4514 dma_addr,4515 le32_to_cpu(sata_cmd.enc_len),4516 end_addr_high, end_addr_low);4517 pm8001_chip_make_sg(task->scatter, 1,4518 ccb->buf_prd);4519 phys_addr = ccb->ccb_dma_handle;4520 sata_cmd.enc_addr_low =4521 cpu_to_le32(lower_32_bits(phys_addr));4522 sata_cmd.enc_addr_high =4523 cpu_to_le32(upper_32_bits(phys_addr));4524 sata_cmd.enc_esgl =4525 cpu_to_le32(1 << 31);4526 }4527 } else if (task->num_scatter == 0) {4528 sata_cmd.enc_addr_low = 0;4529 sata_cmd.enc_addr_high = 0;4530 sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);4531 sata_cmd.enc_esgl = 0;4532 }4533 /* XTS mode. All other fields are 0 */4534 sata_cmd.key_index_mode = cpu_to_le32(0x6 << 4);4535 4536 /* set tweak values. Should be the start lba */4537 sata_cmd.twk_val0 =4538 cpu_to_le32((sata_cmd.sata_fis.lbal_exp << 24) |4539 (sata_cmd.sata_fis.lbah << 16) |4540 (sata_cmd.sata_fis.lbam << 8) |4541 (sata_cmd.sata_fis.lbal));4542 sata_cmd.twk_val1 =4543 cpu_to_le32((sata_cmd.sata_fis.lbah_exp << 8) |4544 (sata_cmd.sata_fis.lbam_exp));4545 } else {4546 pm8001_dbg(pm8001_ha, IO,4547 "Sending Normal SATA command 0x%x inb %x\n",4548 sata_cmd.sata_fis.command, q_index);4549 /* dad (bits 0-1) is 0 */4550 sata_cmd.retfis_ncqtag_atap_dir_m_dad =4551 cpu_to_le32((retfis << 24) | ((ncg_tag & 0xff) << 16) |4552 ((ATAP & 0x3f) << 10) | dir);4553 /* fill in PRD (scatter/gather) table, if any */4554 if (task->num_scatter > 1) {4555 pm8001_chip_make_sg(task->scatter,4556 ccb->n_elem, ccb->buf_prd);4557 phys_addr = ccb->ccb_dma_handle;4558 sata_cmd.addr_low = lower_32_bits(phys_addr);4559 sata_cmd.addr_high = upper_32_bits(phys_addr);4560 sata_cmd.esgl = cpu_to_le32(1U << 31);4561 } else if (task->num_scatter == 1) {4562 u64 dma_addr = sg_dma_address(task->scatter);4563 4564 sata_cmd.addr_low = lower_32_bits(dma_addr);4565 sata_cmd.addr_high = upper_32_bits(dma_addr);4566 sata_cmd.len = cpu_to_le32(task->total_xfer_len);4567 sata_cmd.esgl = 0;4568 4569 /* Check 4G Boundary */4570 end_addr = dma_addr + le32_to_cpu(sata_cmd.len) - 1;4571 end_addr_low = lower_32_bits(end_addr);4572 end_addr_high = upper_32_bits(end_addr);4573 if (end_addr_high != sata_cmd.addr_high) {4574 pm8001_dbg(pm8001_ha, FAIL,4575 "The sg list address start_addr=0x%016llx data_len=0x%xend_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",4576 dma_addr,4577 le32_to_cpu(sata_cmd.len),4578 end_addr_high, end_addr_low);4579 pm8001_chip_make_sg(task->scatter, 1,4580 ccb->buf_prd);4581 phys_addr = ccb->ccb_dma_handle;4582 sata_cmd.addr_low = lower_32_bits(phys_addr);4583 sata_cmd.addr_high = upper_32_bits(phys_addr);4584 sata_cmd.esgl = cpu_to_le32(1U << 31);4585 }4586 } else if (task->num_scatter == 0) {4587 sata_cmd.addr_low = 0;4588 sata_cmd.addr_high = 0;4589 sata_cmd.len = cpu_to_le32(task->total_xfer_len);4590 sata_cmd.esgl = 0;4591 }4592 4593 /* scsi cdb */4594 sata_cmd.atapi_scsi_cdb[0] =4595 cpu_to_le32(((task->ata_task.atapi_packet[0]) |4596 (task->ata_task.atapi_packet[1] << 8) |4597 (task->ata_task.atapi_packet[2] << 16) |4598 (task->ata_task.atapi_packet[3] << 24)));4599 sata_cmd.atapi_scsi_cdb[1] =4600 cpu_to_le32(((task->ata_task.atapi_packet[4]) |4601 (task->ata_task.atapi_packet[5] << 8) |4602 (task->ata_task.atapi_packet[6] << 16) |4603 (task->ata_task.atapi_packet[7] << 24)));4604 sata_cmd.atapi_scsi_cdb[2] =4605 cpu_to_le32(((task->ata_task.atapi_packet[8]) |4606 (task->ata_task.atapi_packet[9] << 8) |4607 (task->ata_task.atapi_packet[10] << 16) |4608 (task->ata_task.atapi_packet[11] << 24)));4609 sata_cmd.atapi_scsi_cdb[3] =4610 cpu_to_le32(((task->ata_task.atapi_packet[12]) |4611 (task->ata_task.atapi_packet[13] << 8) |4612 (task->ata_task.atapi_packet[14] << 16) |4613 (task->ata_task.atapi_packet[15] << 24)));4614 }4615 4616 trace_pm80xx_request_issue(pm8001_ha->id,4617 ccb->device ? ccb->device->attached_phy : PM8001_MAX_PHYS,4618 ccb->ccb_tag, opc,4619 qc ? qc->tf.command : 0, // ata opcode4620 ccb->device ? atomic_read(&ccb->device->running_req) : 0);4621 return pm8001_mpi_build_cmd(pm8001_ha, q_index, opc, &sata_cmd,4622 sizeof(sata_cmd), q_index);4623}4624 4625/**4626 * pm80xx_chip_phy_start_req - start phy via PHY_START COMMAND4627 * @pm8001_ha: our hba card information.4628 * @phy_id: the phy id which we wanted to start up.4629 */4630static int4631pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)4632{4633 struct phy_start_req payload;4634 u32 tag = 0x01;4635 u32 opcode = OPC_INB_PHYSTART;4636 4637 memset(&payload, 0, sizeof(payload));4638 payload.tag = cpu_to_le32(tag);4639 4640 pm8001_dbg(pm8001_ha, INIT, "PHY START REQ for phy_id %d\n", phy_id);4641 4642 payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |4643 LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);4644 /* SSC Disable and SAS Analog ST configuration */4645 /*4646 payload.ase_sh_lm_slr_phyid =4647 cpu_to_le32(SSC_DISABLE_30 | SAS_ASE | SPINHOLD_DISABLE |4648 LINKMODE_AUTO | LINKRATE_15 | LINKRATE_30 | LINKRATE_60 |4649 phy_id);4650 Have to add "SAS PHY Analog Setup SPASTI 1 Byte" Based on need4651 */4652 4653 payload.sas_identify.dev_type = SAS_END_DEVICE;4654 payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;4655 memcpy(payload.sas_identify.sas_addr,4656 &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);4657 payload.sas_identify.phy_id = phy_id;4658 4659 return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,4660 sizeof(payload), 0);4661}4662 4663/**4664 * pm80xx_chip_phy_stop_req - start phy via PHY_STOP COMMAND4665 * @pm8001_ha: our hba card information.4666 * @phy_id: the phy id which we wanted to start up.4667 */4668static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,4669 u8 phy_id)4670{4671 struct phy_stop_req payload;4672 u32 tag = 0x01;4673 u32 opcode = OPC_INB_PHYSTOP;4674 4675 memset(&payload, 0, sizeof(payload));4676 payload.tag = cpu_to_le32(tag);4677 payload.phy_id = cpu_to_le32(phy_id);4678 4679 return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload,4680 sizeof(payload), 0);4681}4682 4683/*4684 * see comments on pm8001_mpi_reg_resp.4685 */4686static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,4687 struct pm8001_device *pm8001_dev, u32 flag)4688{4689 struct reg_dev_req payload;4690 u32 opc;4691 u32 stp_sspsmp_sata = 0x4;4692 u32 linkrate, phy_id;4693 int rc;4694 struct pm8001_ccb_info *ccb;4695 u8 retryFlag = 0x1;4696 u16 firstBurstSize = 0;4697 u16 ITNT = 2000;4698 struct domain_device *dev = pm8001_dev->sas_device;4699 struct domain_device *parent_dev = dev->parent;4700 struct pm8001_port *port = dev->port->lldd_port;4701 4702 memset(&payload, 0, sizeof(payload));4703 ccb = pm8001_ccb_alloc(pm8001_ha, pm8001_dev, NULL);4704 if (!ccb)4705 return -SAS_QUEUE_FULL;4706 4707 payload.tag = cpu_to_le32(ccb->ccb_tag);4708 4709 if (flag == 1) {4710 stp_sspsmp_sata = 0x02; /*direct attached sata */4711 } else {4712 if (pm8001_dev->dev_type == SAS_SATA_DEV)4713 stp_sspsmp_sata = 0x00; /* stp*/4714 else if (pm8001_dev->dev_type == SAS_END_DEVICE ||4715 dev_is_expander(pm8001_dev->dev_type))4716 stp_sspsmp_sata = 0x01; /*ssp or smp*/4717 }4718 if (parent_dev && dev_is_expander(parent_dev->dev_type))4719 phy_id = parent_dev->ex_dev.ex_phy->phy_id;4720 else4721 phy_id = pm8001_dev->attached_phy;4722 4723 opc = OPC_INB_REG_DEV;4724 4725 linkrate = (pm8001_dev->sas_device->linkrate < dev->port->linkrate) ?4726 pm8001_dev->sas_device->linkrate : dev->port->linkrate;4727 4728 payload.phyid_portid =4729 cpu_to_le32(((port->port_id) & 0xFF) |4730 ((phy_id & 0xFF) << 8));4731 4732 payload.dtype_dlr_mcn_ir_retry = cpu_to_le32((retryFlag & 0x01) |4733 ((linkrate & 0x0F) << 24) |4734 ((stp_sspsmp_sata & 0x03) << 28));4735 payload.firstburstsize_ITNexustimeout =4736 cpu_to_le32(ITNT | (firstBurstSize * 0x10000));4737 4738 memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,4739 SAS_ADDR_SIZE);4740 4741 pm8001_dbg(pm8001_ha, INIT,4742 "register device req phy_id 0x%x port_id 0x%x\n", phy_id,4743 (port->port_id & 0xFF));4744 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,4745 sizeof(payload), 0);4746 if (rc)4747 pm8001_ccb_free(pm8001_ha, ccb);4748 4749 return rc;4750}4751 4752/**4753 * pm80xx_chip_phy_ctl_req - support the local phy operation4754 * @pm8001_ha: our hba card information.4755 * @phyId: the phy id which we wanted to operate4756 * @phy_op: phy operation to request4757 */4758static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,4759 u32 phyId, u32 phy_op)4760{4761 u32 tag;4762 int rc;4763 struct local_phy_ctl_req payload;4764 u32 opc = OPC_INB_LOCAL_PHY_CONTROL;4765 4766 memset(&payload, 0, sizeof(payload));4767 rc = pm8001_tag_alloc(pm8001_ha, &tag);4768 if (rc)4769 return rc;4770 4771 payload.tag = cpu_to_le32(tag);4772 payload.phyop_phyid =4773 cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));4774 4775 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,4776 sizeof(payload), 0);4777 if (rc)4778 pm8001_tag_free(pm8001_ha, tag);4779 4780 return rc;4781}4782 4783static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)4784{4785 u32 value;4786 4787 if (pm8001_ha->use_msix)4788 return 1;4789 4790 value = pm8001_cr32(pm8001_ha, 0, MSGU_ODR);4791 if (value)4792 return 1;4793 return 0;4794}4795 4796/**4797 * pm80xx_chip_isr - PM8001 isr handler.4798 * @pm8001_ha: our hba card information.4799 * @vec: irq number.4800 */4801static irqreturn_t4802pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)4803{4804 pm80xx_chip_interrupt_disable(pm8001_ha, vec);4805 pm8001_dbg(pm8001_ha, DEVIO,4806 "irq vec %d, ODMR:0x%x\n",4807 vec, pm8001_cr32(pm8001_ha, 0, 0x30));4808 process_oq(pm8001_ha, vec);4809 pm80xx_chip_interrupt_enable(pm8001_ha, vec);4810 return IRQ_HANDLED;4811}4812 4813static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,4814 u32 operation, u32 phyid,4815 u32 length, u32 *buf)4816{4817 u32 tag, i, j = 0;4818 int rc;4819 struct set_phy_profile_req payload;4820 u32 opc = OPC_INB_SET_PHY_PROFILE;4821 4822 memset(&payload, 0, sizeof(payload));4823 rc = pm8001_tag_alloc(pm8001_ha, &tag);4824 if (rc) {4825 pm8001_dbg(pm8001_ha, FAIL, "Invalid tag\n");4826 return;4827 }4828 4829 payload.tag = cpu_to_le32(tag);4830 payload.ppc_phyid =4831 cpu_to_le32(((operation & 0xF) << 8) | (phyid & 0xFF));4832 pm8001_dbg(pm8001_ha, DISC,4833 " phy profile command for phy %x ,length is %d\n",4834 le32_to_cpu(payload.ppc_phyid), length);4835 for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) {4836 payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i));4837 j++;4838 }4839 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,4840 sizeof(payload), 0);4841 if (rc)4842 pm8001_tag_free(pm8001_ha, tag);4843}4844 4845void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,4846 u32 length, u8 *buf)4847{4848 u32 i;4849 4850 for (i = 0; i < pm8001_ha->chip->n_phy; i++) {4851 mpi_set_phy_profile_req(pm8001_ha,4852 SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf);4853 length = length + PHY_DWORD_LENGTH;4854 }4855 pm8001_dbg(pm8001_ha, INIT, "phy settings completed\n");4856}4857 4858void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,4859 u32 phy, u32 length, u32 *buf)4860{4861 u32 tag, opc;4862 int rc, i;4863 struct set_phy_profile_req payload;4864 4865 memset(&payload, 0, sizeof(payload));4866 4867 rc = pm8001_tag_alloc(pm8001_ha, &tag);4868 if (rc) {4869 pm8001_dbg(pm8001_ha, INIT, "Invalid tag\n");4870 return;4871 }4872 4873 opc = OPC_INB_SET_PHY_PROFILE;4874 4875 payload.tag = cpu_to_le32(tag);4876 payload.ppc_phyid =4877 cpu_to_le32(((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8)4878 | (phy & 0xFF));4879 4880 for (i = 0; i < length; i++)4881 payload.reserved[i] = cpu_to_le32(*(buf + i));4882 4883 rc = pm8001_mpi_build_cmd(pm8001_ha, 0, opc, &payload,4884 sizeof(payload), 0);4885 if (rc)4886 pm8001_tag_free(pm8001_ha, tag);4887 4888 pm8001_dbg(pm8001_ha, INIT, "PHY %d settings applied\n", phy);4889}4890const struct pm8001_dispatch pm8001_80xx_dispatch = {4891 .name = "pmc80xx",4892 .chip_init = pm80xx_chip_init,4893 .chip_post_init = pm80xx_chip_post_init,4894 .chip_soft_rst = pm80xx_chip_soft_rst,4895 .chip_rst = pm80xx_hw_chip_rst,4896 .chip_iounmap = pm8001_chip_iounmap,4897 .isr = pm80xx_chip_isr,4898 .is_our_interrupt = pm80xx_chip_is_our_interrupt,4899 .isr_process_oq = process_oq,4900 .interrupt_enable = pm80xx_chip_interrupt_enable,4901 .interrupt_disable = pm80xx_chip_interrupt_disable,4902 .make_prd = pm8001_chip_make_sg,4903 .smp_req = pm80xx_chip_smp_req,4904 .ssp_io_req = pm80xx_chip_ssp_io_req,4905 .sata_req = pm80xx_chip_sata_req,4906 .phy_start_req = pm80xx_chip_phy_start_req,4907 .phy_stop_req = pm80xx_chip_phy_stop_req,4908 .reg_dev_req = pm80xx_chip_reg_dev_req,4909 .dereg_dev_req = pm8001_chip_dereg_dev_req,4910 .phy_ctl_req = pm80xx_chip_phy_ctl_req,4911 .task_abort = pm8001_chip_abort_task,4912 .ssp_tm_req = pm8001_chip_ssp_tm_req,4913 .get_nvmd_req = pm8001_chip_get_nvmd_req,4914 .set_nvmd_req = pm8001_chip_set_nvmd_req,4915 .fw_flash_update_req = pm8001_chip_fw_flash_update_req,4916 .set_dev_state_req = pm8001_chip_set_dev_state_req,4917 .fatal_errors = pm80xx_fatal_errors,4918 .hw_event_ack_req = pm80xx_hw_event_ack_req,4919};4920