18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2008-2009 PMC-Sierra, Inc.,
58c2ecf20Sopenharmony_ci * All rights reserved.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
88c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
98c2ecf20Sopenharmony_ci * are met:
108c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
118c2ecf20Sopenharmony_ci * notice, this list of conditions, and the following disclaimer,
128c2ecf20Sopenharmony_ci * without modification.
138c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer
148c2ecf20Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below
158c2ecf20Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon
168c2ecf20Sopenharmony_ci * including a substantially similar Disclaimer requirement for further
178c2ecf20Sopenharmony_ci * binary redistribution.
188c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names
198c2ecf20Sopenharmony_ci * of any contributors may be used to endorse or promote products derived
208c2ecf20Sopenharmony_ci * from this software without specific prior written permission.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the
238c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free
248c2ecf20Sopenharmony_ci * Software Foundation.
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * NO WARRANTY
278c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
288c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
298c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
308c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
318c2ecf20Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
328c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
338c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
348c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
358c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
368c2ecf20Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
378c2ecf20Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES.
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_ci #include <linux/slab.h>
418c2ecf20Sopenharmony_ci #include "pm8001_sas.h"
428c2ecf20Sopenharmony_ci #include "pm80xx_hwi.h"
438c2ecf20Sopenharmony_ci #include "pm8001_chips.h"
448c2ecf20Sopenharmony_ci #include "pm8001_ctl.h"
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#define SMP_DIRECT 1
478c2ecf20Sopenharmony_ci#define SMP_INDIRECT 2
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciint pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	u32 reg_val;
538c2ecf20Sopenharmony_ci	unsigned long start;
548c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, shift_value);
558c2ecf20Sopenharmony_ci	/* confirm the setting is written */
568c2ecf20Sopenharmony_ci	start = jiffies + HZ; /* 1 sec */
578c2ecf20Sopenharmony_ci	do {
588c2ecf20Sopenharmony_ci		reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER);
598c2ecf20Sopenharmony_ci	} while ((reg_val != shift_value) && time_before(jiffies, start));
608c2ecf20Sopenharmony_ci	if (reg_val != shift_value) {
618c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:MEMBASE_II_SHIFT_REGISTER = 0x%x\n",
628c2ecf20Sopenharmony_ci			   reg_val);
638c2ecf20Sopenharmony_ci		return -1;
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci	return 0;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic void pm80xx_pci_mem_copy(struct pm8001_hba_info  *pm8001_ha, u32 soffset,
698c2ecf20Sopenharmony_ci				__le32 *destination,
708c2ecf20Sopenharmony_ci				u32 dw_count, u32 bus_base_number)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	u32 index, value, offset;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	for (index = 0; index < dw_count; index += 4, destination++) {
758c2ecf20Sopenharmony_ci		offset = (soffset + index);
768c2ecf20Sopenharmony_ci		if (offset < (64 * 1024)) {
778c2ecf20Sopenharmony_ci			value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
788c2ecf20Sopenharmony_ci			*destination = cpu_to_le32(value);
798c2ecf20Sopenharmony_ci		}
808c2ecf20Sopenharmony_ci	}
818c2ecf20Sopenharmony_ci	return;
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cissize_t pm80xx_get_fatal_dump(struct device *cdev,
858c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(cdev);
888c2ecf20Sopenharmony_ci	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
898c2ecf20Sopenharmony_ci	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
908c2ecf20Sopenharmony_ci	void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;
918c2ecf20Sopenharmony_ci	u32 accum_len , reg_val, index, *temp;
928c2ecf20Sopenharmony_ci	u32 status = 1;
938c2ecf20Sopenharmony_ci	unsigned long start;
948c2ecf20Sopenharmony_ci	u8 *direct_data;
958c2ecf20Sopenharmony_ci	char *fatal_error_data = buf;
968c2ecf20Sopenharmony_ci	u32 length_to_read;
978c2ecf20Sopenharmony_ci	u32 offset;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	pm8001_ha->forensic_info.data_buf.direct_data = buf;
1008c2ecf20Sopenharmony_ci	if (pm8001_ha->chip_id == chip_8001) {
1018c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.direct_data +=
1028c2ecf20Sopenharmony_ci			sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
1038c2ecf20Sopenharmony_ci			"Not supported for SPC controller");
1048c2ecf20Sopenharmony_ci		return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
1058c2ecf20Sopenharmony_ci			(char *)buf;
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci	/* initialize variables for very first call from host application */
1088c2ecf20Sopenharmony_ci	if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
1098c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
1108c2ecf20Sopenharmony_ci			   "forensic_info TYPE_NON_FATAL..............\n");
1118c2ecf20Sopenharmony_ci		direct_data = (u8 *)fatal_error_data;
1128c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;
1138c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;
1148c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.direct_offset = 0;
1158c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.read_len = 0;
1168c2ecf20Sopenharmony_ci		pm8001_ha->forensic_preserved_accumulated_transfer = 0;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci		/* Write signature to fatal dump table */
1198c2ecf20Sopenharmony_ci		pm8001_mw32(fatal_table_address,
1208c2ecf20Sopenharmony_ci				MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
1238c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "ossaHwCB: status1 %d\n", status);
1248c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "ossaHwCB: read_len 0x%x\n",
1258c2ecf20Sopenharmony_ci			   pm8001_ha->forensic_info.data_buf.read_len);
1268c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_len 0x%x\n",
1278c2ecf20Sopenharmony_ci			   pm8001_ha->forensic_info.data_buf.direct_len);
1288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_offset 0x%x\n",
1298c2ecf20Sopenharmony_ci			   pm8001_ha->forensic_info.data_buf.direct_offset);
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci	if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
1328c2ecf20Sopenharmony_ci		/* start to get data */
1338c2ecf20Sopenharmony_ci		/* Program the MEMBASE II Shifting Register with 0x00.*/
1348c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
1358c2ecf20Sopenharmony_ci				pm8001_ha->fatal_forensic_shift_offset);
1368c2ecf20Sopenharmony_ci		pm8001_ha->forensic_last_offset = 0;
1378c2ecf20Sopenharmony_ci		pm8001_ha->forensic_fatal_step = 0;
1388c2ecf20Sopenharmony_ci		pm8001_ha->fatal_bar_loc = 0;
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	/* Read until accum_len is retrived */
1428c2ecf20Sopenharmony_ci	accum_len = pm8001_mr32(fatal_table_address,
1438c2ecf20Sopenharmony_ci				MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
1448c2ecf20Sopenharmony_ci	/* Determine length of data between previously stored transfer length
1458c2ecf20Sopenharmony_ci	 * and current accumulated transfer length
1468c2ecf20Sopenharmony_ci	 */
1478c2ecf20Sopenharmony_ci	length_to_read =
1488c2ecf20Sopenharmony_ci		accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;
1498c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: accum_len 0x%x\n",
1508c2ecf20Sopenharmony_ci		   accum_len);
1518c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: length_to_read 0x%x\n",
1528c2ecf20Sopenharmony_ci		   length_to_read);
1538c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: last_offset 0x%x\n",
1548c2ecf20Sopenharmony_ci		   pm8001_ha->forensic_last_offset);
1558c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: read_len 0x%x\n",
1568c2ecf20Sopenharmony_ci		   pm8001_ha->forensic_info.data_buf.read_len);
1578c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_len 0x%x\n",
1588c2ecf20Sopenharmony_ci		   pm8001_ha->forensic_info.data_buf.direct_len);
1598c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_offset 0x%x\n",
1608c2ecf20Sopenharmony_ci		   pm8001_ha->forensic_info.data_buf.direct_offset);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	/* If accumulated length failed to read correctly fail the attempt.*/
1638c2ecf20Sopenharmony_ci	if (accum_len == 0xFFFFFFFF) {
1648c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
1658c2ecf20Sopenharmony_ci			   "Possible PCI issue 0x%x not expected\n",
1668c2ecf20Sopenharmony_ci			   accum_len);
1678c2ecf20Sopenharmony_ci		return status;
1688c2ecf20Sopenharmony_ci	}
1698c2ecf20Sopenharmony_ci	/* If accumulated length is zero fail the attempt */
1708c2ecf20Sopenharmony_ci	if (accum_len == 0) {
1718c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.direct_data +=
1728c2ecf20Sopenharmony_ci			sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
1738c2ecf20Sopenharmony_ci			"%08x ", 0xFFFFFFFF);
1748c2ecf20Sopenharmony_ci		return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
1758c2ecf20Sopenharmony_ci			(char *)buf;
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci	/* Accumulated length is good so start capturing the first data */
1788c2ecf20Sopenharmony_ci	temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
1798c2ecf20Sopenharmony_ci	if (pm8001_ha->forensic_fatal_step == 0) {
1808c2ecf20Sopenharmony_cimoreData:
1818c2ecf20Sopenharmony_ci		/* If data to read is less than SYSFS_OFFSET then reduce the
1828c2ecf20Sopenharmony_ci		 * length of dataLen
1838c2ecf20Sopenharmony_ci		 */
1848c2ecf20Sopenharmony_ci		if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET
1858c2ecf20Sopenharmony_ci				> length_to_read) {
1868c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_len =
1878c2ecf20Sopenharmony_ci				length_to_read -
1888c2ecf20Sopenharmony_ci				pm8001_ha->forensic_last_offset;
1898c2ecf20Sopenharmony_ci		} else {
1908c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_len =
1918c2ecf20Sopenharmony_ci				SYSFS_OFFSET;
1928c2ecf20Sopenharmony_ci		}
1938c2ecf20Sopenharmony_ci		if (pm8001_ha->forensic_info.data_buf.direct_data) {
1948c2ecf20Sopenharmony_ci			/* Data is in bar, copy to host memory */
1958c2ecf20Sopenharmony_ci			pm80xx_pci_mem_copy(pm8001_ha,
1968c2ecf20Sopenharmony_ci			pm8001_ha->fatal_bar_loc,
1978c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
1988c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_len, 1);
1998c2ecf20Sopenharmony_ci		}
2008c2ecf20Sopenharmony_ci		pm8001_ha->fatal_bar_loc +=
2018c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_len;
2028c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.direct_offset +=
2038c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_len;
2048c2ecf20Sopenharmony_ci		pm8001_ha->forensic_last_offset	+=
2058c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_len;
2068c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.read_len =
2078c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_len;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci		if (pm8001_ha->forensic_last_offset  >= length_to_read) {
2108c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_data +=
2118c2ecf20Sopenharmony_ci			sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
2128c2ecf20Sopenharmony_ci				"%08x ", 3);
2138c2ecf20Sopenharmony_ci			for (index = 0; index <
2148c2ecf20Sopenharmony_ci				(pm8001_ha->forensic_info.data_buf.direct_len
2158c2ecf20Sopenharmony_ci				 / 4); index++) {
2168c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data +=
2178c2ecf20Sopenharmony_ci				sprintf(
2188c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data,
2198c2ecf20Sopenharmony_ci				"%08x ", *(temp + index));
2208c2ecf20Sopenharmony_ci			}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci			pm8001_ha->fatal_bar_loc = 0;
2238c2ecf20Sopenharmony_ci			pm8001_ha->forensic_fatal_step = 1;
2248c2ecf20Sopenharmony_ci			pm8001_ha->fatal_forensic_shift_offset = 0;
2258c2ecf20Sopenharmony_ci			pm8001_ha->forensic_last_offset	= 0;
2268c2ecf20Sopenharmony_ci			status = 0;
2278c2ecf20Sopenharmony_ci			offset = (int)
2288c2ecf20Sopenharmony_ci			((char *)pm8001_ha->forensic_info.data_buf.direct_data
2298c2ecf20Sopenharmony_ci			- (char *)buf);
2308c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, IO,
2318c2ecf20Sopenharmony_ci				   "get_fatal_spcv:return1 0x%x\n", offset);
2328c2ecf20Sopenharmony_ci			return (char *)pm8001_ha->
2338c2ecf20Sopenharmony_ci				forensic_info.data_buf.direct_data -
2348c2ecf20Sopenharmony_ci				(char *)buf;
2358c2ecf20Sopenharmony_ci		}
2368c2ecf20Sopenharmony_ci		if (pm8001_ha->fatal_bar_loc < (64 * 1024)) {
2378c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_data +=
2388c2ecf20Sopenharmony_ci				sprintf(pm8001_ha->
2398c2ecf20Sopenharmony_ci					forensic_info.data_buf.direct_data,
2408c2ecf20Sopenharmony_ci					"%08x ", 2);
2418c2ecf20Sopenharmony_ci			for (index = 0; index <
2428c2ecf20Sopenharmony_ci				(pm8001_ha->forensic_info.data_buf.direct_len
2438c2ecf20Sopenharmony_ci				 / 4); index++) {
2448c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data
2458c2ecf20Sopenharmony_ci					+= sprintf(pm8001_ha->
2468c2ecf20Sopenharmony_ci					forensic_info.data_buf.direct_data,
2478c2ecf20Sopenharmony_ci					"%08x ", *(temp + index));
2488c2ecf20Sopenharmony_ci			}
2498c2ecf20Sopenharmony_ci			status = 0;
2508c2ecf20Sopenharmony_ci			offset = (int)
2518c2ecf20Sopenharmony_ci			((char *)pm8001_ha->forensic_info.data_buf.direct_data
2528c2ecf20Sopenharmony_ci			- (char *)buf);
2538c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, IO,
2548c2ecf20Sopenharmony_ci				   "get_fatal_spcv:return2 0x%x\n", offset);
2558c2ecf20Sopenharmony_ci			return (char *)pm8001_ha->
2568c2ecf20Sopenharmony_ci				forensic_info.data_buf.direct_data -
2578c2ecf20Sopenharmony_ci				(char *)buf;
2588c2ecf20Sopenharmony_ci		}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci		/* Increment the MEMBASE II Shifting Register value by 0x100.*/
2618c2ecf20Sopenharmony_ci		pm8001_ha->forensic_info.data_buf.direct_data +=
2628c2ecf20Sopenharmony_ci			sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
2638c2ecf20Sopenharmony_ci				"%08x ", 2);
2648c2ecf20Sopenharmony_ci		for (index = 0; index <
2658c2ecf20Sopenharmony_ci			(pm8001_ha->forensic_info.data_buf.direct_len
2668c2ecf20Sopenharmony_ci			 / 4) ; index++) {
2678c2ecf20Sopenharmony_ci			pm8001_ha->forensic_info.data_buf.direct_data +=
2688c2ecf20Sopenharmony_ci				sprintf(pm8001_ha->
2698c2ecf20Sopenharmony_ci				forensic_info.data_buf.direct_data,
2708c2ecf20Sopenharmony_ci				"%08x ", *(temp + index));
2718c2ecf20Sopenharmony_ci		}
2728c2ecf20Sopenharmony_ci		pm8001_ha->fatal_forensic_shift_offset += 0x100;
2738c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
2748c2ecf20Sopenharmony_ci			pm8001_ha->fatal_forensic_shift_offset);
2758c2ecf20Sopenharmony_ci		pm8001_ha->fatal_bar_loc = 0;
2768c2ecf20Sopenharmony_ci		status = 0;
2778c2ecf20Sopenharmony_ci		offset = (int)
2788c2ecf20Sopenharmony_ci			((char *)pm8001_ha->forensic_info.data_buf.direct_data
2798c2ecf20Sopenharmony_ci			- (char *)buf);
2808c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return3 0x%x\n",
2818c2ecf20Sopenharmony_ci			   offset);
2828c2ecf20Sopenharmony_ci		return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
2838c2ecf20Sopenharmony_ci			(char *)buf;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci	if (pm8001_ha->forensic_fatal_step == 1) {
2868c2ecf20Sopenharmony_ci		/* store previous accumulated length before triggering next
2878c2ecf20Sopenharmony_ci		 * accumulated length update
2888c2ecf20Sopenharmony_ci		 */
2898c2ecf20Sopenharmony_ci		pm8001_ha->forensic_preserved_accumulated_transfer =
2908c2ecf20Sopenharmony_ci			pm8001_mr32(fatal_table_address,
2918c2ecf20Sopenharmony_ci			MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci		/* continue capturing the fatal log until Dump status is 0x3 */
2948c2ecf20Sopenharmony_ci		if (pm8001_mr32(fatal_table_address,
2958c2ecf20Sopenharmony_ci			MPI_FATAL_EDUMP_TABLE_STATUS) <
2968c2ecf20Sopenharmony_ci			MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci			/* reset fddstat bit by writing to zero*/
2998c2ecf20Sopenharmony_ci			pm8001_mw32(fatal_table_address,
3008c2ecf20Sopenharmony_ci					MPI_FATAL_EDUMP_TABLE_STATUS, 0x0);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci			/* set dump control value to '1' so that new data will
3038c2ecf20Sopenharmony_ci			 * be transferred to shared memory
3048c2ecf20Sopenharmony_ci			 */
3058c2ecf20Sopenharmony_ci			pm8001_mw32(fatal_table_address,
3068c2ecf20Sopenharmony_ci				MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
3078c2ecf20Sopenharmony_ci				MPI_FATAL_EDUMP_HANDSHAKE_RDY);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci			/*Poll FDDHSHK  until clear */
3108c2ecf20Sopenharmony_ci			start = jiffies + (2 * HZ); /* 2 sec */
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci			do {
3138c2ecf20Sopenharmony_ci				reg_val = pm8001_mr32(fatal_table_address,
3148c2ecf20Sopenharmony_ci					MPI_FATAL_EDUMP_TABLE_HANDSHAKE);
3158c2ecf20Sopenharmony_ci			} while ((reg_val) && time_before(jiffies, start));
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci			if (reg_val != 0) {
3188c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
3198c2ecf20Sopenharmony_ci					   "TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n",
3208c2ecf20Sopenharmony_ci					   reg_val);
3218c2ecf20Sopenharmony_ci			       /* Fail the dump if a timeout occurs */
3228c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data +=
3238c2ecf20Sopenharmony_ci				sprintf(
3248c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data,
3258c2ecf20Sopenharmony_ci				"%08x ", 0xFFFFFFFF);
3268c2ecf20Sopenharmony_ci				return((char *)
3278c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data
3288c2ecf20Sopenharmony_ci				- (char *)buf);
3298c2ecf20Sopenharmony_ci			}
3308c2ecf20Sopenharmony_ci			/* Poll status register until set to 2 or
3318c2ecf20Sopenharmony_ci			 * 3 for up to 2 seconds
3328c2ecf20Sopenharmony_ci			 */
3338c2ecf20Sopenharmony_ci			start = jiffies + (2 * HZ); /* 2 sec */
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci			do {
3368c2ecf20Sopenharmony_ci				reg_val = pm8001_mr32(fatal_table_address,
3378c2ecf20Sopenharmony_ci					MPI_FATAL_EDUMP_TABLE_STATUS);
3388c2ecf20Sopenharmony_ci			} while (((reg_val != 2) && (reg_val != 3)) &&
3398c2ecf20Sopenharmony_ci					time_before(jiffies, start));
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci			if (reg_val < 2) {
3428c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
3438c2ecf20Sopenharmony_ci					   "TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n",
3448c2ecf20Sopenharmony_ci					   reg_val);
3458c2ecf20Sopenharmony_ci				/* Fail the dump if a timeout occurs */
3468c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data +=
3478c2ecf20Sopenharmony_ci				sprintf(
3488c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data,
3498c2ecf20Sopenharmony_ci				"%08x ", 0xFFFFFFFF);
3508c2ecf20Sopenharmony_ci				pm8001_cw32(pm8001_ha, 0,
3518c2ecf20Sopenharmony_ci					MEMBASE_II_SHIFT_REGISTER,
3528c2ecf20Sopenharmony_ci					pm8001_ha->fatal_forensic_shift_offset);
3538c2ecf20Sopenharmony_ci			}
3548c2ecf20Sopenharmony_ci			/* Read the next block of the debug data.*/
3558c2ecf20Sopenharmony_ci			length_to_read = pm8001_mr32(fatal_table_address,
3568c2ecf20Sopenharmony_ci			MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) -
3578c2ecf20Sopenharmony_ci			pm8001_ha->forensic_preserved_accumulated_transfer;
3588c2ecf20Sopenharmony_ci			if (length_to_read != 0x0) {
3598c2ecf20Sopenharmony_ci				pm8001_ha->forensic_fatal_step = 0;
3608c2ecf20Sopenharmony_ci				goto moreData;
3618c2ecf20Sopenharmony_ci			} else {
3628c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data +=
3638c2ecf20Sopenharmony_ci				sprintf(
3648c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_data,
3658c2ecf20Sopenharmony_ci				"%08x ", 4);
3668c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.read_len
3678c2ecf20Sopenharmony_ci								= 0xFFFFFFFF;
3688c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_len
3698c2ecf20Sopenharmony_ci								=  0;
3708c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.direct_offset
3718c2ecf20Sopenharmony_ci								= 0;
3728c2ecf20Sopenharmony_ci				pm8001_ha->forensic_info.data_buf.read_len = 0;
3738c2ecf20Sopenharmony_ci			}
3748c2ecf20Sopenharmony_ci		}
3758c2ecf20Sopenharmony_ci	}
3768c2ecf20Sopenharmony_ci	offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data
3778c2ecf20Sopenharmony_ci			- (char *)buf);
3788c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return4 0x%x\n", offset);
3798c2ecf20Sopenharmony_ci	return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
3808c2ecf20Sopenharmony_ci		(char *)buf;
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci/* pm80xx_get_non_fatal_dump - dump the nonfatal data from the dma
3848c2ecf20Sopenharmony_ci * location by the firmware.
3858c2ecf20Sopenharmony_ci */
3868c2ecf20Sopenharmony_cissize_t pm80xx_get_non_fatal_dump(struct device *cdev,
3878c2ecf20Sopenharmony_ci	struct device_attribute *attr, char *buf)
3888c2ecf20Sopenharmony_ci{
3898c2ecf20Sopenharmony_ci	struct Scsi_Host *shost = class_to_shost(cdev);
3908c2ecf20Sopenharmony_ci	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
3918c2ecf20Sopenharmony_ci	struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
3928c2ecf20Sopenharmony_ci	void __iomem *nonfatal_table_address = pm8001_ha->fatal_tbl_addr;
3938c2ecf20Sopenharmony_ci	u32 accum_len = 0;
3948c2ecf20Sopenharmony_ci	u32 total_len = 0;
3958c2ecf20Sopenharmony_ci	u32 reg_val = 0;
3968c2ecf20Sopenharmony_ci	u32 *temp = NULL;
3978c2ecf20Sopenharmony_ci	u32 index = 0;
3988c2ecf20Sopenharmony_ci	u32 output_length;
3998c2ecf20Sopenharmony_ci	unsigned long start = 0;
4008c2ecf20Sopenharmony_ci	char *buf_copy = buf;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
4038c2ecf20Sopenharmony_ci	if (++pm8001_ha->non_fatal_count == 1) {
4048c2ecf20Sopenharmony_ci		if (pm8001_ha->chip_id == chip_8001) {
4058c2ecf20Sopenharmony_ci			snprintf(pm8001_ha->forensic_info.data_buf.direct_data,
4068c2ecf20Sopenharmony_ci				PAGE_SIZE, "Not supported for SPC controller");
4078c2ecf20Sopenharmony_ci			return 0;
4088c2ecf20Sopenharmony_ci		}
4098c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "forensic_info TYPE_NON_FATAL...\n");
4108c2ecf20Sopenharmony_ci		/*
4118c2ecf20Sopenharmony_ci		 * Step 1: Write the host buffer parameters in the MPI Fatal and
4128c2ecf20Sopenharmony_ci		 * Non-Fatal Error Dump Capture Table.This is the buffer
4138c2ecf20Sopenharmony_ci		 * where debug data will be DMAed to.
4148c2ecf20Sopenharmony_ci		 */
4158c2ecf20Sopenharmony_ci		pm8001_mw32(nonfatal_table_address,
4168c2ecf20Sopenharmony_ci		MPI_FATAL_EDUMP_TABLE_LO_OFFSET,
4178c2ecf20Sopenharmony_ci		pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_lo);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci		pm8001_mw32(nonfatal_table_address,
4208c2ecf20Sopenharmony_ci		MPI_FATAL_EDUMP_TABLE_HI_OFFSET,
4218c2ecf20Sopenharmony_ci		pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_hi);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci		pm8001_mw32(nonfatal_table_address,
4248c2ecf20Sopenharmony_ci		MPI_FATAL_EDUMP_TABLE_LENGTH, SYSFS_OFFSET);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci		/* Optionally, set the DUMPCTRL bit to 1 if the host
4278c2ecf20Sopenharmony_ci		 * keeps sending active I/Os while capturing the non-fatal
4288c2ecf20Sopenharmony_ci		 * debug data. Otherwise, leave this bit set to zero
4298c2ecf20Sopenharmony_ci		 */
4308c2ecf20Sopenharmony_ci		pm8001_mw32(nonfatal_table_address,
4318c2ecf20Sopenharmony_ci		MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci		/*
4348c2ecf20Sopenharmony_ci		 * Step 2: Clear Accumulative Length of Debug Data Transferred
4358c2ecf20Sopenharmony_ci		 * [ACCDDLEN] field in the MPI Fatal and Non-Fatal Error Dump
4368c2ecf20Sopenharmony_ci		 * Capture Table to zero.
4378c2ecf20Sopenharmony_ci		 */
4388c2ecf20Sopenharmony_ci		pm8001_mw32(nonfatal_table_address,
4398c2ecf20Sopenharmony_ci				MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, 0);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci		/* initiallize previous accumulated length to 0 */
4428c2ecf20Sopenharmony_ci		pm8001_ha->forensic_preserved_accumulated_transfer = 0;
4438c2ecf20Sopenharmony_ci		pm8001_ha->non_fatal_read_length = 0;
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	total_len = pm8001_mr32(nonfatal_table_address,
4478c2ecf20Sopenharmony_ci			MPI_FATAL_EDUMP_TABLE_TOTAL_LEN);
4488c2ecf20Sopenharmony_ci	/*
4498c2ecf20Sopenharmony_ci	 * Step 3:Clear Fatal/Non-Fatal Debug Data Transfer Status [FDDTSTAT]
4508c2ecf20Sopenharmony_ci	 * field and then request that the SPCv controller transfer the debug
4518c2ecf20Sopenharmony_ci	 * data by setting bit 7 of the Inbound Doorbell Set Register.
4528c2ecf20Sopenharmony_ci	 */
4538c2ecf20Sopenharmony_ci	pm8001_mw32(nonfatal_table_address, MPI_FATAL_EDUMP_TABLE_STATUS, 0);
4548c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET,
4558c2ecf20Sopenharmony_ci			SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP);
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/*
4588c2ecf20Sopenharmony_ci	 * Step 4.1: Read back the Inbound Doorbell Set Register (by polling for
4598c2ecf20Sopenharmony_ci	 * 2 seconds) until register bit 7 is cleared.
4608c2ecf20Sopenharmony_ci	 * This step only indicates the request is accepted by the controller.
4618c2ecf20Sopenharmony_ci	 */
4628c2ecf20Sopenharmony_ci	start = jiffies + (2 * HZ); /* 2 sec */
4638c2ecf20Sopenharmony_ci	do {
4648c2ecf20Sopenharmony_ci		reg_val = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET) &
4658c2ecf20Sopenharmony_ci			SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP;
4668c2ecf20Sopenharmony_ci	} while ((reg_val != 0) && time_before(jiffies, start));
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	/* Step 4.2: To check the completion of the transfer, poll the Fatal/Non
4698c2ecf20Sopenharmony_ci	 * Fatal Debug Data Transfer Status [FDDTSTAT] field for 2 seconds in
4708c2ecf20Sopenharmony_ci	 * the MPI Fatal and Non-Fatal Error Dump Capture Table.
4718c2ecf20Sopenharmony_ci	 */
4728c2ecf20Sopenharmony_ci	start = jiffies + (2 * HZ); /* 2 sec */
4738c2ecf20Sopenharmony_ci	do {
4748c2ecf20Sopenharmony_ci		reg_val = pm8001_mr32(nonfatal_table_address,
4758c2ecf20Sopenharmony_ci				MPI_FATAL_EDUMP_TABLE_STATUS);
4768c2ecf20Sopenharmony_ci	} while ((!reg_val) && time_before(jiffies, start));
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	if ((reg_val == 0x00) ||
4798c2ecf20Sopenharmony_ci		(reg_val == MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED) ||
4808c2ecf20Sopenharmony_ci		(reg_val > MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE)) {
4818c2ecf20Sopenharmony_ci		pm8001_ha->non_fatal_read_length = 0;
4828c2ecf20Sopenharmony_ci		buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 0xFFFFFFFF);
4838c2ecf20Sopenharmony_ci		pm8001_ha->non_fatal_count = 0;
4848c2ecf20Sopenharmony_ci		return (buf_copy - buf);
4858c2ecf20Sopenharmony_ci	} else if (reg_val ==
4868c2ecf20Sopenharmony_ci			MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA) {
4878c2ecf20Sopenharmony_ci		buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 2);
4888c2ecf20Sopenharmony_ci	} else if ((reg_val == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) ||
4898c2ecf20Sopenharmony_ci		(pm8001_ha->non_fatal_read_length >= total_len)) {
4908c2ecf20Sopenharmony_ci		pm8001_ha->non_fatal_read_length = 0;
4918c2ecf20Sopenharmony_ci		buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 4);
4928c2ecf20Sopenharmony_ci		pm8001_ha->non_fatal_count = 0;
4938c2ecf20Sopenharmony_ci	}
4948c2ecf20Sopenharmony_ci	accum_len = pm8001_mr32(nonfatal_table_address,
4958c2ecf20Sopenharmony_ci			MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
4968c2ecf20Sopenharmony_ci	output_length = accum_len -
4978c2ecf20Sopenharmony_ci		pm8001_ha->forensic_preserved_accumulated_transfer;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	for (index = 0; index < output_length/4; index++)
5008c2ecf20Sopenharmony_ci		buf_copy += snprintf(buf_copy, PAGE_SIZE,
5018c2ecf20Sopenharmony_ci				"%08x ", *(temp+index));
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	pm8001_ha->non_fatal_read_length += output_length;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/* store current accumulated length to use in next iteration as
5068c2ecf20Sopenharmony_ci	 * the previous accumulated length
5078c2ecf20Sopenharmony_ci	 */
5088c2ecf20Sopenharmony_ci	pm8001_ha->forensic_preserved_accumulated_transfer = accum_len;
5098c2ecf20Sopenharmony_ci	return (buf_copy - buf);
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci/**
5138c2ecf20Sopenharmony_ci * read_main_config_table - read the configure table and save it.
5148c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
5158c2ecf20Sopenharmony_ci */
5168c2ecf20Sopenharmony_cistatic void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature	=
5218c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_SIGNATURE_OFFSET);
5228c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev =
5238c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_INTERFACE_REVISION);
5248c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev	=
5258c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_FW_REVISION);
5268c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io	=
5278c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_MAX_OUTSTANDING_IO_OFFSET);
5288c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl	=
5298c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_MAX_SGL_OFFSET);
5308c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag =
5318c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_CNTRL_CAP_OFFSET);
5328c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset	=
5338c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_GST_OFFSET);
5348c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset =
5358c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_IBQ_OFFSET);
5368c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset =
5378c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_OBQ_OFFSET);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	/* read Error Dump Offset and Length */
5408c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset0 =
5418c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET);
5428c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length0 =
5438c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH);
5448c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset1 =
5458c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET);
5468c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length1 =
5478c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/* read GPIO LED settings from the configuration table */
5508c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping =
5518c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	/* read analog Setting offset from the configuration table */
5548c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.analog_setup_table_offset =
5558c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset =
5588c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_INT_VECTOR_TABLE_OFFSET);
5598c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset =
5608c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_SAS_PHY_ATTR_TABLE_OFFSET);
5618c2ecf20Sopenharmony_ci	/* read port recover and reset timeout */
5628c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer =
5638c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER);
5648c2ecf20Sopenharmony_ci	/* read ILA and inactive firmware version */
5658c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version =
5668c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
5678c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
5688c2ecf20Sopenharmony_ci		pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
5718c2ecf20Sopenharmony_ci		   "Main cfg table: sign:%x interface rev:%x fw_rev:%x\n",
5728c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature,
5738c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev,
5748c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev);
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
5778c2ecf20Sopenharmony_ci		   "table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n",
5788c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset,
5798c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset,
5808c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset,
5818c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset,
5828c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
5858c2ecf20Sopenharmony_ci		   "Main cfg table; ila rev:%x Inactive fw rev:%x\n",
5868c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version,
5878c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version);
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci/**
5918c2ecf20Sopenharmony_ci * read_general_status_table - read the general status table and save it.
5928c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
5938c2ecf20Sopenharmony_ci */
5948c2ecf20Sopenharmony_cistatic void read_general_status_table(struct pm8001_hba_info *pm8001_ha)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->general_stat_tbl_addr;
5978c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.gst_len_mpistate	=
5988c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_GSTLEN_MPIS_OFFSET);
5998c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state0	=
6008c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_IQ_FREEZE_STATE0_OFFSET);
6018c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state1	=
6028c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_IQ_FREEZE_STATE1_OFFSET);
6038c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.msgu_tcnt		=
6048c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_MSGUTCNT_OFFSET);
6058c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.iop_tcnt		=
6068c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_IOPTCNT_OFFSET);
6078c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.gpio_input_val	=
6088c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_GPIO_INPUT_VAL);
6098c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[0] =
6108c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_RERRINFO_OFFSET0);
6118c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[1] =
6128c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_RERRINFO_OFFSET1);
6138c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[2] =
6148c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_RERRINFO_OFFSET2);
6158c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[3] =
6168c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_RERRINFO_OFFSET3);
6178c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[4] =
6188c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_RERRINFO_OFFSET4);
6198c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[5] =
6208c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_RERRINFO_OFFSET5);
6218c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[6] =
6228c2ecf20Sopenharmony_ci			pm8001_mr32(address, GST_RERRINFO_OFFSET6);
6238c2ecf20Sopenharmony_ci	pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[7] =
6248c2ecf20Sopenharmony_ci			 pm8001_mr32(address, GST_RERRINFO_OFFSET7);
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ci/**
6278c2ecf20Sopenharmony_ci * read_phy_attr_table - read the phy attribute table and save it.
6288c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
6298c2ecf20Sopenharmony_ci */
6308c2ecf20Sopenharmony_cistatic void read_phy_attr_table(struct pm8001_hba_info *pm8001_ha)
6318c2ecf20Sopenharmony_ci{
6328c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->pspa_q_tbl_addr;
6338c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[0] =
6348c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE0_OFFSET);
6358c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[1] =
6368c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE1_OFFSET);
6378c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[2] =
6388c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE2_OFFSET);
6398c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[3] =
6408c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE3_OFFSET);
6418c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[4] =
6428c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE4_OFFSET);
6438c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[5] =
6448c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE5_OFFSET);
6458c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[6] =
6468c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE6_OFFSET);
6478c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[7] =
6488c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE7_OFFSET);
6498c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[8] =
6508c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE8_OFFSET);
6518c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[9] =
6528c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE9_OFFSET);
6538c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[10] =
6548c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE10_OFFSET);
6558c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[11] =
6568c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE11_OFFSET);
6578c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[12] =
6588c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE12_OFFSET);
6598c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[13] =
6608c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE13_OFFSET);
6618c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[14] =
6628c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE14_OFFSET);
6638c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.phystart1_16[15] =
6648c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_PHYSTATE15_OFFSET);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[0] =
6678c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID0_OFFSET);
6688c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[1] =
6698c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID1_OFFSET);
6708c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[2] =
6718c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID2_OFFSET);
6728c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[3] =
6738c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID3_OFFSET);
6748c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[4] =
6758c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID4_OFFSET);
6768c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[5] =
6778c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID5_OFFSET);
6788c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[6] =
6798c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID6_OFFSET);
6808c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[7] =
6818c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID7_OFFSET);
6828c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[8] =
6838c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID8_OFFSET);
6848c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[9] =
6858c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID9_OFFSET);
6868c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[10] =
6878c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID10_OFFSET);
6888c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[11] =
6898c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID11_OFFSET);
6908c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[12] =
6918c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID12_OFFSET);
6928c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[13] =
6938c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID13_OFFSET);
6948c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[14] =
6958c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID14_OFFSET);
6968c2ecf20Sopenharmony_ci	pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[15] =
6978c2ecf20Sopenharmony_ci			pm8001_mr32(address, PSPA_OB_HW_EVENT_PID15_OFFSET);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci/**
7028c2ecf20Sopenharmony_ci * read_inbnd_queue_table - read the inbound queue table and save it.
7038c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
7048c2ecf20Sopenharmony_ci */
7058c2ecf20Sopenharmony_cistatic void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
7068c2ecf20Sopenharmony_ci{
7078c2ecf20Sopenharmony_ci	int i;
7088c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
7098c2ecf20Sopenharmony_ci	for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
7108c2ecf20Sopenharmony_ci		u32 offset = i * 0x20;
7118c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
7128c2ecf20Sopenharmony_ci			get_pci_bar_index(pm8001_mr32(address,
7138c2ecf20Sopenharmony_ci				(offset + IB_PIPCI_BAR)));
7148c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].pi_offset =
7158c2ecf20Sopenharmony_ci			pm8001_mr32(address, (offset + IB_PIPCI_BAR_OFFSET));
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci/**
7208c2ecf20Sopenharmony_ci * read_outbnd_queue_table - read the outbound queue table and save it.
7218c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
7228c2ecf20Sopenharmony_ci */
7238c2ecf20Sopenharmony_cistatic void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	int i;
7268c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
7278c2ecf20Sopenharmony_ci	for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
7288c2ecf20Sopenharmony_ci		u32 offset = i * 0x24;
7298c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
7308c2ecf20Sopenharmony_ci			get_pci_bar_index(pm8001_mr32(address,
7318c2ecf20Sopenharmony_ci				(offset + OB_CIPCI_BAR)));
7328c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].ci_offset =
7338c2ecf20Sopenharmony_ci			pm8001_mr32(address, (offset + OB_CIPCI_BAR_OFFSET));
7348c2ecf20Sopenharmony_ci	}
7358c2ecf20Sopenharmony_ci}
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci/**
7388c2ecf20Sopenharmony_ci * init_default_table_values - init the default table.
7398c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
7408c2ecf20Sopenharmony_ci */
7418c2ecf20Sopenharmony_cistatic void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	int i;
7448c2ecf20Sopenharmony_ci	u32 offsetib, offsetob;
7458c2ecf20Sopenharmony_ci	void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
7468c2ecf20Sopenharmony_ci	void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
7478c2ecf20Sopenharmony_ci	u32 ib_offset = pm8001_ha->ib_offset;
7488c2ecf20Sopenharmony_ci	u32 ob_offset = pm8001_ha->ob_offset;
7498c2ecf20Sopenharmony_ci	u32 ci_offset = pm8001_ha->ci_offset;
7508c2ecf20Sopenharmony_ci	u32 pi_offset = pm8001_ha->pi_offset;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr		=
7538c2ecf20Sopenharmony_ci		pm8001_ha->memoryMap.region[AAP1].phys_addr_hi;
7548c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr		=
7558c2ecf20Sopenharmony_ci		pm8001_ha->memoryMap.region[AAP1].phys_addr_lo;
7568c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size		=
7578c2ecf20Sopenharmony_ci							PM8001_EVENT_LOG_SIZE;
7588c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity		= 0x01;
7598c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr	=
7608c2ecf20Sopenharmony_ci		pm8001_ha->memoryMap.region[IOP].phys_addr_hi;
7618c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr	=
7628c2ecf20Sopenharmony_ci		pm8001_ha->memoryMap.region[IOP].phys_addr_lo;
7638c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size		=
7648c2ecf20Sopenharmony_ci							PM8001_EVENT_LOG_SIZE;
7658c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity	= 0x01;
7668c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt		= 0x01;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	/* Enable higher IQs and OQs, 32 to 63, bit 16 */
7698c2ecf20Sopenharmony_ci	if (pm8001_ha->max_q_num > 32)
7708c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
7718c2ecf20Sopenharmony_ci							1 << 16;
7728c2ecf20Sopenharmony_ci	/* Disable end to end CRC checking */
7738c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	for (i = 0; i < pm8001_ha->max_q_num; i++) {
7768c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt	=
7778c2ecf20Sopenharmony_ci			PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
7788c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].upper_base_addr	=
7798c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi;
7808c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].lower_base_addr	=
7818c2ecf20Sopenharmony_ci		pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo;
7828c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].base_virt		=
7838c2ecf20Sopenharmony_ci		  (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr;
7848c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].total_length		=
7858c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ib_offset + i].total_len;
7868c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr	=
7878c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi;
7888c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr	=
7898c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo;
7908c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].ci_virt		=
7918c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr;
7928c2ecf20Sopenharmony_ci		offsetib = i * 0x20;
7938c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].pi_pci_bar		=
7948c2ecf20Sopenharmony_ci			get_pci_bar_index(pm8001_mr32(addressib,
7958c2ecf20Sopenharmony_ci				(offsetib + 0x14)));
7968c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].pi_offset		=
7978c2ecf20Sopenharmony_ci			pm8001_mr32(addressib, (offsetib + 0x18));
7988c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].producer_idx		= 0;
7998c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[i].consumer_index	= 0;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEV,
8028c2ecf20Sopenharmony_ci			   "IQ %d pi_bar 0x%x pi_offset 0x%x\n", i,
8038c2ecf20Sopenharmony_ci			   pm8001_ha->inbnd_q_tbl[i].pi_pci_bar,
8048c2ecf20Sopenharmony_ci			   pm8001_ha->inbnd_q_tbl[i].pi_offset);
8058c2ecf20Sopenharmony_ci	}
8068c2ecf20Sopenharmony_ci	for (i = 0; i < pm8001_ha->max_q_num; i++) {
8078c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].element_size_cnt	=
8088c2ecf20Sopenharmony_ci			PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
8098c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].upper_base_addr	=
8108c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi;
8118c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].lower_base_addr	=
8128c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo;
8138c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].base_virt		=
8148c2ecf20Sopenharmony_ci		  (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr;
8158c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].total_length		=
8168c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[ob_offset + i].total_len;
8178c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr	=
8188c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi;
8198c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr	=
8208c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo;
8218c2ecf20Sopenharmony_ci		/* interrupt vector based on oq */
8228c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24);
8238c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].pi_virt		=
8248c2ecf20Sopenharmony_ci			pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr;
8258c2ecf20Sopenharmony_ci		offsetob = i * 0x24;
8268c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].ci_pci_bar		=
8278c2ecf20Sopenharmony_ci			get_pci_bar_index(pm8001_mr32(addressob,
8288c2ecf20Sopenharmony_ci			offsetob + 0x14));
8298c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].ci_offset		=
8308c2ecf20Sopenharmony_ci			pm8001_mr32(addressob, (offsetob + 0x18));
8318c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].consumer_idx		= 0;
8328c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[i].producer_index	= 0;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEV,
8358c2ecf20Sopenharmony_ci			   "OQ %d ci_bar 0x%x ci_offset 0x%x\n", i,
8368c2ecf20Sopenharmony_ci			   pm8001_ha->outbnd_q_tbl[i].ci_pci_bar,
8378c2ecf20Sopenharmony_ci			   pm8001_ha->outbnd_q_tbl[i].ci_offset);
8388c2ecf20Sopenharmony_ci	}
8398c2ecf20Sopenharmony_ci}
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci/**
8428c2ecf20Sopenharmony_ci * update_main_config_table - update the main default table to the HBA.
8438c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
8448c2ecf20Sopenharmony_ci */
8458c2ecf20Sopenharmony_cistatic void update_main_config_table(struct pm8001_hba_info *pm8001_ha)
8468c2ecf20Sopenharmony_ci{
8478c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->main_cfg_tbl_addr;
8488c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_IQNPPD_HPPD_OFFSET,
8498c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_q_nppd_hppd);
8508c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_HI,
8518c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr);
8528c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_LO,
8538c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr);
8548c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_EVENT_LOG_BUFF_SIZE,
8558c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size);
8568c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_EVENT_LOG_OPTION,
8578c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity);
8588c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_HI,
8598c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr);
8608c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_LO,
8618c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr);
8628c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_PCS_EVENT_LOG_BUFF_SIZE,
8638c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);
8648c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,
8658c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
8668c2ecf20Sopenharmony_ci	/* Update Fatal error interrupt vector */
8678c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
8688c2ecf20Sopenharmony_ci					((pm8001_ha->max_q_num - 1) << 8);
8698c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
8708c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
8718c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
8728c2ecf20Sopenharmony_ci		   "Updated Fatal error interrupt vector 0x%x\n",
8738c2ecf20Sopenharmony_ci		   pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT));
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
8768c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	/* SPCv specific */
8798c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping &= 0xCFFFFFFF;
8808c2ecf20Sopenharmony_ci	/* Set GPIOLED to 0x2 for LED indicator */
8818c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000;
8828c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET,
8838c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping);
8848c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
8858c2ecf20Sopenharmony_ci		   "Programming DW 0x21 in main cfg table with 0x%x\n",
8868c2ecf20Sopenharmony_ci		   pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET));
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
8898c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
8908c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_INT_REASSERTION_DELAY,
8918c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.interrupt_reassertion_delay);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= 0xffff0000;
8948c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
8958c2ecf20Sopenharmony_ci							PORT_RECOVERY_TIMEOUT;
8968c2ecf20Sopenharmony_ci	if (pm8001_ha->chip_id == chip_8006) {
8978c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &=
8988c2ecf20Sopenharmony_ci					0x0000ffff;
8998c2ecf20Sopenharmony_ci		pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
9008c2ecf20Sopenharmony_ci					CHIP_8006_PORT_RECOVERY_TIMEOUT;
9018c2ecf20Sopenharmony_ci	}
9028c2ecf20Sopenharmony_ci	pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
9038c2ecf20Sopenharmony_ci			pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
9048c2ecf20Sopenharmony_ci}
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci/**
9078c2ecf20Sopenharmony_ci * update_inbnd_queue_table - update the inbound queue table to the HBA.
9088c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
9098c2ecf20Sopenharmony_ci * @number: entry in the queue
9108c2ecf20Sopenharmony_ci */
9118c2ecf20Sopenharmony_cistatic void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
9128c2ecf20Sopenharmony_ci					 int number)
9138c2ecf20Sopenharmony_ci{
9148c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
9158c2ecf20Sopenharmony_ci	u16 offset = number * 0x20;
9168c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + IB_PROPERITY_OFFSET,
9178c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt);
9188c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + IB_BASE_ADDR_HI_OFFSET,
9198c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[number].upper_base_addr);
9208c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + IB_BASE_ADDR_LO_OFFSET,
9218c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[number].lower_base_addr);
9228c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + IB_CI_BASE_ADDR_HI_OFFSET,
9238c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr);
9248c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET,
9258c2ecf20Sopenharmony_ci		pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
9288c2ecf20Sopenharmony_ci		   "IQ %d: Element pri size 0x%x\n",
9298c2ecf20Sopenharmony_ci		   number,
9308c2ecf20Sopenharmony_ci		   pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt);
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
9338c2ecf20Sopenharmony_ci		   "IQ upr base addr 0x%x IQ lwr base addr 0x%x\n",
9348c2ecf20Sopenharmony_ci		   pm8001_ha->inbnd_q_tbl[number].upper_base_addr,
9358c2ecf20Sopenharmony_ci		   pm8001_ha->inbnd_q_tbl[number].lower_base_addr);
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
9388c2ecf20Sopenharmony_ci		   "CI upper base addr 0x%x CI lower base addr 0x%x\n",
9398c2ecf20Sopenharmony_ci		   pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr,
9408c2ecf20Sopenharmony_ci		   pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
9418c2ecf20Sopenharmony_ci}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci/**
9448c2ecf20Sopenharmony_ci * update_outbnd_queue_table - update the outbound queue table to the HBA.
9458c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
9468c2ecf20Sopenharmony_ci * @number: entry in the queue
9478c2ecf20Sopenharmony_ci */
9488c2ecf20Sopenharmony_cistatic void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
9498c2ecf20Sopenharmony_ci						 int number)
9508c2ecf20Sopenharmony_ci{
9518c2ecf20Sopenharmony_ci	void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
9528c2ecf20Sopenharmony_ci	u16 offset = number * 0x24;
9538c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + OB_PROPERITY_OFFSET,
9548c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[number].element_size_cnt);
9558c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + OB_BASE_ADDR_HI_OFFSET,
9568c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[number].upper_base_addr);
9578c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + OB_BASE_ADDR_LO_OFFSET,
9588c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[number].lower_base_addr);
9598c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + OB_PI_BASE_ADDR_HI_OFFSET,
9608c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr);
9618c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + OB_PI_BASE_ADDR_LO_OFFSET,
9628c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
9638c2ecf20Sopenharmony_ci	pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET,
9648c2ecf20Sopenharmony_ci		pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay);
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
9678c2ecf20Sopenharmony_ci		   "OQ %d: Element pri size 0x%x\n",
9688c2ecf20Sopenharmony_ci		   number,
9698c2ecf20Sopenharmony_ci		   pm8001_ha->outbnd_q_tbl[number].element_size_cnt);
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
9728c2ecf20Sopenharmony_ci		   "OQ upr base addr 0x%x OQ lwr base addr 0x%x\n",
9738c2ecf20Sopenharmony_ci		   pm8001_ha->outbnd_q_tbl[number].upper_base_addr,
9748c2ecf20Sopenharmony_ci		   pm8001_ha->outbnd_q_tbl[number].lower_base_addr);
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
9778c2ecf20Sopenharmony_ci		   "PI upper base addr 0x%x PI lower base addr 0x%x\n",
9788c2ecf20Sopenharmony_ci		   pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr,
9798c2ecf20Sopenharmony_ci		   pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
9808c2ecf20Sopenharmony_ci}
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci/**
9838c2ecf20Sopenharmony_ci * mpi_init_check - check firmware initialization status.
9848c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
9858c2ecf20Sopenharmony_ci */
9868c2ecf20Sopenharmony_cistatic int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
9878c2ecf20Sopenharmony_ci{
9888c2ecf20Sopenharmony_ci	u32 max_wait_count;
9898c2ecf20Sopenharmony_ci	u32 value;
9908c2ecf20Sopenharmony_ci	u32 gst_len_mpistate;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	/* Write bit0=1 to Inbound DoorBell Register to tell the SPC FW the
9938c2ecf20Sopenharmony_ci	table is updated */
9948c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE);
9958c2ecf20Sopenharmony_ci	/* wait until Inbound DoorBell Clear Register toggled */
9968c2ecf20Sopenharmony_ci	if (IS_SPCV_12G(pm8001_ha->pdev)) {
9978c2ecf20Sopenharmony_ci		max_wait_count = SPCV_DOORBELL_CLEAR_TIMEOUT;
9988c2ecf20Sopenharmony_ci	} else {
9998c2ecf20Sopenharmony_ci		max_wait_count = SPC_DOORBELL_CLEAR_TIMEOUT;
10008c2ecf20Sopenharmony_ci	}
10018c2ecf20Sopenharmony_ci	do {
10028c2ecf20Sopenharmony_ci		udelay(1);
10038c2ecf20Sopenharmony_ci		value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);
10048c2ecf20Sopenharmony_ci		value &= SPCv_MSGU_CFG_TABLE_UPDATE;
10058c2ecf20Sopenharmony_ci	} while ((value != 0) && (--max_wait_count));
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	if (!max_wait_count) {
10088c2ecf20Sopenharmony_ci		/* additional check */
10098c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
10108c2ecf20Sopenharmony_ci			   "Inb doorbell clear not toggled[value:%x]\n",
10118c2ecf20Sopenharmony_ci			   value);
10128c2ecf20Sopenharmony_ci		return -EBUSY;
10138c2ecf20Sopenharmony_ci	}
10148c2ecf20Sopenharmony_ci	/* check the MPI-State for initialization upto 100ms*/
10158c2ecf20Sopenharmony_ci	max_wait_count = 100 * 1000;/* 100 msec */
10168c2ecf20Sopenharmony_ci	do {
10178c2ecf20Sopenharmony_ci		udelay(1);
10188c2ecf20Sopenharmony_ci		gst_len_mpistate =
10198c2ecf20Sopenharmony_ci			pm8001_mr32(pm8001_ha->general_stat_tbl_addr,
10208c2ecf20Sopenharmony_ci					GST_GSTLEN_MPIS_OFFSET);
10218c2ecf20Sopenharmony_ci	} while ((GST_MPI_STATE_INIT !=
10228c2ecf20Sopenharmony_ci		(gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count));
10238c2ecf20Sopenharmony_ci	if (!max_wait_count)
10248c2ecf20Sopenharmony_ci		return -EBUSY;
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	/* check MPI Initialization error */
10278c2ecf20Sopenharmony_ci	gst_len_mpistate = gst_len_mpistate >> 16;
10288c2ecf20Sopenharmony_ci	if (0x0000 != gst_len_mpistate)
10298c2ecf20Sopenharmony_ci		return -EBUSY;
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	/*
10328c2ecf20Sopenharmony_ci	 *  As per controller datasheet, after successful MPI
10338c2ecf20Sopenharmony_ci	 *  initialization minimum 500ms delay is required before
10348c2ecf20Sopenharmony_ci	 *  issuing commands.
10358c2ecf20Sopenharmony_ci	 */
10368c2ecf20Sopenharmony_ci	msleep(500);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	return 0;
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci/**
10428c2ecf20Sopenharmony_ci * check_fw_ready - The LLDD check if the FW is ready, if not, return error.
10438c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
10448c2ecf20Sopenharmony_ci */
10458c2ecf20Sopenharmony_cistatic int check_fw_ready(struct pm8001_hba_info *pm8001_ha)
10468c2ecf20Sopenharmony_ci{
10478c2ecf20Sopenharmony_ci	u32 value;
10488c2ecf20Sopenharmony_ci	u32 max_wait_count;
10498c2ecf20Sopenharmony_ci	u32 max_wait_time;
10508c2ecf20Sopenharmony_ci	int ret = 0;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	/* reset / PCIe ready */
10538c2ecf20Sopenharmony_ci	max_wait_time = max_wait_count = 100 * 1000;	/* 100 milli sec */
10548c2ecf20Sopenharmony_ci	do {
10558c2ecf20Sopenharmony_ci		udelay(1);
10568c2ecf20Sopenharmony_ci		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
10578c2ecf20Sopenharmony_ci	} while ((value == 0xFFFFFFFF) && (--max_wait_count));
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	/* check ila status */
10608c2ecf20Sopenharmony_ci	max_wait_time = max_wait_count = 1000 * 1000;	/* 1000 milli sec */
10618c2ecf20Sopenharmony_ci	do {
10628c2ecf20Sopenharmony_ci		udelay(1);
10638c2ecf20Sopenharmony_ci		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
10648c2ecf20Sopenharmony_ci	} while (((value & SCRATCH_PAD_ILA_READY) !=
10658c2ecf20Sopenharmony_ci			SCRATCH_PAD_ILA_READY) && (--max_wait_count));
10668c2ecf20Sopenharmony_ci	if (!max_wait_count)
10678c2ecf20Sopenharmony_ci		ret = -1;
10688c2ecf20Sopenharmony_ci	else {
10698c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
10708c2ecf20Sopenharmony_ci			   " ila ready status in %d millisec\n",
10718c2ecf20Sopenharmony_ci			   (max_wait_time - max_wait_count));
10728c2ecf20Sopenharmony_ci	}
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	/* check RAAE status */
10758c2ecf20Sopenharmony_ci	max_wait_time = max_wait_count = 1800 * 1000;	/* 1800 milli sec */
10768c2ecf20Sopenharmony_ci	do {
10778c2ecf20Sopenharmony_ci		udelay(1);
10788c2ecf20Sopenharmony_ci		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
10798c2ecf20Sopenharmony_ci	} while (((value & SCRATCH_PAD_RAAE_READY) !=
10808c2ecf20Sopenharmony_ci				SCRATCH_PAD_RAAE_READY) && (--max_wait_count));
10818c2ecf20Sopenharmony_ci	if (!max_wait_count)
10828c2ecf20Sopenharmony_ci		ret = -1;
10838c2ecf20Sopenharmony_ci	else {
10848c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
10858c2ecf20Sopenharmony_ci			   " raae ready status in %d millisec\n",
10868c2ecf20Sopenharmony_ci			   (max_wait_time - max_wait_count));
10878c2ecf20Sopenharmony_ci	}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	/* check iop0 status */
10908c2ecf20Sopenharmony_ci	max_wait_time = max_wait_count = 600 * 1000;	/* 600 milli sec */
10918c2ecf20Sopenharmony_ci	do {
10928c2ecf20Sopenharmony_ci		udelay(1);
10938c2ecf20Sopenharmony_ci		value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
10948c2ecf20Sopenharmony_ci	} while (((value & SCRATCH_PAD_IOP0_READY) != SCRATCH_PAD_IOP0_READY) &&
10958c2ecf20Sopenharmony_ci			(--max_wait_count));
10968c2ecf20Sopenharmony_ci	if (!max_wait_count)
10978c2ecf20Sopenharmony_ci		ret = -1;
10988c2ecf20Sopenharmony_ci	else {
10998c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
11008c2ecf20Sopenharmony_ci			   " iop0 ready status in %d millisec\n",
11018c2ecf20Sopenharmony_ci			   (max_wait_time - max_wait_count));
11028c2ecf20Sopenharmony_ci	}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	/* check iop1 status only for 16 port controllers */
11058c2ecf20Sopenharmony_ci	if ((pm8001_ha->chip_id != chip_8008) &&
11068c2ecf20Sopenharmony_ci			(pm8001_ha->chip_id != chip_8009)) {
11078c2ecf20Sopenharmony_ci		/* 200 milli sec */
11088c2ecf20Sopenharmony_ci		max_wait_time = max_wait_count = 200 * 1000;
11098c2ecf20Sopenharmony_ci		do {
11108c2ecf20Sopenharmony_ci			udelay(1);
11118c2ecf20Sopenharmony_ci			value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
11128c2ecf20Sopenharmony_ci		} while (((value & SCRATCH_PAD_IOP1_READY) !=
11138c2ecf20Sopenharmony_ci				SCRATCH_PAD_IOP1_READY) && (--max_wait_count));
11148c2ecf20Sopenharmony_ci		if (!max_wait_count)
11158c2ecf20Sopenharmony_ci			ret = -1;
11168c2ecf20Sopenharmony_ci		else {
11178c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, MSG,
11188c2ecf20Sopenharmony_ci				   "iop1 ready status in %d millisec\n",
11198c2ecf20Sopenharmony_ci				   (max_wait_time - max_wait_count));
11208c2ecf20Sopenharmony_ci		}
11218c2ecf20Sopenharmony_ci	}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	return ret;
11248c2ecf20Sopenharmony_ci}
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_cistatic void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha)
11278c2ecf20Sopenharmony_ci{
11288c2ecf20Sopenharmony_ci	void __iomem *base_addr;
11298c2ecf20Sopenharmony_ci	u32	value;
11308c2ecf20Sopenharmony_ci	u32	offset;
11318c2ecf20Sopenharmony_ci	u32	pcibar;
11328c2ecf20Sopenharmony_ci	u32	pcilogic;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
11358c2ecf20Sopenharmony_ci	offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV, "Scratchpad 0 Offset: 0x%x value 0x%x\n",
11388c2ecf20Sopenharmony_ci		   offset, value);
11398c2ecf20Sopenharmony_ci	pcilogic = (value & 0xFC000000) >> 26;
11408c2ecf20Sopenharmony_ci	pcibar = get_pci_bar_index(pcilogic);
11418c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 PCI BAR: %d\n", pcibar);
11428c2ecf20Sopenharmony_ci	pm8001_ha->main_cfg_tbl_addr = base_addr =
11438c2ecf20Sopenharmony_ci		pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
11448c2ecf20Sopenharmony_ci	pm8001_ha->general_stat_tbl_addr =
11458c2ecf20Sopenharmony_ci		base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x18) &
11468c2ecf20Sopenharmony_ci					0xFFFFFF);
11478c2ecf20Sopenharmony_ci	pm8001_ha->inbnd_q_tbl_addr =
11488c2ecf20Sopenharmony_ci		base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C) &
11498c2ecf20Sopenharmony_ci					0xFFFFFF);
11508c2ecf20Sopenharmony_ci	pm8001_ha->outbnd_q_tbl_addr =
11518c2ecf20Sopenharmony_ci		base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x20) &
11528c2ecf20Sopenharmony_ci					0xFFFFFF);
11538c2ecf20Sopenharmony_ci	pm8001_ha->ivt_tbl_addr =
11548c2ecf20Sopenharmony_ci		base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C) &
11558c2ecf20Sopenharmony_ci					0xFFFFFF);
11568c2ecf20Sopenharmony_ci	pm8001_ha->pspa_q_tbl_addr =
11578c2ecf20Sopenharmony_ci		base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) &
11588c2ecf20Sopenharmony_ci					0xFFFFFF);
11598c2ecf20Sopenharmony_ci	pm8001_ha->fatal_tbl_addr =
11608c2ecf20Sopenharmony_ci		base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) &
11618c2ecf20Sopenharmony_ci					0xFFFFFF);
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "GST OFFSET 0x%x\n",
11648c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, pcibar, offset + 0x18));
11658c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "INBND OFFSET 0x%x\n",
11668c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C));
11678c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "OBND OFFSET 0x%x\n",
11688c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, pcibar, offset + 0x20));
11698c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "IVT OFFSET 0x%x\n",
11708c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C));
11718c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "PSPA OFFSET 0x%x\n",
11728c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, pcibar, offset + 0x90));
11738c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "addr - main cfg %p general status %p\n",
11748c2ecf20Sopenharmony_ci		   pm8001_ha->main_cfg_tbl_addr,
11758c2ecf20Sopenharmony_ci		   pm8001_ha->general_stat_tbl_addr);
11768c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "addr - inbnd %p obnd %p\n",
11778c2ecf20Sopenharmony_ci		   pm8001_ha->inbnd_q_tbl_addr,
11788c2ecf20Sopenharmony_ci		   pm8001_ha->outbnd_q_tbl_addr);
11798c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "addr - pspa %p ivt %p\n",
11808c2ecf20Sopenharmony_ci		   pm8001_ha->pspa_q_tbl_addr,
11818c2ecf20Sopenharmony_ci		   pm8001_ha->ivt_tbl_addr);
11828c2ecf20Sopenharmony_ci}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci/**
11858c2ecf20Sopenharmony_ci * pm80xx_set_thermal_config - support the thermal configuration
11868c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
11878c2ecf20Sopenharmony_ci */
11888c2ecf20Sopenharmony_ciint
11898c2ecf20Sopenharmony_cipm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha)
11908c2ecf20Sopenharmony_ci{
11918c2ecf20Sopenharmony_ci	struct set_ctrl_cfg_req payload;
11928c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
11938c2ecf20Sopenharmony_ci	int rc;
11948c2ecf20Sopenharmony_ci	u32 tag;
11958c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;
11968c2ecf20Sopenharmony_ci	u32 page_code;
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
11998c2ecf20Sopenharmony_ci	rc = pm8001_tag_alloc(pm8001_ha, &tag);
12008c2ecf20Sopenharmony_ci	if (rc)
12018c2ecf20Sopenharmony_ci		return -1;
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
12048c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	if (IS_SPCV_12G(pm8001_ha->pdev))
12078c2ecf20Sopenharmony_ci		page_code = THERMAL_PAGE_CODE_7H;
12088c2ecf20Sopenharmony_ci	else
12098c2ecf20Sopenharmony_ci		page_code = THERMAL_PAGE_CODE_8H;
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	payload.cfg_pg[0] =
12128c2ecf20Sopenharmony_ci		cpu_to_le32((THERMAL_LOG_ENABLE << 9) |
12138c2ecf20Sopenharmony_ci			    (THERMAL_ENABLE << 8) | page_code);
12148c2ecf20Sopenharmony_ci	payload.cfg_pg[1] =
12158c2ecf20Sopenharmony_ci		cpu_to_le32((LTEMPHIL << 24) | (RTEMPHIL << 8));
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
12188c2ecf20Sopenharmony_ci		   "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
12198c2ecf20Sopenharmony_ci		   payload.cfg_pg[0], payload.cfg_pg[1]);
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
12228c2ecf20Sopenharmony_ci			sizeof(payload), 0);
12238c2ecf20Sopenharmony_ci	if (rc)
12248c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, tag);
12258c2ecf20Sopenharmony_ci	return rc;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci}
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci/**
12308c2ecf20Sopenharmony_ci* pm80xx_set_sas_protocol_timer_config - support the SAS Protocol
12318c2ecf20Sopenharmony_ci* Timer configuration page
12328c2ecf20Sopenharmony_ci* @pm8001_ha: our hba card information.
12338c2ecf20Sopenharmony_ci*/
12348c2ecf20Sopenharmony_cistatic int
12358c2ecf20Sopenharmony_cipm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha)
12368c2ecf20Sopenharmony_ci{
12378c2ecf20Sopenharmony_ci	struct set_ctrl_cfg_req payload;
12388c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
12398c2ecf20Sopenharmony_ci	SASProtocolTimerConfig_t SASConfigPage;
12408c2ecf20Sopenharmony_ci	int rc;
12418c2ecf20Sopenharmony_ci	u32 tag;
12428c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SET_CONTROLLER_CONFIG;
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(struct set_ctrl_cfg_req));
12458c2ecf20Sopenharmony_ci	memset(&SASConfigPage, 0, sizeof(SASProtocolTimerConfig_t));
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	rc = pm8001_tag_alloc(pm8001_ha, &tag);
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	if (rc)
12508c2ecf20Sopenharmony_ci		return -1;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
12538c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	SASConfigPage.pageCode = cpu_to_le32(SAS_PROTOCOL_TIMER_CONFIG_PAGE);
12568c2ecf20Sopenharmony_ci	SASConfigPage.MST_MSI = cpu_to_le32(3 << 15);
12578c2ecf20Sopenharmony_ci	SASConfigPage.STP_SSP_MCT_TMO =
12588c2ecf20Sopenharmony_ci		cpu_to_le32((STP_MCT_TMO << 16) | SSP_MCT_TMO);
12598c2ecf20Sopenharmony_ci	SASConfigPage.STP_FRM_TMO =
12608c2ecf20Sopenharmony_ci		cpu_to_le32((SAS_MAX_OPEN_TIME << 24) |
12618c2ecf20Sopenharmony_ci			    (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER);
12628c2ecf20Sopenharmony_ci	SASConfigPage.STP_IDLE_TMO = cpu_to_le32(STP_IDLE_TIME);
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	SASConfigPage.OPNRJT_RTRY_INTVL =
12658c2ecf20Sopenharmony_ci		cpu_to_le32((SAS_MFD << 16) | SAS_OPNRJT_RTRY_INTVL);
12668c2ecf20Sopenharmony_ci	SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO =
12678c2ecf20Sopenharmony_ci		cpu_to_le32((SAS_DOPNRJT_RTRY_TMO << 16) | SAS_COPNRJT_RTRY_TMO);
12688c2ecf20Sopenharmony_ci	SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR =
12698c2ecf20Sopenharmony_ci		cpu_to_le32((SAS_DOPNRJT_RTRY_THR << 16) | SAS_COPNRJT_RTRY_THR);
12708c2ecf20Sopenharmony_ci	SASConfigPage.MAX_AIP = cpu_to_le32(SAS_MAX_AIP);
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.pageCode 0x%08x\n",
12738c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.pageCode));
12748c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MST_MSI  0x%08x\n",
12758c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.MST_MSI));
12768c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_SSP_MCT_TMO  0x%08x\n",
12778c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.STP_SSP_MCT_TMO));
12788c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_FRM_TMO  0x%08x\n",
12798c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.STP_FRM_TMO));
12808c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_IDLE_TMO  0x%08x\n",
12818c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.STP_IDLE_TMO));
12828c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.OPNRJT_RTRY_INTVL  0x%08x\n",
12838c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.OPNRJT_RTRY_INTVL));
12848c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO  0x%08x\n",
12858c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO));
12868c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR  0x%08x\n",
12878c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR));
12888c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MAX_AIP  0x%08x\n",
12898c2ecf20Sopenharmony_ci		   le32_to_cpu(SASConfigPage.MAX_AIP));
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	memcpy(&payload.cfg_pg, &SASConfigPage,
12928c2ecf20Sopenharmony_ci			 sizeof(SASProtocolTimerConfig_t));
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
12958c2ecf20Sopenharmony_ci			sizeof(payload), 0);
12968c2ecf20Sopenharmony_ci	if (rc)
12978c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, tag);
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	return rc;
13008c2ecf20Sopenharmony_ci}
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci/**
13038c2ecf20Sopenharmony_ci * pm80xx_get_encrypt_info - Check for encryption
13048c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
13058c2ecf20Sopenharmony_ci */
13068c2ecf20Sopenharmony_cistatic int
13078c2ecf20Sopenharmony_cipm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha)
13088c2ecf20Sopenharmony_ci{
13098c2ecf20Sopenharmony_ci	u32 scratch3_value;
13108c2ecf20Sopenharmony_ci	int ret = -1;
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	/* Read encryption status from SCRATCH PAD 3 */
13138c2ecf20Sopenharmony_ci	scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
13168c2ecf20Sopenharmony_ci					SCRATCH_PAD3_ENC_READY) {
13178c2ecf20Sopenharmony_ci		if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
13188c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
13198c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13208c2ecf20Sopenharmony_ci						SCRATCH_PAD3_SMF_ENABLED)
13218c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
13228c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13238c2ecf20Sopenharmony_ci						SCRATCH_PAD3_SMA_ENABLED)
13248c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
13258c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13268c2ecf20Sopenharmony_ci						SCRATCH_PAD3_SMB_ENABLED)
13278c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
13288c2ecf20Sopenharmony_ci		pm8001_ha->encrypt_info.status = 0;
13298c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, INIT,
13308c2ecf20Sopenharmony_ci			   "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X.Cipher mode 0x%x Sec mode 0x%x status 0x%x\n",
13318c2ecf20Sopenharmony_ci			   scratch3_value,
13328c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.cipher_mode,
13338c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.sec_mode,
13348c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.status);
13358c2ecf20Sopenharmony_ci		ret = 0;
13368c2ecf20Sopenharmony_ci	} else if ((scratch3_value & SCRATCH_PAD3_ENC_READY) ==
13378c2ecf20Sopenharmony_ci					SCRATCH_PAD3_ENC_DISABLED) {
13388c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, INIT,
13398c2ecf20Sopenharmony_ci			   "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n",
13408c2ecf20Sopenharmony_ci			   scratch3_value);
13418c2ecf20Sopenharmony_ci		pm8001_ha->encrypt_info.status = 0xFFFFFFFF;
13428c2ecf20Sopenharmony_ci		pm8001_ha->encrypt_info.cipher_mode = 0;
13438c2ecf20Sopenharmony_ci		pm8001_ha->encrypt_info.sec_mode = 0;
13448c2ecf20Sopenharmony_ci		ret = 0;
13458c2ecf20Sopenharmony_ci	} else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
13468c2ecf20Sopenharmony_ci				SCRATCH_PAD3_ENC_DIS_ERR) {
13478c2ecf20Sopenharmony_ci		pm8001_ha->encrypt_info.status =
13488c2ecf20Sopenharmony_ci			(scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;
13498c2ecf20Sopenharmony_ci		if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
13508c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
13518c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13528c2ecf20Sopenharmony_ci					SCRATCH_PAD3_SMF_ENABLED)
13538c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
13548c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13558c2ecf20Sopenharmony_ci					SCRATCH_PAD3_SMA_ENABLED)
13568c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
13578c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13588c2ecf20Sopenharmony_ci					SCRATCH_PAD3_SMB_ENABLED)
13598c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
13608c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, INIT,
13618c2ecf20Sopenharmony_ci			   "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
13628c2ecf20Sopenharmony_ci			   scratch3_value,
13638c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.cipher_mode,
13648c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.sec_mode,
13658c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.status);
13668c2ecf20Sopenharmony_ci	} else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
13678c2ecf20Sopenharmony_ci				 SCRATCH_PAD3_ENC_ENA_ERR) {
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci		pm8001_ha->encrypt_info.status =
13708c2ecf20Sopenharmony_ci			(scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16;
13718c2ecf20Sopenharmony_ci		if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED)
13728c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS;
13738c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13748c2ecf20Sopenharmony_ci					SCRATCH_PAD3_SMF_ENABLED)
13758c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF;
13768c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13778c2ecf20Sopenharmony_ci					SCRATCH_PAD3_SMA_ENABLED)
13788c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA;
13798c2ecf20Sopenharmony_ci		if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
13808c2ecf20Sopenharmony_ci					SCRATCH_PAD3_SMB_ENABLED)
13818c2ecf20Sopenharmony_ci			pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, INIT,
13848c2ecf20Sopenharmony_ci			   "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
13858c2ecf20Sopenharmony_ci			   scratch3_value,
13868c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.cipher_mode,
13878c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.sec_mode,
13888c2ecf20Sopenharmony_ci			   pm8001_ha->encrypt_info.status);
13898c2ecf20Sopenharmony_ci	}
13908c2ecf20Sopenharmony_ci	return ret;
13918c2ecf20Sopenharmony_ci}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci/**
13948c2ecf20Sopenharmony_ci * pm80xx_encrypt_update - update flash with encryption informtion
13958c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
13968c2ecf20Sopenharmony_ci */
13978c2ecf20Sopenharmony_cistatic int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha)
13988c2ecf20Sopenharmony_ci{
13998c2ecf20Sopenharmony_ci	struct kek_mgmt_req payload;
14008c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
14018c2ecf20Sopenharmony_ci	int rc;
14028c2ecf20Sopenharmony_ci	u32 tag;
14038c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_KEK_MANAGEMENT;
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(struct kek_mgmt_req));
14068c2ecf20Sopenharmony_ci	rc = pm8001_tag_alloc(pm8001_ha, &tag);
14078c2ecf20Sopenharmony_ci	if (rc)
14088c2ecf20Sopenharmony_ci		return -1;
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
14118c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
14128c2ecf20Sopenharmony_ci	/* Currently only one key is used. New KEK index is 1.
14138c2ecf20Sopenharmony_ci	 * Current KEK index is 1. Store KEK to NVRAM is 1.
14148c2ecf20Sopenharmony_ci	 */
14158c2ecf20Sopenharmony_ci	payload.new_curidx_ksop =
14168c2ecf20Sopenharmony_ci		cpu_to_le32(((1 << 24) | (1 << 16) | (1 << 8) |
14178c2ecf20Sopenharmony_ci			     KEK_MGMT_SUBOP_KEYCARDUPDATE));
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
14208c2ecf20Sopenharmony_ci		   "Saving Encryption info to flash. payload 0x%x\n",
14218c2ecf20Sopenharmony_ci		   le32_to_cpu(payload.new_curidx_ksop));
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
14248c2ecf20Sopenharmony_ci			sizeof(payload), 0);
14258c2ecf20Sopenharmony_ci	if (rc)
14268c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, tag);
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci	return rc;
14298c2ecf20Sopenharmony_ci}
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci/**
14328c2ecf20Sopenharmony_ci * pm8001_chip_init - the main init function that initialize whole PM8001 chip.
14338c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
14348c2ecf20Sopenharmony_ci */
14358c2ecf20Sopenharmony_cistatic int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha)
14368c2ecf20Sopenharmony_ci{
14378c2ecf20Sopenharmony_ci	int ret;
14388c2ecf20Sopenharmony_ci	u8 i = 0;
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	/* check the firmware status */
14418c2ecf20Sopenharmony_ci	if (-1 == check_fw_ready(pm8001_ha)) {
14428c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n");
14438c2ecf20Sopenharmony_ci		return -EBUSY;
14448c2ecf20Sopenharmony_ci	}
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	/* Initialize the controller fatal error flag */
14478c2ecf20Sopenharmony_ci	pm8001_ha->controller_fatal_error = false;
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	/* Initialize pci space address eg: mpi offset */
14508c2ecf20Sopenharmony_ci	init_pci_device_addresses(pm8001_ha);
14518c2ecf20Sopenharmony_ci	init_default_table_values(pm8001_ha);
14528c2ecf20Sopenharmony_ci	read_main_config_table(pm8001_ha);
14538c2ecf20Sopenharmony_ci	read_general_status_table(pm8001_ha);
14548c2ecf20Sopenharmony_ci	read_inbnd_queue_table(pm8001_ha);
14558c2ecf20Sopenharmony_ci	read_outbnd_queue_table(pm8001_ha);
14568c2ecf20Sopenharmony_ci	read_phy_attr_table(pm8001_ha);
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	/* update main config table ,inbound table and outbound table */
14598c2ecf20Sopenharmony_ci	update_main_config_table(pm8001_ha);
14608c2ecf20Sopenharmony_ci	for (i = 0; i < pm8001_ha->max_q_num; i++) {
14618c2ecf20Sopenharmony_ci		update_inbnd_queue_table(pm8001_ha, i);
14628c2ecf20Sopenharmony_ci		update_outbnd_queue_table(pm8001_ha, i);
14638c2ecf20Sopenharmony_ci	}
14648c2ecf20Sopenharmony_ci	/* notify firmware update finished and check initialization status */
14658c2ecf20Sopenharmony_ci	if (0 == mpi_init_check(pm8001_ha)) {
14668c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, INIT, "MPI initialize successful!\n");
14678c2ecf20Sopenharmony_ci	} else
14688c2ecf20Sopenharmony_ci		return -EBUSY;
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	/* send SAS protocol timer configuration page to FW */
14718c2ecf20Sopenharmony_ci	ret = pm80xx_set_sas_protocol_timer_config(pm8001_ha);
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci	/* Check for encryption */
14748c2ecf20Sopenharmony_ci	if (pm8001_ha->chip->encrypt) {
14758c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, INIT, "Checking for encryption\n");
14768c2ecf20Sopenharmony_ci		ret = pm80xx_get_encrypt_info(pm8001_ha);
14778c2ecf20Sopenharmony_ci		if (ret == -1) {
14788c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, INIT, "Encryption error !!\n");
14798c2ecf20Sopenharmony_ci			if (pm8001_ha->encrypt_info.status == 0x81) {
14808c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, INIT,
14818c2ecf20Sopenharmony_ci					   "Encryption enabled with error.Saving encryption key to flash\n");
14828c2ecf20Sopenharmony_ci				pm80xx_encrypt_update(pm8001_ha);
14838c2ecf20Sopenharmony_ci			}
14848c2ecf20Sopenharmony_ci		}
14858c2ecf20Sopenharmony_ci	}
14868c2ecf20Sopenharmony_ci	return 0;
14878c2ecf20Sopenharmony_ci}
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_cistatic int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha)
14908c2ecf20Sopenharmony_ci{
14918c2ecf20Sopenharmony_ci	u32 max_wait_count;
14928c2ecf20Sopenharmony_ci	u32 value;
14938c2ecf20Sopenharmony_ci	u32 gst_len_mpistate;
14948c2ecf20Sopenharmony_ci	init_pci_device_addresses(pm8001_ha);
14958c2ecf20Sopenharmony_ci	/* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the
14968c2ecf20Sopenharmony_ci	table is stop */
14978c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	/* wait until Inbound DoorBell Clear Register toggled */
15008c2ecf20Sopenharmony_ci	if (IS_SPCV_12G(pm8001_ha->pdev)) {
15018c2ecf20Sopenharmony_ci		max_wait_count = 30 * 1000 * 1000; /* 30 sec */
15028c2ecf20Sopenharmony_ci	} else {
15038c2ecf20Sopenharmony_ci		max_wait_count = 15 * 1000 * 1000; /* 15 sec */
15048c2ecf20Sopenharmony_ci	}
15058c2ecf20Sopenharmony_ci	do {
15068c2ecf20Sopenharmony_ci		udelay(1);
15078c2ecf20Sopenharmony_ci		value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET);
15088c2ecf20Sopenharmony_ci		value &= SPCv_MSGU_CFG_TABLE_RESET;
15098c2ecf20Sopenharmony_ci	} while ((value != 0) && (--max_wait_count));
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	if (!max_wait_count) {
15128c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:IBDB value/=%x\n", value);
15138c2ecf20Sopenharmony_ci		return -1;
15148c2ecf20Sopenharmony_ci	}
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	/* check the MPI-State for termination in progress */
15178c2ecf20Sopenharmony_ci	/* wait until Inbound DoorBell Clear Register toggled */
15188c2ecf20Sopenharmony_ci	max_wait_count = 2 * 1000 * 1000;	/* 2 sec for spcv/ve */
15198c2ecf20Sopenharmony_ci	do {
15208c2ecf20Sopenharmony_ci		udelay(1);
15218c2ecf20Sopenharmony_ci		gst_len_mpistate =
15228c2ecf20Sopenharmony_ci			pm8001_mr32(pm8001_ha->general_stat_tbl_addr,
15238c2ecf20Sopenharmony_ci			GST_GSTLEN_MPIS_OFFSET);
15248c2ecf20Sopenharmony_ci		if (GST_MPI_STATE_UNINIT ==
15258c2ecf20Sopenharmony_ci			(gst_len_mpistate & GST_MPI_STATE_MASK))
15268c2ecf20Sopenharmony_ci			break;
15278c2ecf20Sopenharmony_ci	} while (--max_wait_count);
15288c2ecf20Sopenharmony_ci	if (!max_wait_count) {
15298c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, " TIME OUT MPI State = 0x%x\n",
15308c2ecf20Sopenharmony_ci			   gst_len_mpistate & GST_MPI_STATE_MASK);
15318c2ecf20Sopenharmony_ci		return -1;
15328c2ecf20Sopenharmony_ci	}
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	return 0;
15358c2ecf20Sopenharmony_ci}
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci/**
15388c2ecf20Sopenharmony_ci * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all
15398c2ecf20Sopenharmony_ci * the FW register status to the originated status.
15408c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
15418c2ecf20Sopenharmony_ci */
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_cistatic int
15448c2ecf20Sopenharmony_cipm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
15458c2ecf20Sopenharmony_ci{
15468c2ecf20Sopenharmony_ci	u32 regval;
15478c2ecf20Sopenharmony_ci	u32 bootloader_state;
15488c2ecf20Sopenharmony_ci	u32 ibutton0, ibutton1;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	/* Process MPI table uninitialization only if FW is ready */
15518c2ecf20Sopenharmony_ci	if (!pm8001_ha->controller_fatal_error) {
15528c2ecf20Sopenharmony_ci		/* Check if MPI is in ready state to reset */
15538c2ecf20Sopenharmony_ci		if (mpi_uninit_check(pm8001_ha) != 0) {
15548c2ecf20Sopenharmony_ci			u32 r0 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
15558c2ecf20Sopenharmony_ci			u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
15568c2ecf20Sopenharmony_ci			u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);
15578c2ecf20Sopenharmony_ci			u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
15588c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, FAIL,
15598c2ecf20Sopenharmony_ci				   "MPI state is not ready scratch: %x:%x:%x:%x\n",
15608c2ecf20Sopenharmony_ci				   r0, r1, r2, r3);
15618c2ecf20Sopenharmony_ci			/* if things aren't ready but the bootloader is ok then
15628c2ecf20Sopenharmony_ci			 * try the reset anyway.
15638c2ecf20Sopenharmony_ci			 */
15648c2ecf20Sopenharmony_ci			if (r1 & SCRATCH_PAD1_BOOTSTATE_MASK)
15658c2ecf20Sopenharmony_ci				return -1;
15668c2ecf20Sopenharmony_ci		}
15678c2ecf20Sopenharmony_ci	}
15688c2ecf20Sopenharmony_ci	/* checked for reset register normal state; 0x0 */
15698c2ecf20Sopenharmony_ci	regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
15708c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "reset register before write : 0x%x\n",
15718c2ecf20Sopenharmony_ci		   regval);
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE);
15748c2ecf20Sopenharmony_ci	msleep(500);
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
15778c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "reset register after write 0x%x\n",
15788c2ecf20Sopenharmony_ci		   regval);
15798c2ecf20Sopenharmony_ci
15808c2ecf20Sopenharmony_ci	if ((regval & SPCv_SOFT_RESET_READ_MASK) ==
15818c2ecf20Sopenharmony_ci			SPCv_SOFT_RESET_NORMAL_RESET_OCCURED) {
15828c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
15838c2ecf20Sopenharmony_ci			   " soft reset successful [regval: 0x%x]\n",
15848c2ecf20Sopenharmony_ci			   regval);
15858c2ecf20Sopenharmony_ci	} else {
15868c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
15878c2ecf20Sopenharmony_ci			   " soft reset failed [regval: 0x%x]\n",
15888c2ecf20Sopenharmony_ci			   regval);
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci		/* check bootloader is successfully executed or in HDA mode */
15918c2ecf20Sopenharmony_ci		bootloader_state =
15928c2ecf20Sopenharmony_ci			pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1) &
15938c2ecf20Sopenharmony_ci			SCRATCH_PAD1_BOOTSTATE_MASK;
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci		if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM) {
15968c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, MSG,
15978c2ecf20Sopenharmony_ci				   "Bootloader state - HDA mode SEEPROM\n");
15988c2ecf20Sopenharmony_ci		} else if (bootloader_state ==
15998c2ecf20Sopenharmony_ci				SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP) {
16008c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, MSG,
16018c2ecf20Sopenharmony_ci				   "Bootloader state - HDA mode Bootstrap Pin\n");
16028c2ecf20Sopenharmony_ci		} else if (bootloader_state ==
16038c2ecf20Sopenharmony_ci				SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET) {
16048c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, MSG,
16058c2ecf20Sopenharmony_ci				   "Bootloader state - HDA mode soft reset\n");
16068c2ecf20Sopenharmony_ci		} else if (bootloader_state ==
16078c2ecf20Sopenharmony_ci					SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR) {
16088c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, MSG,
16098c2ecf20Sopenharmony_ci				   "Bootloader state-HDA mode critical error\n");
16108c2ecf20Sopenharmony_ci		}
16118c2ecf20Sopenharmony_ci		return -EBUSY;
16128c2ecf20Sopenharmony_ci	}
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	/* check the firmware status after reset */
16158c2ecf20Sopenharmony_ci	if (-1 == check_fw_ready(pm8001_ha)) {
16168c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n");
16178c2ecf20Sopenharmony_ci		/* check iButton feature support for motherboard controller */
16188c2ecf20Sopenharmony_ci		if (pm8001_ha->pdev->subsystem_vendor !=
16198c2ecf20Sopenharmony_ci			PCI_VENDOR_ID_ADAPTEC2 &&
16208c2ecf20Sopenharmony_ci			pm8001_ha->pdev->subsystem_vendor !=
16218c2ecf20Sopenharmony_ci			PCI_VENDOR_ID_ATTO &&
16228c2ecf20Sopenharmony_ci			pm8001_ha->pdev->subsystem_vendor != 0) {
16238c2ecf20Sopenharmony_ci			ibutton0 = pm8001_cr32(pm8001_ha, 0,
16248c2ecf20Sopenharmony_ci					MSGU_HOST_SCRATCH_PAD_6);
16258c2ecf20Sopenharmony_ci			ibutton1 = pm8001_cr32(pm8001_ha, 0,
16268c2ecf20Sopenharmony_ci					MSGU_HOST_SCRATCH_PAD_7);
16278c2ecf20Sopenharmony_ci			if (!ibutton0 && !ibutton1) {
16288c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
16298c2ecf20Sopenharmony_ci					   "iButton Feature is not Available!!!\n");
16308c2ecf20Sopenharmony_ci				return -EBUSY;
16318c2ecf20Sopenharmony_ci			}
16328c2ecf20Sopenharmony_ci			if (ibutton0 == 0xdeadbeef && ibutton1 == 0xdeadbeef) {
16338c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
16348c2ecf20Sopenharmony_ci					   "CRC Check for iButton Feature Failed!!!\n");
16358c2ecf20Sopenharmony_ci				return -EBUSY;
16368c2ecf20Sopenharmony_ci			}
16378c2ecf20Sopenharmony_ci		}
16388c2ecf20Sopenharmony_ci	}
16398c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SPCv soft reset Complete\n");
16408c2ecf20Sopenharmony_ci	return 0;
16418c2ecf20Sopenharmony_ci}
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_cistatic void pm80xx_hw_chip_rst(struct pm8001_hba_info *pm8001_ha)
16448c2ecf20Sopenharmony_ci{
16458c2ecf20Sopenharmony_ci	u32 i;
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "chip reset start\n");
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	/* do SPCv chip reset. */
16508c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, 0x11);
16518c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "SPC soft reset Complete\n");
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci	/* Check this ..whether delay is required or no */
16548c2ecf20Sopenharmony_ci	/* delay 10 usec */
16558c2ecf20Sopenharmony_ci	udelay(10);
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	/* wait for 20 msec until the firmware gets reloaded */
16588c2ecf20Sopenharmony_ci	i = 20;
16598c2ecf20Sopenharmony_ci	do {
16608c2ecf20Sopenharmony_ci		mdelay(1);
16618c2ecf20Sopenharmony_ci	} while ((--i) != 0);
16628c2ecf20Sopenharmony_ci
16638c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "chip reset finished\n");
16648c2ecf20Sopenharmony_ci}
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci/**
16678c2ecf20Sopenharmony_ci * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
16688c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
16698c2ecf20Sopenharmony_ci */
16708c2ecf20Sopenharmony_cistatic void
16718c2ecf20Sopenharmony_cipm80xx_chip_intx_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
16728c2ecf20Sopenharmony_ci{
16738c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_CLEAR_ALL);
16748c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, MSGU_ODCR, ODCR_CLEAR_ALL);
16758c2ecf20Sopenharmony_ci}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci/**
16788c2ecf20Sopenharmony_ci * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt
16798c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
16808c2ecf20Sopenharmony_ci */
16818c2ecf20Sopenharmony_cistatic void
16828c2ecf20Sopenharmony_cipm80xx_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
16838c2ecf20Sopenharmony_ci{
16848c2ecf20Sopenharmony_ci	pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, ODMR_MASK_ALL);
16858c2ecf20Sopenharmony_ci}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci/**
16888c2ecf20Sopenharmony_ci * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
16898c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
16908c2ecf20Sopenharmony_ci * @vec: interrupt number to enable
16918c2ecf20Sopenharmony_ci */
16928c2ecf20Sopenharmony_cistatic void
16938c2ecf20Sopenharmony_cipm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
16948c2ecf20Sopenharmony_ci{
16958c2ecf20Sopenharmony_ci#ifdef PM8001_USE_MSIX
16968c2ecf20Sopenharmony_ci	if (vec < 32)
16978c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, 1U << vec);
16988c2ecf20Sopenharmony_ci	else
16998c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR_U,
17008c2ecf20Sopenharmony_ci			    1U << (vec - 32));
17018c2ecf20Sopenharmony_ci	return;
17028c2ecf20Sopenharmony_ci#endif
17038c2ecf20Sopenharmony_ci	pm80xx_chip_intx_interrupt_enable(pm8001_ha);
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci}
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci/**
17088c2ecf20Sopenharmony_ci * pm8001_chip_interrupt_disable- disable PM8001 chip interrupt
17098c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
17108c2ecf20Sopenharmony_ci * @vec: interrupt number to disable
17118c2ecf20Sopenharmony_ci */
17128c2ecf20Sopenharmony_cistatic void
17138c2ecf20Sopenharmony_cipm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
17148c2ecf20Sopenharmony_ci{
17158c2ecf20Sopenharmony_ci#ifdef PM8001_USE_MSIX
17168c2ecf20Sopenharmony_ci	if (vec == 0xFF) {
17178c2ecf20Sopenharmony_ci		/* disable all vectors 0-31, 32-63 */
17188c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 0xFFFFFFFF);
17198c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U, 0xFFFFFFFF);
17208c2ecf20Sopenharmony_ci	} else if (vec < 32)
17218c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 1U << vec);
17228c2ecf20Sopenharmony_ci	else
17238c2ecf20Sopenharmony_ci		pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U,
17248c2ecf20Sopenharmony_ci			    1U << (vec - 32));
17258c2ecf20Sopenharmony_ci	return;
17268c2ecf20Sopenharmony_ci#endif
17278c2ecf20Sopenharmony_ci	pm80xx_chip_intx_interrupt_disable(pm8001_ha);
17288c2ecf20Sopenharmony_ci}
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_cistatic void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha,
17318c2ecf20Sopenharmony_ci		struct pm8001_device *pm8001_ha_dev)
17328c2ecf20Sopenharmony_ci{
17338c2ecf20Sopenharmony_ci	int res;
17348c2ecf20Sopenharmony_ci	u32 ccb_tag;
17358c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
17368c2ecf20Sopenharmony_ci	struct sas_task *task = NULL;
17378c2ecf20Sopenharmony_ci	struct task_abort_req task_abort;
17388c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
17398c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SATA_ABORT;
17408c2ecf20Sopenharmony_ci	int ret;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci	if (!pm8001_ha_dev) {
17438c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "dev is null\n");
17448c2ecf20Sopenharmony_ci		return;
17458c2ecf20Sopenharmony_ci	}
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci	task = sas_alloc_slow_task(GFP_ATOMIC);
17488c2ecf20Sopenharmony_ci
17498c2ecf20Sopenharmony_ci	if (!task) {
17508c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");
17518c2ecf20Sopenharmony_ci		return;
17528c2ecf20Sopenharmony_ci	}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci	task->task_done = pm8001_task_done;
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
17578c2ecf20Sopenharmony_ci	if (res) {
17588c2ecf20Sopenharmony_ci		sas_free_task(task);
17598c2ecf20Sopenharmony_ci		return;
17608c2ecf20Sopenharmony_ci	}
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[ccb_tag];
17638c2ecf20Sopenharmony_ci	ccb->device = pm8001_ha_dev;
17648c2ecf20Sopenharmony_ci	ccb->ccb_tag = ccb_tag;
17658c2ecf20Sopenharmony_ci	ccb->task = task;
17668c2ecf20Sopenharmony_ci	ccb->n_elem = 0;
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci	memset(&task_abort, 0, sizeof(task_abort));
17718c2ecf20Sopenharmony_ci	task_abort.abort_all = cpu_to_le32(1);
17728c2ecf20Sopenharmony_ci	task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
17738c2ecf20Sopenharmony_ci	task_abort.tag = cpu_to_le32(ccb_tag);
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
17768c2ecf20Sopenharmony_ci			sizeof(task_abort), 0);
17778c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "Executing abort task end\n");
17788c2ecf20Sopenharmony_ci	if (ret) {
17798c2ecf20Sopenharmony_ci		sas_free_task(task);
17808c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, ccb_tag);
17818c2ecf20Sopenharmony_ci	}
17828c2ecf20Sopenharmony_ci}
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_cistatic void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha,
17858c2ecf20Sopenharmony_ci		struct pm8001_device *pm8001_ha_dev)
17868c2ecf20Sopenharmony_ci{
17878c2ecf20Sopenharmony_ci	struct sata_start_req sata_cmd;
17888c2ecf20Sopenharmony_ci	int res;
17898c2ecf20Sopenharmony_ci	u32 ccb_tag;
17908c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
17918c2ecf20Sopenharmony_ci	struct sas_task *task = NULL;
17928c2ecf20Sopenharmony_ci	struct host_to_dev_fis fis;
17938c2ecf20Sopenharmony_ci	struct domain_device *dev;
17948c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
17958c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SATA_HOST_OPSTART;
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	task = sas_alloc_slow_task(GFP_ATOMIC);
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci	if (!task) {
18008c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");
18018c2ecf20Sopenharmony_ci		return;
18028c2ecf20Sopenharmony_ci	}
18038c2ecf20Sopenharmony_ci	task->task_done = pm8001_task_done;
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
18068c2ecf20Sopenharmony_ci	if (res) {
18078c2ecf20Sopenharmony_ci		sas_free_task(task);
18088c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n");
18098c2ecf20Sopenharmony_ci		return;
18108c2ecf20Sopenharmony_ci	}
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci	/* allocate domain device by ourselves as libsas
18138c2ecf20Sopenharmony_ci	 * is not going to provide any
18148c2ecf20Sopenharmony_ci	*/
18158c2ecf20Sopenharmony_ci	dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
18168c2ecf20Sopenharmony_ci	if (!dev) {
18178c2ecf20Sopenharmony_ci		sas_free_task(task);
18188c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, ccb_tag);
18198c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
18208c2ecf20Sopenharmony_ci			   "Domain device cannot be allocated\n");
18218c2ecf20Sopenharmony_ci		return;
18228c2ecf20Sopenharmony_ci	}
18238c2ecf20Sopenharmony_ci
18248c2ecf20Sopenharmony_ci	task->dev = dev;
18258c2ecf20Sopenharmony_ci	task->dev->lldd_dev = pm8001_ha_dev;
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[ccb_tag];
18288c2ecf20Sopenharmony_ci	ccb->device = pm8001_ha_dev;
18298c2ecf20Sopenharmony_ci	ccb->ccb_tag = ccb_tag;
18308c2ecf20Sopenharmony_ci	ccb->task = task;
18318c2ecf20Sopenharmony_ci	ccb->n_elem = 0;
18328c2ecf20Sopenharmony_ci	pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
18338c2ecf20Sopenharmony_ci	pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	memset(&sata_cmd, 0, sizeof(sata_cmd));
18368c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	/* construct read log FIS */
18398c2ecf20Sopenharmony_ci	memset(&fis, 0, sizeof(struct host_to_dev_fis));
18408c2ecf20Sopenharmony_ci	fis.fis_type = 0x27;
18418c2ecf20Sopenharmony_ci	fis.flags = 0x80;
18428c2ecf20Sopenharmony_ci	fis.command = ATA_CMD_READ_LOG_EXT;
18438c2ecf20Sopenharmony_ci	fis.lbal = 0x10;
18448c2ecf20Sopenharmony_ci	fis.sector_count = 0x1;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci	sata_cmd.tag = cpu_to_le32(ccb_tag);
18478c2ecf20Sopenharmony_ci	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
18488c2ecf20Sopenharmony_ci	sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((0x1 << 7) | (0x5 << 9)));
18498c2ecf20Sopenharmony_ci	memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
18528c2ecf20Sopenharmony_ci			sizeof(sata_cmd), 0);
18538c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "Executing read log end\n");
18548c2ecf20Sopenharmony_ci	if (res) {
18558c2ecf20Sopenharmony_ci		sas_free_task(task);
18568c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, ccb_tag);
18578c2ecf20Sopenharmony_ci		kfree(dev);
18588c2ecf20Sopenharmony_ci	}
18598c2ecf20Sopenharmony_ci}
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci/**
18628c2ecf20Sopenharmony_ci * mpi_ssp_completion- process the event that FW response to the SSP request.
18638c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
18648c2ecf20Sopenharmony_ci * @piomb: the message contents of this outbound message.
18658c2ecf20Sopenharmony_ci *
18668c2ecf20Sopenharmony_ci * When FW has completed a ssp request for example a IO request, after it has
18678c2ecf20Sopenharmony_ci * filled the SG data with the data, it will trigger this event represent
18688c2ecf20Sopenharmony_ci * that he has finished the job,please check the coresponding buffer.
18698c2ecf20Sopenharmony_ci * So we will tell the caller who maybe waiting the result to tell upper layer
18708c2ecf20Sopenharmony_ci * that the task has been finished.
18718c2ecf20Sopenharmony_ci */
18728c2ecf20Sopenharmony_cistatic void
18738c2ecf20Sopenharmony_cimpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb)
18748c2ecf20Sopenharmony_ci{
18758c2ecf20Sopenharmony_ci	struct sas_task *t;
18768c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
18778c2ecf20Sopenharmony_ci	unsigned long flags;
18788c2ecf20Sopenharmony_ci	u32 status;
18798c2ecf20Sopenharmony_ci	u32 param;
18808c2ecf20Sopenharmony_ci	u32 tag;
18818c2ecf20Sopenharmony_ci	struct ssp_completion_resp *psspPayload;
18828c2ecf20Sopenharmony_ci	struct task_status_struct *ts;
18838c2ecf20Sopenharmony_ci	struct ssp_response_iu *iu;
18848c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev;
18858c2ecf20Sopenharmony_ci	psspPayload = (struct ssp_completion_resp *)(piomb + 4);
18868c2ecf20Sopenharmony_ci	status = le32_to_cpu(psspPayload->status);
18878c2ecf20Sopenharmony_ci	tag = le32_to_cpu(psspPayload->tag);
18888c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[tag];
18898c2ecf20Sopenharmony_ci	if ((status == IO_ABORTED) && ccb->open_retry) {
18908c2ecf20Sopenharmony_ci		/* Being completed by another */
18918c2ecf20Sopenharmony_ci		ccb->open_retry = 0;
18928c2ecf20Sopenharmony_ci		return;
18938c2ecf20Sopenharmony_ci	}
18948c2ecf20Sopenharmony_ci	pm8001_dev = ccb->device;
18958c2ecf20Sopenharmony_ci	param = le32_to_cpu(psspPayload->param);
18968c2ecf20Sopenharmony_ci	t = ccb->task;
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci	if (status && status != IO_UNDERFLOW)
18998c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", status);
19008c2ecf20Sopenharmony_ci	if (unlikely(!t || !t->lldd_task || !t->dev))
19018c2ecf20Sopenharmony_ci		return;
19028c2ecf20Sopenharmony_ci	ts = &t->task_status;
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
19058c2ecf20Sopenharmony_ci		   "tag::0x%x, status::0x%x task::0x%p\n", tag, status, t);
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	/* Print sas address of IO failed device */
19088c2ecf20Sopenharmony_ci	if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
19098c2ecf20Sopenharmony_ci		(status != IO_UNDERFLOW))
19108c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "SAS Address of IO Failure Drive:%016llx\n",
19118c2ecf20Sopenharmony_ci			   SAS_ADDR(t->dev->sas_addr));
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci	switch (status) {
19148c2ecf20Sopenharmony_ci	case IO_SUCCESS:
19158c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS ,param = 0x%x\n",
19168c2ecf20Sopenharmony_ci			   param);
19178c2ecf20Sopenharmony_ci		if (param == 0) {
19188c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_COMPLETE;
19198c2ecf20Sopenharmony_ci			ts->stat = SAS_SAM_STAT_GOOD;
19208c2ecf20Sopenharmony_ci		} else {
19218c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_COMPLETE;
19228c2ecf20Sopenharmony_ci			ts->stat = SAS_PROTO_RESPONSE;
19238c2ecf20Sopenharmony_ci			ts->residual = param;
19248c2ecf20Sopenharmony_ci			iu = &psspPayload->ssp_resp_iu;
19258c2ecf20Sopenharmony_ci			sas_ssp_task_response(pm8001_ha->dev, t, iu);
19268c2ecf20Sopenharmony_ci		}
19278c2ecf20Sopenharmony_ci		if (pm8001_dev)
19288c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19298c2ecf20Sopenharmony_ci		break;
19308c2ecf20Sopenharmony_ci	case IO_ABORTED:
19318c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");
19328c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
19338c2ecf20Sopenharmony_ci		ts->stat = SAS_ABORTED_TASK;
19348c2ecf20Sopenharmony_ci		if (pm8001_dev)
19358c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19368c2ecf20Sopenharmony_ci		break;
19378c2ecf20Sopenharmony_ci	case IO_UNDERFLOW:
19388c2ecf20Sopenharmony_ci		/* SSP Completion with error */
19398c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW ,param = 0x%x\n",
19408c2ecf20Sopenharmony_ci			   param);
19418c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
19428c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_UNDERRUN;
19438c2ecf20Sopenharmony_ci		ts->residual = param;
19448c2ecf20Sopenharmony_ci		if (pm8001_dev)
19458c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19468c2ecf20Sopenharmony_ci		break;
19478c2ecf20Sopenharmony_ci	case IO_NO_DEVICE:
19488c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
19498c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_UNDELIVERED;
19508c2ecf20Sopenharmony_ci		ts->stat = SAS_PHY_DOWN;
19518c2ecf20Sopenharmony_ci		if (pm8001_dev)
19528c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19538c2ecf20Sopenharmony_ci		break;
19548c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_BREAK:
19558c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
19568c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
19578c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
19588c2ecf20Sopenharmony_ci		/* Force the midlayer to retry */
19598c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
19608c2ecf20Sopenharmony_ci		if (pm8001_dev)
19618c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19628c2ecf20Sopenharmony_ci		break;
19638c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_PHY_NOT_READY:
19648c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
19658c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
19668c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
19678c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
19688c2ecf20Sopenharmony_ci		if (pm8001_dev)
19698c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19708c2ecf20Sopenharmony_ci		break;
19718c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME:
19728c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
19738c2ecf20Sopenharmony_ci			   "IO_XFER_ERROR_INVALID_SSP_RSP_FRAME\n");
19748c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
19758c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
19768c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
19778c2ecf20Sopenharmony_ci		if (pm8001_dev)
19788c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19798c2ecf20Sopenharmony_ci		break;
19808c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
19818c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
19828c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
19838c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
19848c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
19858c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_EPROTO;
19868c2ecf20Sopenharmony_ci		if (pm8001_dev)
19878c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19888c2ecf20Sopenharmony_ci		break;
19898c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
19908c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
19918c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
19928c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
19938c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
19948c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
19958c2ecf20Sopenharmony_ci		if (pm8001_dev)
19968c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
19978c2ecf20Sopenharmony_ci		break;
19988c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BREAK:
19998c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
20008c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20018c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20028c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
20038c2ecf20Sopenharmony_ci		if (pm8001_dev)
20048c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20058c2ecf20Sopenharmony_ci		break;
20068c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
20078c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
20088c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
20098c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
20108c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
20118c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
20128c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
20138c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20148c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20158c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
20168c2ecf20Sopenharmony_ci		if (!t->uldd_task)
20178c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha,
20188c2ecf20Sopenharmony_ci				pm8001_dev,
20198c2ecf20Sopenharmony_ci				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
20208c2ecf20Sopenharmony_ci		break;
20218c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
20228c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
20238c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
20248c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20258c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20268c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_BAD_DEST;
20278c2ecf20Sopenharmony_ci		if (pm8001_dev)
20288c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20298c2ecf20Sopenharmony_ci		break;
20308c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
20318c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
20328c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
20338c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20348c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20358c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
20368c2ecf20Sopenharmony_ci		if (pm8001_dev)
20378c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20388c2ecf20Sopenharmony_ci		break;
20398c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
20408c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
20418c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
20428c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_UNDELIVERED;
20438c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20448c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
20458c2ecf20Sopenharmony_ci		if (pm8001_dev)
20468c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20478c2ecf20Sopenharmony_ci		break;
20488c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_NAK_RECEIVED:
20498c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
20508c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20518c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20528c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
20538c2ecf20Sopenharmony_ci		if (pm8001_dev)
20548c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20558c2ecf20Sopenharmony_ci		break;
20568c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
20578c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
20588c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20598c2ecf20Sopenharmony_ci		ts->stat = SAS_NAK_R_ERR;
20608c2ecf20Sopenharmony_ci		if (pm8001_dev)
20618c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20628c2ecf20Sopenharmony_ci		break;
20638c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_DMA:
20648c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");
20658c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20668c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20678c2ecf20Sopenharmony_ci		if (pm8001_dev)
20688c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20698c2ecf20Sopenharmony_ci		break;
20708c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_TIMEOUT:
20718c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
20728c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20738c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20748c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
20758c2ecf20Sopenharmony_ci		if (pm8001_dev)
20768c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20778c2ecf20Sopenharmony_ci		break;
20788c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_OFFSET_MISMATCH:
20798c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
20808c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20818c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20828c2ecf20Sopenharmony_ci		if (pm8001_dev)
20838c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20848c2ecf20Sopenharmony_ci		break;
20858c2ecf20Sopenharmony_ci	case IO_PORT_IN_RESET:
20868c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
20878c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20888c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20898c2ecf20Sopenharmony_ci		if (pm8001_dev)
20908c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
20918c2ecf20Sopenharmony_ci		break;
20928c2ecf20Sopenharmony_ci	case IO_DS_NON_OPERATIONAL:
20938c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
20948c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
20958c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
20968c2ecf20Sopenharmony_ci		if (!t->uldd_task)
20978c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha,
20988c2ecf20Sopenharmony_ci				pm8001_dev,
20998c2ecf20Sopenharmony_ci				IO_DS_NON_OPERATIONAL);
21008c2ecf20Sopenharmony_ci		break;
21018c2ecf20Sopenharmony_ci	case IO_DS_IN_RECOVERY:
21028c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
21038c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
21048c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
21058c2ecf20Sopenharmony_ci		if (pm8001_dev)
21068c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
21078c2ecf20Sopenharmony_ci		break;
21088c2ecf20Sopenharmony_ci	case IO_TM_TAG_NOT_FOUND:
21098c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_TM_TAG_NOT_FOUND\n");
21108c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
21118c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
21128c2ecf20Sopenharmony_ci		if (pm8001_dev)
21138c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
21148c2ecf20Sopenharmony_ci		break;
21158c2ecf20Sopenharmony_ci	case IO_SSP_EXT_IU_ZERO_LEN_ERROR:
21168c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_SSP_EXT_IU_ZERO_LEN_ERROR\n");
21178c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
21188c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
21198c2ecf20Sopenharmony_ci		if (pm8001_dev)
21208c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
21218c2ecf20Sopenharmony_ci		break;
21228c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
21238c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
21248c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
21258c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
21268c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
21278c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
21288c2ecf20Sopenharmony_ci		if (pm8001_dev)
21298c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
21308c2ecf20Sopenharmony_ci		break;
21318c2ecf20Sopenharmony_ci	default:
21328c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
21338c2ecf20Sopenharmony_ci		/* not allowed case. Therefore, return failed status */
21348c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
21358c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
21368c2ecf20Sopenharmony_ci		if (pm8001_dev)
21378c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
21388c2ecf20Sopenharmony_ci		break;
21398c2ecf20Sopenharmony_ci	}
21408c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n ",
21418c2ecf20Sopenharmony_ci		   psspPayload->ssp_resp_iu.status);
21428c2ecf20Sopenharmony_ci	spin_lock_irqsave(&t->task_state_lock, flags);
21438c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
21448c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
21458c2ecf20Sopenharmony_ci	t->task_state_flags |= SAS_TASK_STATE_DONE;
21468c2ecf20Sopenharmony_ci	if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
21478c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
21488c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
21498c2ecf20Sopenharmony_ci			   "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
21508c2ecf20Sopenharmony_ci			   t, status, ts->resp, ts->stat);
21518c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
21528c2ecf20Sopenharmony_ci		if (t->slow_task)
21538c2ecf20Sopenharmony_ci			complete(&t->slow_task->completion);
21548c2ecf20Sopenharmony_ci	} else {
21558c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
21568c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
21578c2ecf20Sopenharmony_ci		mb();/* in order to force CPU ordering */
21588c2ecf20Sopenharmony_ci		t->task_done(t);
21598c2ecf20Sopenharmony_ci	}
21608c2ecf20Sopenharmony_ci}
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci/*See the comments for mpi_ssp_completion */
21638c2ecf20Sopenharmony_cistatic void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
21648c2ecf20Sopenharmony_ci{
21658c2ecf20Sopenharmony_ci	struct sas_task *t;
21668c2ecf20Sopenharmony_ci	unsigned long flags;
21678c2ecf20Sopenharmony_ci	struct task_status_struct *ts;
21688c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
21698c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev;
21708c2ecf20Sopenharmony_ci	struct ssp_event_resp *psspPayload =
21718c2ecf20Sopenharmony_ci		(struct ssp_event_resp *)(piomb + 4);
21728c2ecf20Sopenharmony_ci	u32 event = le32_to_cpu(psspPayload->event);
21738c2ecf20Sopenharmony_ci	u32 tag = le32_to_cpu(psspPayload->tag);
21748c2ecf20Sopenharmony_ci	u32 port_id = le32_to_cpu(psspPayload->port_id);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[tag];
21778c2ecf20Sopenharmony_ci	t = ccb->task;
21788c2ecf20Sopenharmony_ci	pm8001_dev = ccb->device;
21798c2ecf20Sopenharmony_ci	if (event)
21808c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", event);
21818c2ecf20Sopenharmony_ci	if (unlikely(!t || !t->lldd_task || !t->dev))
21828c2ecf20Sopenharmony_ci		return;
21838c2ecf20Sopenharmony_ci	ts = &t->task_status;
21848c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",
21858c2ecf20Sopenharmony_ci		   port_id, tag, event);
21868c2ecf20Sopenharmony_ci	switch (event) {
21878c2ecf20Sopenharmony_ci	case IO_OVERFLOW:
21888c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
21898c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
21908c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
21918c2ecf20Sopenharmony_ci		ts->residual = 0;
21928c2ecf20Sopenharmony_ci		if (pm8001_dev)
21938c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
21948c2ecf20Sopenharmony_ci		break;
21958c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_BREAK:
21968c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
21978c2ecf20Sopenharmony_ci		pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK);
21988c2ecf20Sopenharmony_ci		return;
21998c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_PHY_NOT_READY:
22008c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
22018c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22028c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22038c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
22048c2ecf20Sopenharmony_ci		break;
22058c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
22068c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
22078c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
22088c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22098c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22108c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_EPROTO;
22118c2ecf20Sopenharmony_ci		break;
22128c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
22138c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
22148c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
22158c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22168c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22178c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
22188c2ecf20Sopenharmony_ci		break;
22198c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BREAK:
22208c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
22218c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22228c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22238c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
22248c2ecf20Sopenharmony_ci		break;
22258c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
22268c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
22278c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
22288c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
22298c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
22308c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
22318c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
22328c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22338c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22348c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
22358c2ecf20Sopenharmony_ci		if (!t->uldd_task)
22368c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha,
22378c2ecf20Sopenharmony_ci				pm8001_dev,
22388c2ecf20Sopenharmony_ci				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
22398c2ecf20Sopenharmony_ci		break;
22408c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
22418c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
22428c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
22438c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22448c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22458c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_BAD_DEST;
22468c2ecf20Sopenharmony_ci		break;
22478c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
22488c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
22498c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
22508c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22518c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22528c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
22538c2ecf20Sopenharmony_ci		break;
22548c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
22558c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
22568c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
22578c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22588c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22598c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
22608c2ecf20Sopenharmony_ci		break;
22618c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_NAK_RECEIVED:
22628c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
22638c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22648c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
22658c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
22668c2ecf20Sopenharmony_ci		break;
22678c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
22688c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
22698c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22708c2ecf20Sopenharmony_ci		ts->stat = SAS_NAK_R_ERR;
22718c2ecf20Sopenharmony_ci		break;
22728c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_TIMEOUT:
22738c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
22748c2ecf20Sopenharmony_ci		pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT);
22758c2ecf20Sopenharmony_ci		return;
22768c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_UNEXPECTED_PHASE:
22778c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");
22788c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22798c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
22808c2ecf20Sopenharmony_ci		break;
22818c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_XFER_RDY_OVERRUN:
22828c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");
22838c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22848c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
22858c2ecf20Sopenharmony_ci		break;
22868c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
22878c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
22888c2ecf20Sopenharmony_ci			   "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");
22898c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22908c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
22918c2ecf20Sopenharmony_ci		break;
22928c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
22938c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
22948c2ecf20Sopenharmony_ci			   "IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n");
22958c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
22968c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
22978c2ecf20Sopenharmony_ci		break;
22988c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_OFFSET_MISMATCH:
22998c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
23008c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
23018c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
23028c2ecf20Sopenharmony_ci		break;
23038c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
23048c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
23058c2ecf20Sopenharmony_ci			   "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");
23068c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
23078c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
23088c2ecf20Sopenharmony_ci		break;
23098c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
23108c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IOERR,
23118c2ecf20Sopenharmony_ci			   "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n");
23128c2ecf20Sopenharmony_ci		/* TBC: used default set values */
23138c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
23148c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
23158c2ecf20Sopenharmony_ci		break;
23168c2ecf20Sopenharmony_ci	case IO_XFER_CMD_FRAME_ISSUED:
23178c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");
23188c2ecf20Sopenharmony_ci		return;
23198c2ecf20Sopenharmony_ci	default:
23208c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event);
23218c2ecf20Sopenharmony_ci		/* not allowed case. Therefore, return failed status */
23228c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
23238c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
23248c2ecf20Sopenharmony_ci		break;
23258c2ecf20Sopenharmony_ci	}
23268c2ecf20Sopenharmony_ci	spin_lock_irqsave(&t->task_state_lock, flags);
23278c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
23288c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
23298c2ecf20Sopenharmony_ci	t->task_state_flags |= SAS_TASK_STATE_DONE;
23308c2ecf20Sopenharmony_ci	if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
23318c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
23328c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
23338c2ecf20Sopenharmony_ci			   "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
23348c2ecf20Sopenharmony_ci			   t, event, ts->resp, ts->stat);
23358c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
23368c2ecf20Sopenharmony_ci	} else {
23378c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
23388c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
23398c2ecf20Sopenharmony_ci		mb();/* in order to force CPU ordering */
23408c2ecf20Sopenharmony_ci		t->task_done(t);
23418c2ecf20Sopenharmony_ci	}
23428c2ecf20Sopenharmony_ci}
23438c2ecf20Sopenharmony_ci
23448c2ecf20Sopenharmony_ci/*See the comments for mpi_ssp_completion */
23458c2ecf20Sopenharmony_cistatic void
23468c2ecf20Sopenharmony_cimpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
23478c2ecf20Sopenharmony_ci{
23488c2ecf20Sopenharmony_ci	struct sas_task *t;
23498c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
23508c2ecf20Sopenharmony_ci	u32 param;
23518c2ecf20Sopenharmony_ci	u32 status;
23528c2ecf20Sopenharmony_ci	u32 tag;
23538c2ecf20Sopenharmony_ci	int i, j;
23548c2ecf20Sopenharmony_ci	u8 sata_addr_low[4];
23558c2ecf20Sopenharmony_ci	u32 temp_sata_addr_low, temp_sata_addr_hi;
23568c2ecf20Sopenharmony_ci	u8 sata_addr_hi[4];
23578c2ecf20Sopenharmony_ci	struct sata_completion_resp *psataPayload;
23588c2ecf20Sopenharmony_ci	struct task_status_struct *ts;
23598c2ecf20Sopenharmony_ci	struct ata_task_resp *resp ;
23608c2ecf20Sopenharmony_ci	u32 *sata_resp;
23618c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev;
23628c2ecf20Sopenharmony_ci	unsigned long flags;
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_ci	psataPayload = (struct sata_completion_resp *)(piomb + 4);
23658c2ecf20Sopenharmony_ci	status = le32_to_cpu(psataPayload->status);
23668c2ecf20Sopenharmony_ci	tag = le32_to_cpu(psataPayload->tag);
23678c2ecf20Sopenharmony_ci
23688c2ecf20Sopenharmony_ci	if (!tag) {
23698c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "tag null\n");
23708c2ecf20Sopenharmony_ci		return;
23718c2ecf20Sopenharmony_ci	}
23728c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[tag];
23738c2ecf20Sopenharmony_ci	param = le32_to_cpu(psataPayload->param);
23748c2ecf20Sopenharmony_ci	if (ccb) {
23758c2ecf20Sopenharmony_ci		t = ccb->task;
23768c2ecf20Sopenharmony_ci		pm8001_dev = ccb->device;
23778c2ecf20Sopenharmony_ci	} else {
23788c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "ccb null\n");
23798c2ecf20Sopenharmony_ci		return;
23808c2ecf20Sopenharmony_ci	}
23818c2ecf20Sopenharmony_ci
23828c2ecf20Sopenharmony_ci	if (t) {
23838c2ecf20Sopenharmony_ci		if (t->dev && (t->dev->lldd_dev))
23848c2ecf20Sopenharmony_ci			pm8001_dev = t->dev->lldd_dev;
23858c2ecf20Sopenharmony_ci	} else {
23868c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "task null\n");
23878c2ecf20Sopenharmony_ci		return;
23888c2ecf20Sopenharmony_ci	}
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci	if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
23918c2ecf20Sopenharmony_ci		&& unlikely(!t || !t->lldd_task || !t->dev)) {
23928c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n");
23938c2ecf20Sopenharmony_ci		return;
23948c2ecf20Sopenharmony_ci	}
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci	ts = &t->task_status;
23978c2ecf20Sopenharmony_ci	if (!ts) {
23988c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "ts null\n");
23998c2ecf20Sopenharmony_ci		return;
24008c2ecf20Sopenharmony_ci	}
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci	if (unlikely(status))
24038c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IOERR,
24048c2ecf20Sopenharmony_ci			   "status:0x%x, tag:0x%x, task::0x%p\n",
24058c2ecf20Sopenharmony_ci			   status, tag, t);
24068c2ecf20Sopenharmony_ci
24078c2ecf20Sopenharmony_ci	/* Print sas address of IO failed device */
24088c2ecf20Sopenharmony_ci	if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
24098c2ecf20Sopenharmony_ci		(status != IO_UNDERFLOW)) {
24108c2ecf20Sopenharmony_ci		if (!((t->dev->parent) &&
24118c2ecf20Sopenharmony_ci			(dev_is_expander(t->dev->parent->dev_type)))) {
24128c2ecf20Sopenharmony_ci			for (i = 0 , j = 4; i <= 3 && j <= 7; i++ , j++)
24138c2ecf20Sopenharmony_ci				sata_addr_low[i] = pm8001_ha->sas_addr[j];
24148c2ecf20Sopenharmony_ci			for (i = 0 , j = 0; i <= 3 && j <= 3; i++ , j++)
24158c2ecf20Sopenharmony_ci				sata_addr_hi[i] = pm8001_ha->sas_addr[j];
24168c2ecf20Sopenharmony_ci			memcpy(&temp_sata_addr_low, sata_addr_low,
24178c2ecf20Sopenharmony_ci				sizeof(sata_addr_low));
24188c2ecf20Sopenharmony_ci			memcpy(&temp_sata_addr_hi, sata_addr_hi,
24198c2ecf20Sopenharmony_ci				sizeof(sata_addr_hi));
24208c2ecf20Sopenharmony_ci			temp_sata_addr_hi = (((temp_sata_addr_hi >> 24) & 0xff)
24218c2ecf20Sopenharmony_ci						|((temp_sata_addr_hi << 8) &
24228c2ecf20Sopenharmony_ci						0xff0000) |
24238c2ecf20Sopenharmony_ci						((temp_sata_addr_hi >> 8)
24248c2ecf20Sopenharmony_ci						& 0xff00) |
24258c2ecf20Sopenharmony_ci						((temp_sata_addr_hi << 24) &
24268c2ecf20Sopenharmony_ci						0xff000000));
24278c2ecf20Sopenharmony_ci			temp_sata_addr_low = ((((temp_sata_addr_low >> 24)
24288c2ecf20Sopenharmony_ci						& 0xff) |
24298c2ecf20Sopenharmony_ci						((temp_sata_addr_low << 8)
24308c2ecf20Sopenharmony_ci						& 0xff0000) |
24318c2ecf20Sopenharmony_ci						((temp_sata_addr_low >> 8)
24328c2ecf20Sopenharmony_ci						& 0xff00) |
24338c2ecf20Sopenharmony_ci						((temp_sata_addr_low << 24)
24348c2ecf20Sopenharmony_ci						& 0xff000000)) +
24358c2ecf20Sopenharmony_ci						pm8001_dev->attached_phy +
24368c2ecf20Sopenharmony_ci						0x10);
24378c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, FAIL,
24388c2ecf20Sopenharmony_ci				   "SAS Address of IO Failure Drive:%08x%08x\n",
24398c2ecf20Sopenharmony_ci				   temp_sata_addr_hi,
24408c2ecf20Sopenharmony_ci				   temp_sata_addr_low);
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci		} else {
24438c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, FAIL,
24448c2ecf20Sopenharmony_ci				   "SAS Address of IO Failure Drive:%016llx\n",
24458c2ecf20Sopenharmony_ci				   SAS_ADDR(t->dev->sas_addr));
24468c2ecf20Sopenharmony_ci		}
24478c2ecf20Sopenharmony_ci	}
24488c2ecf20Sopenharmony_ci	switch (status) {
24498c2ecf20Sopenharmony_ci	case IO_SUCCESS:
24508c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");
24518c2ecf20Sopenharmony_ci		if (param == 0) {
24528c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_COMPLETE;
24538c2ecf20Sopenharmony_ci			ts->stat = SAS_SAM_STAT_GOOD;
24548c2ecf20Sopenharmony_ci			/* check if response is for SEND READ LOG */
24558c2ecf20Sopenharmony_ci			if (pm8001_dev &&
24568c2ecf20Sopenharmony_ci				(pm8001_dev->id & NCQ_READ_LOG_FLAG)) {
24578c2ecf20Sopenharmony_ci				/* set new bit for abort_all */
24588c2ecf20Sopenharmony_ci				pm8001_dev->id |= NCQ_ABORT_ALL_FLAG;
24598c2ecf20Sopenharmony_ci				/* clear bit for read log */
24608c2ecf20Sopenharmony_ci				pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF;
24618c2ecf20Sopenharmony_ci				pm80xx_send_abort_all(pm8001_ha, pm8001_dev);
24628c2ecf20Sopenharmony_ci				/* Free the tag */
24638c2ecf20Sopenharmony_ci				pm8001_tag_free(pm8001_ha, tag);
24648c2ecf20Sopenharmony_ci				sas_free_task(t);
24658c2ecf20Sopenharmony_ci				return;
24668c2ecf20Sopenharmony_ci			}
24678c2ecf20Sopenharmony_ci		} else {
24688c2ecf20Sopenharmony_ci			u8 len;
24698c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_COMPLETE;
24708c2ecf20Sopenharmony_ci			ts->stat = SAS_PROTO_RESPONSE;
24718c2ecf20Sopenharmony_ci			ts->residual = param;
24728c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, IO,
24738c2ecf20Sopenharmony_ci				   "SAS_PROTO_RESPONSE len = %d\n",
24748c2ecf20Sopenharmony_ci				   param);
24758c2ecf20Sopenharmony_ci			sata_resp = &psataPayload->sata_resp[0];
24768c2ecf20Sopenharmony_ci			resp = (struct ata_task_resp *)ts->buf;
24778c2ecf20Sopenharmony_ci			if (t->ata_task.dma_xfer == 0 &&
24788c2ecf20Sopenharmony_ci			    t->data_dir == DMA_FROM_DEVICE) {
24798c2ecf20Sopenharmony_ci				len = sizeof(struct pio_setup_fis);
24808c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, IO,
24818c2ecf20Sopenharmony_ci					   "PIO read len = %d\n", len);
24828c2ecf20Sopenharmony_ci			} else if (t->ata_task.use_ncq &&
24838c2ecf20Sopenharmony_ci				   t->data_dir != DMA_NONE) {
24848c2ecf20Sopenharmony_ci				len = sizeof(struct set_dev_bits_fis);
24858c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",
24868c2ecf20Sopenharmony_ci					   len);
24878c2ecf20Sopenharmony_ci			} else {
24888c2ecf20Sopenharmony_ci				len = sizeof(struct dev_to_host_fis);
24898c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, IO, "other len = %d\n",
24908c2ecf20Sopenharmony_ci					   len);
24918c2ecf20Sopenharmony_ci			}
24928c2ecf20Sopenharmony_ci			if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
24938c2ecf20Sopenharmony_ci				resp->frame_len = len;
24948c2ecf20Sopenharmony_ci				memcpy(&resp->ending_fis[0], sata_resp, len);
24958c2ecf20Sopenharmony_ci				ts->buf_valid_size = sizeof(*resp);
24968c2ecf20Sopenharmony_ci			} else
24978c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, IO,
24988c2ecf20Sopenharmony_ci					   "response too large\n");
24998c2ecf20Sopenharmony_ci		}
25008c2ecf20Sopenharmony_ci		if (pm8001_dev)
25018c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25028c2ecf20Sopenharmony_ci		break;
25038c2ecf20Sopenharmony_ci	case IO_ABORTED:
25048c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");
25058c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25068c2ecf20Sopenharmony_ci		ts->stat = SAS_ABORTED_TASK;
25078c2ecf20Sopenharmony_ci		if (pm8001_dev)
25088c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25098c2ecf20Sopenharmony_ci		break;
25108c2ecf20Sopenharmony_ci		/* following cases are to do cases */
25118c2ecf20Sopenharmony_ci	case IO_UNDERFLOW:
25128c2ecf20Sopenharmony_ci		/* SATA Completion with error */
25138c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW param = %d\n", param);
25148c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25158c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_UNDERRUN;
25168c2ecf20Sopenharmony_ci		ts->residual = param;
25178c2ecf20Sopenharmony_ci		if (pm8001_dev)
25188c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25198c2ecf20Sopenharmony_ci		break;
25208c2ecf20Sopenharmony_ci	case IO_NO_DEVICE:
25218c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
25228c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_UNDELIVERED;
25238c2ecf20Sopenharmony_ci		ts->stat = SAS_PHY_DOWN;
25248c2ecf20Sopenharmony_ci		if (pm8001_dev)
25258c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25268c2ecf20Sopenharmony_ci		break;
25278c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_BREAK:
25288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
25298c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25308c2ecf20Sopenharmony_ci		ts->stat = SAS_INTERRUPTED;
25318c2ecf20Sopenharmony_ci		if (pm8001_dev)
25328c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25338c2ecf20Sopenharmony_ci		break;
25348c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_PHY_NOT_READY:
25358c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
25368c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25378c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
25388c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
25398c2ecf20Sopenharmony_ci		if (pm8001_dev)
25408c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25418c2ecf20Sopenharmony_ci		break;
25428c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
25438c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
25448c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
25458c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25468c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
25478c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_EPROTO;
25488c2ecf20Sopenharmony_ci		if (pm8001_dev)
25498c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25508c2ecf20Sopenharmony_ci		break;
25518c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
25528c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
25538c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
25548c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25558c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
25568c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
25578c2ecf20Sopenharmony_ci		if (pm8001_dev)
25588c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25598c2ecf20Sopenharmony_ci		break;
25608c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BREAK:
25618c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
25628c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25638c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
25648c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
25658c2ecf20Sopenharmony_ci		if (pm8001_dev)
25668c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
25678c2ecf20Sopenharmony_ci		break;
25688c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
25698c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
25708c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
25718c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
25728c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
25738c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
25748c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
25758c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
25768c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
25778c2ecf20Sopenharmony_ci		if (!t->uldd_task) {
25788c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha,
25798c2ecf20Sopenharmony_ci				pm8001_dev,
25808c2ecf20Sopenharmony_ci				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
25818c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_UNDELIVERED;
25828c2ecf20Sopenharmony_ci			ts->stat = SAS_QUEUE_FULL;
25838c2ecf20Sopenharmony_ci			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
25848c2ecf20Sopenharmony_ci			return;
25858c2ecf20Sopenharmony_ci		}
25868c2ecf20Sopenharmony_ci		break;
25878c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
25888c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
25898c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
25908c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_UNDELIVERED;
25918c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
25928c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_BAD_DEST;
25938c2ecf20Sopenharmony_ci		if (!t->uldd_task) {
25948c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha,
25958c2ecf20Sopenharmony_ci				pm8001_dev,
25968c2ecf20Sopenharmony_ci				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
25978c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_UNDELIVERED;
25988c2ecf20Sopenharmony_ci			ts->stat = SAS_QUEUE_FULL;
25998c2ecf20Sopenharmony_ci			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
26008c2ecf20Sopenharmony_ci			return;
26018c2ecf20Sopenharmony_ci		}
26028c2ecf20Sopenharmony_ci		break;
26038c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
26048c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
26058c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
26068c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26078c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
26088c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
26098c2ecf20Sopenharmony_ci		if (pm8001_dev)
26108c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26118c2ecf20Sopenharmony_ci		break;
26128c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
26138c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
26148c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n");
26158c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26168c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
26178c2ecf20Sopenharmony_ci		if (!t->uldd_task) {
26188c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha,
26198c2ecf20Sopenharmony_ci				pm8001_dev,
26208c2ecf20Sopenharmony_ci				IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY);
26218c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_UNDELIVERED;
26228c2ecf20Sopenharmony_ci			ts->stat = SAS_QUEUE_FULL;
26238c2ecf20Sopenharmony_ci			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
26248c2ecf20Sopenharmony_ci			return;
26258c2ecf20Sopenharmony_ci		}
26268c2ecf20Sopenharmony_ci		break;
26278c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
26288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
26298c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
26308c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26318c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
26328c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
26338c2ecf20Sopenharmony_ci		if (pm8001_dev)
26348c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26358c2ecf20Sopenharmony_ci		break;
26368c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_NAK_RECEIVED:
26378c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
26388c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26398c2ecf20Sopenharmony_ci		ts->stat = SAS_NAK_R_ERR;
26408c2ecf20Sopenharmony_ci		if (pm8001_dev)
26418c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26428c2ecf20Sopenharmony_ci		break;
26438c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
26448c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
26458c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26468c2ecf20Sopenharmony_ci		ts->stat = SAS_NAK_R_ERR;
26478c2ecf20Sopenharmony_ci		if (pm8001_dev)
26488c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26498c2ecf20Sopenharmony_ci		break;
26508c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_DMA:
26518c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");
26528c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26538c2ecf20Sopenharmony_ci		ts->stat = SAS_ABORTED_TASK;
26548c2ecf20Sopenharmony_ci		if (pm8001_dev)
26558c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26568c2ecf20Sopenharmony_ci		break;
26578c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
26588c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_SATA_LINK_TIMEOUT\n");
26598c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_UNDELIVERED;
26608c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
26618c2ecf20Sopenharmony_ci		if (pm8001_dev)
26628c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26638c2ecf20Sopenharmony_ci		break;
26648c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_REJECTED_NCQ_MODE:
26658c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");
26668c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26678c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_UNDERRUN;
26688c2ecf20Sopenharmony_ci		if (pm8001_dev)
26698c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26708c2ecf20Sopenharmony_ci		break;
26718c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_TIMEOUT:
26728c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
26738c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26748c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
26758c2ecf20Sopenharmony_ci		if (pm8001_dev)
26768c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26778c2ecf20Sopenharmony_ci		break;
26788c2ecf20Sopenharmony_ci	case IO_PORT_IN_RESET:
26798c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
26808c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26818c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
26828c2ecf20Sopenharmony_ci		if (pm8001_dev)
26838c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
26848c2ecf20Sopenharmony_ci		break;
26858c2ecf20Sopenharmony_ci	case IO_DS_NON_OPERATIONAL:
26868c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
26878c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
26888c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
26898c2ecf20Sopenharmony_ci		if (!t->uldd_task) {
26908c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha, pm8001_dev,
26918c2ecf20Sopenharmony_ci					IO_DS_NON_OPERATIONAL);
26928c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_UNDELIVERED;
26938c2ecf20Sopenharmony_ci			ts->stat = SAS_QUEUE_FULL;
26948c2ecf20Sopenharmony_ci			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
26958c2ecf20Sopenharmony_ci			return;
26968c2ecf20Sopenharmony_ci		}
26978c2ecf20Sopenharmony_ci		break;
26988c2ecf20Sopenharmony_ci	case IO_DS_IN_RECOVERY:
26998c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
27008c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
27018c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
27028c2ecf20Sopenharmony_ci		if (pm8001_dev)
27038c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
27048c2ecf20Sopenharmony_ci		break;
27058c2ecf20Sopenharmony_ci	case IO_DS_IN_ERROR:
27068c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_ERROR\n");
27078c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
27088c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
27098c2ecf20Sopenharmony_ci		if (!t->uldd_task) {
27108c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha, pm8001_dev,
27118c2ecf20Sopenharmony_ci					IO_DS_IN_ERROR);
27128c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_UNDELIVERED;
27138c2ecf20Sopenharmony_ci			ts->stat = SAS_QUEUE_FULL;
27148c2ecf20Sopenharmony_ci			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
27158c2ecf20Sopenharmony_ci			return;
27168c2ecf20Sopenharmony_ci		}
27178c2ecf20Sopenharmony_ci		break;
27188c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
27198c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
27208c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
27218c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
27228c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
27238c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
27248c2ecf20Sopenharmony_ci		if (pm8001_dev)
27258c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
27268c2ecf20Sopenharmony_ci		break;
27278c2ecf20Sopenharmony_ci	default:
27288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
27298c2ecf20Sopenharmony_ci		/* not allowed case. Therefore, return failed status */
27308c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
27318c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
27328c2ecf20Sopenharmony_ci		if (pm8001_dev)
27338c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
27348c2ecf20Sopenharmony_ci		break;
27358c2ecf20Sopenharmony_ci	}
27368c2ecf20Sopenharmony_ci	spin_lock_irqsave(&t->task_state_lock, flags);
27378c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
27388c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
27398c2ecf20Sopenharmony_ci	t->task_state_flags |= SAS_TASK_STATE_DONE;
27408c2ecf20Sopenharmony_ci	if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
27418c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
27428c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
27438c2ecf20Sopenharmony_ci			   "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
27448c2ecf20Sopenharmony_ci			   t, status, ts->resp, ts->stat);
27458c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
27468c2ecf20Sopenharmony_ci		if (t->slow_task)
27478c2ecf20Sopenharmony_ci			complete(&t->slow_task->completion);
27488c2ecf20Sopenharmony_ci	} else {
27498c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
27508c2ecf20Sopenharmony_ci		pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
27518c2ecf20Sopenharmony_ci	}
27528c2ecf20Sopenharmony_ci}
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci/*See the comments for mpi_ssp_completion */
27558c2ecf20Sopenharmony_cistatic void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
27568c2ecf20Sopenharmony_ci{
27578c2ecf20Sopenharmony_ci	struct sas_task *t;
27588c2ecf20Sopenharmony_ci	struct task_status_struct *ts;
27598c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
27608c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev;
27618c2ecf20Sopenharmony_ci	struct sata_event_resp *psataPayload =
27628c2ecf20Sopenharmony_ci		(struct sata_event_resp *)(piomb + 4);
27638c2ecf20Sopenharmony_ci	u32 event = le32_to_cpu(psataPayload->event);
27648c2ecf20Sopenharmony_ci	u32 tag = le32_to_cpu(psataPayload->tag);
27658c2ecf20Sopenharmony_ci	u32 port_id = le32_to_cpu(psataPayload->port_id);
27668c2ecf20Sopenharmony_ci	u32 dev_id = le32_to_cpu(psataPayload->device_id);
27678c2ecf20Sopenharmony_ci	unsigned long flags;
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[tag];
27708c2ecf20Sopenharmony_ci
27718c2ecf20Sopenharmony_ci	if (ccb) {
27728c2ecf20Sopenharmony_ci		t = ccb->task;
27738c2ecf20Sopenharmony_ci		pm8001_dev = ccb->device;
27748c2ecf20Sopenharmony_ci	} else {
27758c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "No CCB !!!. returning\n");
27768c2ecf20Sopenharmony_ci		return;
27778c2ecf20Sopenharmony_ci	}
27788c2ecf20Sopenharmony_ci	if (event)
27798c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event);
27808c2ecf20Sopenharmony_ci
27818c2ecf20Sopenharmony_ci	/* Check if this is NCQ error */
27828c2ecf20Sopenharmony_ci	if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
27838c2ecf20Sopenharmony_ci		/* find device using device id */
27848c2ecf20Sopenharmony_ci		pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
27858c2ecf20Sopenharmony_ci		/* send read log extension */
27868c2ecf20Sopenharmony_ci		if (pm8001_dev)
27878c2ecf20Sopenharmony_ci			pm80xx_send_read_log(pm8001_ha, pm8001_dev);
27888c2ecf20Sopenharmony_ci		return;
27898c2ecf20Sopenharmony_ci	}
27908c2ecf20Sopenharmony_ci
27918c2ecf20Sopenharmony_ci	if (unlikely(!t || !t->lldd_task || !t->dev)) {
27928c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n");
27938c2ecf20Sopenharmony_ci		return;
27948c2ecf20Sopenharmony_ci	}
27958c2ecf20Sopenharmony_ci
27968c2ecf20Sopenharmony_ci	ts = &t->task_status;
27978c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",
27988c2ecf20Sopenharmony_ci		   port_id, tag, event);
27998c2ecf20Sopenharmony_ci	switch (event) {
28008c2ecf20Sopenharmony_ci	case IO_OVERFLOW:
28018c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
28028c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28038c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
28048c2ecf20Sopenharmony_ci		ts->residual = 0;
28058c2ecf20Sopenharmony_ci		if (pm8001_dev)
28068c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
28078c2ecf20Sopenharmony_ci		break;
28088c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_BREAK:
28098c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
28108c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28118c2ecf20Sopenharmony_ci		ts->stat = SAS_INTERRUPTED;
28128c2ecf20Sopenharmony_ci		break;
28138c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_PHY_NOT_READY:
28148c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
28158c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28168c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
28178c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
28188c2ecf20Sopenharmony_ci		break;
28198c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
28208c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
28218c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
28228c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28238c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
28248c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_EPROTO;
28258c2ecf20Sopenharmony_ci		break;
28268c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
28278c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
28288c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
28298c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28308c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
28318c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
28328c2ecf20Sopenharmony_ci		break;
28338c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BREAK:
28348c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
28358c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28368c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
28378c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
28388c2ecf20Sopenharmony_ci		break;
28398c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
28408c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
28418c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
28428c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
28438c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
28448c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
28458c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
28468c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
28478c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_UNDELIVERED;
28488c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
28498c2ecf20Sopenharmony_ci		if (!t->uldd_task) {
28508c2ecf20Sopenharmony_ci			pm8001_handle_event(pm8001_ha,
28518c2ecf20Sopenharmony_ci				pm8001_dev,
28528c2ecf20Sopenharmony_ci				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
28538c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_COMPLETE;
28548c2ecf20Sopenharmony_ci			ts->stat = SAS_QUEUE_FULL;
28558c2ecf20Sopenharmony_ci			pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
28568c2ecf20Sopenharmony_ci			return;
28578c2ecf20Sopenharmony_ci		}
28588c2ecf20Sopenharmony_ci		break;
28598c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
28608c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
28618c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
28628c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_UNDELIVERED;
28638c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
28648c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_BAD_DEST;
28658c2ecf20Sopenharmony_ci		break;
28668c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
28678c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
28688c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
28698c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28708c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
28718c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
28728c2ecf20Sopenharmony_ci		break;
28738c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
28748c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
28758c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
28768c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28778c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
28788c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
28798c2ecf20Sopenharmony_ci		break;
28808c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_NAK_RECEIVED:
28818c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
28828c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28838c2ecf20Sopenharmony_ci		ts->stat = SAS_NAK_R_ERR;
28848c2ecf20Sopenharmony_ci		break;
28858c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_PEER_ABORTED:
28868c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PEER_ABORTED\n");
28878c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28888c2ecf20Sopenharmony_ci		ts->stat = SAS_NAK_R_ERR;
28898c2ecf20Sopenharmony_ci		break;
28908c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_REJECTED_NCQ_MODE:
28918c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");
28928c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28938c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_UNDERRUN;
28948c2ecf20Sopenharmony_ci		break;
28958c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_TIMEOUT:
28968c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
28978c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
28988c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
28998c2ecf20Sopenharmony_ci		break;
29008c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_UNEXPECTED_PHASE:
29018c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");
29028c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29038c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29048c2ecf20Sopenharmony_ci		break;
29058c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_XFER_RDY_OVERRUN:
29068c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");
29078c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29088c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29098c2ecf20Sopenharmony_ci		break;
29108c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
29118c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
29128c2ecf20Sopenharmony_ci			   "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");
29138c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29148c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29158c2ecf20Sopenharmony_ci		break;
29168c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_OFFSET_MISMATCH:
29178c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
29188c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29198c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29208c2ecf20Sopenharmony_ci		break;
29218c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
29228c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
29238c2ecf20Sopenharmony_ci			   "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");
29248c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29258c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29268c2ecf20Sopenharmony_ci		break;
29278c2ecf20Sopenharmony_ci	case IO_XFER_CMD_FRAME_ISSUED:
29288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");
29298c2ecf20Sopenharmony_ci		break;
29308c2ecf20Sopenharmony_ci	case IO_XFER_PIO_SETUP_ERROR:
29318c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_PIO_SETUP_ERROR\n");
29328c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29338c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29348c2ecf20Sopenharmony_ci		break;
29358c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
29368c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
29378c2ecf20Sopenharmony_ci			   "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n");
29388c2ecf20Sopenharmony_ci		/* TBC: used default set values */
29398c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29408c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29418c2ecf20Sopenharmony_ci		break;
29428c2ecf20Sopenharmony_ci	case IO_XFER_DMA_ACTIVATE_TIMEOUT:
29438c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "IO_XFR_DMA_ACTIVATE_TIMEOUT\n");
29448c2ecf20Sopenharmony_ci		/* TBC: used default set values */
29458c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29468c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29478c2ecf20Sopenharmony_ci		break;
29488c2ecf20Sopenharmony_ci	default:
29498c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "Unknown status 0x%x\n", event);
29508c2ecf20Sopenharmony_ci		/* not allowed case. Therefore, return failed status */
29518c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
29528c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_TO;
29538c2ecf20Sopenharmony_ci		break;
29548c2ecf20Sopenharmony_ci	}
29558c2ecf20Sopenharmony_ci	spin_lock_irqsave(&t->task_state_lock, flags);
29568c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
29578c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
29588c2ecf20Sopenharmony_ci	t->task_state_flags |= SAS_TASK_STATE_DONE;
29598c2ecf20Sopenharmony_ci	if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
29608c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
29618c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
29628c2ecf20Sopenharmony_ci			   "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
29638c2ecf20Sopenharmony_ci			   t, event, ts->resp, ts->stat);
29648c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
29658c2ecf20Sopenharmony_ci	} else {
29668c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
29678c2ecf20Sopenharmony_ci		pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
29688c2ecf20Sopenharmony_ci	}
29698c2ecf20Sopenharmony_ci}
29708c2ecf20Sopenharmony_ci
29718c2ecf20Sopenharmony_ci/*See the comments for mpi_ssp_completion */
29728c2ecf20Sopenharmony_cistatic void
29738c2ecf20Sopenharmony_cimpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
29748c2ecf20Sopenharmony_ci{
29758c2ecf20Sopenharmony_ci	u32 param, i;
29768c2ecf20Sopenharmony_ci	struct sas_task *t;
29778c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
29788c2ecf20Sopenharmony_ci	unsigned long flags;
29798c2ecf20Sopenharmony_ci	u32 status;
29808c2ecf20Sopenharmony_ci	u32 tag;
29818c2ecf20Sopenharmony_ci	struct smp_completion_resp *psmpPayload;
29828c2ecf20Sopenharmony_ci	struct task_status_struct *ts;
29838c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev;
29848c2ecf20Sopenharmony_ci	char *pdma_respaddr = NULL;
29858c2ecf20Sopenharmony_ci
29868c2ecf20Sopenharmony_ci	psmpPayload = (struct smp_completion_resp *)(piomb + 4);
29878c2ecf20Sopenharmony_ci	status = le32_to_cpu(psmpPayload->status);
29888c2ecf20Sopenharmony_ci	tag = le32_to_cpu(psmpPayload->tag);
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[tag];
29918c2ecf20Sopenharmony_ci	param = le32_to_cpu(psmpPayload->param);
29928c2ecf20Sopenharmony_ci	t = ccb->task;
29938c2ecf20Sopenharmony_ci	ts = &t->task_status;
29948c2ecf20Sopenharmony_ci	pm8001_dev = ccb->device;
29958c2ecf20Sopenharmony_ci	if (status)
29968c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "smp IO status 0x%x\n", status);
29978c2ecf20Sopenharmony_ci	if (unlikely(!t || !t->lldd_task || !t->dev))
29988c2ecf20Sopenharmony_ci		return;
29998c2ecf20Sopenharmony_ci
30008c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV, "tag::0x%x status::0x%x\n", tag, status);
30018c2ecf20Sopenharmony_ci
30028c2ecf20Sopenharmony_ci	switch (status) {
30038c2ecf20Sopenharmony_ci
30048c2ecf20Sopenharmony_ci	case IO_SUCCESS:
30058c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");
30068c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30078c2ecf20Sopenharmony_ci		ts->stat = SAS_SAM_STAT_GOOD;
30088c2ecf20Sopenharmony_ci		if (pm8001_dev)
30098c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
30108c2ecf20Sopenharmony_ci		if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
30118c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, IO,
30128c2ecf20Sopenharmony_ci				   "DIRECT RESPONSE Length:%d\n",
30138c2ecf20Sopenharmony_ci				   param);
30148c2ecf20Sopenharmony_ci			pdma_respaddr = (char *)(phys_to_virt(cpu_to_le64
30158c2ecf20Sopenharmony_ci						((u64)sg_dma_address
30168c2ecf20Sopenharmony_ci						(&t->smp_task.smp_resp))));
30178c2ecf20Sopenharmony_ci			for (i = 0; i < param; i++) {
30188c2ecf20Sopenharmony_ci				*(pdma_respaddr+i) = psmpPayload->_r_a[i];
30198c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, IO,
30208c2ecf20Sopenharmony_ci					   "SMP Byte%d DMA data 0x%x psmp 0x%x\n",
30218c2ecf20Sopenharmony_ci					   i, *(pdma_respaddr + i),
30228c2ecf20Sopenharmony_ci					   psmpPayload->_r_a[i]);
30238c2ecf20Sopenharmony_ci			}
30248c2ecf20Sopenharmony_ci		}
30258c2ecf20Sopenharmony_ci		break;
30268c2ecf20Sopenharmony_ci	case IO_ABORTED:
30278c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB\n");
30288c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30298c2ecf20Sopenharmony_ci		ts->stat = SAS_ABORTED_TASK;
30308c2ecf20Sopenharmony_ci		if (pm8001_dev)
30318c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
30328c2ecf20Sopenharmony_ci		break;
30338c2ecf20Sopenharmony_ci	case IO_OVERFLOW:
30348c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
30358c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30368c2ecf20Sopenharmony_ci		ts->stat = SAS_DATA_OVERRUN;
30378c2ecf20Sopenharmony_ci		ts->residual = 0;
30388c2ecf20Sopenharmony_ci		if (pm8001_dev)
30398c2ecf20Sopenharmony_ci			atomic_dec(&pm8001_dev->running_req);
30408c2ecf20Sopenharmony_ci		break;
30418c2ecf20Sopenharmony_ci	case IO_NO_DEVICE:
30428c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
30438c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30448c2ecf20Sopenharmony_ci		ts->stat = SAS_PHY_DOWN;
30458c2ecf20Sopenharmony_ci		break;
30468c2ecf20Sopenharmony_ci	case IO_ERROR_HW_TIMEOUT:
30478c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_ERROR_HW_TIMEOUT\n");
30488c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30498c2ecf20Sopenharmony_ci		ts->stat = SAS_SAM_STAT_BUSY;
30508c2ecf20Sopenharmony_ci		break;
30518c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_BREAK:
30528c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
30538c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30548c2ecf20Sopenharmony_ci		ts->stat = SAS_SAM_STAT_BUSY;
30558c2ecf20Sopenharmony_ci		break;
30568c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_PHY_NOT_READY:
30578c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
30588c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30598c2ecf20Sopenharmony_ci		ts->stat = SAS_SAM_STAT_BUSY;
30608c2ecf20Sopenharmony_ci		break;
30618c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
30628c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
30638c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
30648c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30658c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
30668c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
30678c2ecf20Sopenharmony_ci		break;
30688c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
30698c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
30708c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
30718c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30728c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
30738c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
30748c2ecf20Sopenharmony_ci		break;
30758c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BREAK:
30768c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
30778c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30788c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
30798c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
30808c2ecf20Sopenharmony_ci		break;
30818c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
30828c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
30838c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
30848c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
30858c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
30868c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
30878c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
30888c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30898c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
30908c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_UNKNOWN;
30918c2ecf20Sopenharmony_ci		pm8001_handle_event(pm8001_ha,
30928c2ecf20Sopenharmony_ci				pm8001_dev,
30938c2ecf20Sopenharmony_ci				IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
30948c2ecf20Sopenharmony_ci		break;
30958c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
30968c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
30978c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
30988c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
30998c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
31008c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_BAD_DEST;
31018c2ecf20Sopenharmony_ci		break;
31028c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
31038c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
31048c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
31058c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31068c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
31078c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_CONN_RATE;
31088c2ecf20Sopenharmony_ci		break;
31098c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
31108c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
31118c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
31128c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31138c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
31148c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
31158c2ecf20Sopenharmony_ci		break;
31168c2ecf20Sopenharmony_ci	case IO_XFER_ERROR_RX_FRAME:
31178c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_RX_FRAME\n");
31188c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31198c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
31208c2ecf20Sopenharmony_ci		break;
31218c2ecf20Sopenharmony_ci	case IO_XFER_OPEN_RETRY_TIMEOUT:
31228c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
31238c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31248c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
31258c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
31268c2ecf20Sopenharmony_ci		break;
31278c2ecf20Sopenharmony_ci	case IO_ERROR_INTERNAL_SMP_RESOURCE:
31288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_ERROR_INTERNAL_SMP_RESOURCE\n");
31298c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31308c2ecf20Sopenharmony_ci		ts->stat = SAS_QUEUE_FULL;
31318c2ecf20Sopenharmony_ci		break;
31328c2ecf20Sopenharmony_ci	case IO_PORT_IN_RESET:
31338c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
31348c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31358c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
31368c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
31378c2ecf20Sopenharmony_ci		break;
31388c2ecf20Sopenharmony_ci	case IO_DS_NON_OPERATIONAL:
31398c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
31408c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31418c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
31428c2ecf20Sopenharmony_ci		break;
31438c2ecf20Sopenharmony_ci	case IO_DS_IN_RECOVERY:
31448c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
31458c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31468c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
31478c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
31488c2ecf20Sopenharmony_ci		break;
31498c2ecf20Sopenharmony_ci	case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
31508c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
31518c2ecf20Sopenharmony_ci			   "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
31528c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31538c2ecf20Sopenharmony_ci		ts->stat = SAS_OPEN_REJECT;
31548c2ecf20Sopenharmony_ci		ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
31558c2ecf20Sopenharmony_ci		break;
31568c2ecf20Sopenharmony_ci	default:
31578c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
31588c2ecf20Sopenharmony_ci		ts->resp = SAS_TASK_COMPLETE;
31598c2ecf20Sopenharmony_ci		ts->stat = SAS_DEV_NO_RESPONSE;
31608c2ecf20Sopenharmony_ci		/* not allowed case. Therefore, return failed status */
31618c2ecf20Sopenharmony_ci		break;
31628c2ecf20Sopenharmony_ci	}
31638c2ecf20Sopenharmony_ci	spin_lock_irqsave(&t->task_state_lock, flags);
31648c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
31658c2ecf20Sopenharmony_ci	t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
31668c2ecf20Sopenharmony_ci	t->task_state_flags |= SAS_TASK_STATE_DONE;
31678c2ecf20Sopenharmony_ci	if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
31688c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
31698c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
31708c2ecf20Sopenharmony_ci			   "task 0x%p done with io_status 0x%x resp 0x%xstat 0x%x but aborted by upper layer!\n",
31718c2ecf20Sopenharmony_ci			   t, status, ts->resp, ts->stat);
31728c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
31738c2ecf20Sopenharmony_ci	} else {
31748c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&t->task_state_lock, flags);
31758c2ecf20Sopenharmony_ci		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
31768c2ecf20Sopenharmony_ci		mb();/* in order to force CPU ordering */
31778c2ecf20Sopenharmony_ci		t->task_done(t);
31788c2ecf20Sopenharmony_ci	}
31798c2ecf20Sopenharmony_ci}
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci/**
31828c2ecf20Sopenharmony_ci * pm80xx_hw_event_ack_req- For PM8001,some events need to acknowage to FW.
31838c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
31848c2ecf20Sopenharmony_ci * @Qnum: the outbound queue message number.
31858c2ecf20Sopenharmony_ci * @SEA: source of event to ack
31868c2ecf20Sopenharmony_ci * @port_id: port id.
31878c2ecf20Sopenharmony_ci * @phyId: phy id.
31888c2ecf20Sopenharmony_ci * @param0: parameter 0.
31898c2ecf20Sopenharmony_ci * @param1: parameter 1.
31908c2ecf20Sopenharmony_ci */
31918c2ecf20Sopenharmony_cistatic void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha,
31928c2ecf20Sopenharmony_ci	u32 Qnum, u32 SEA, u32 port_id, u32 phyId, u32 param0, u32 param1)
31938c2ecf20Sopenharmony_ci{
31948c2ecf20Sopenharmony_ci	struct hw_event_ack_req	 payload;
31958c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SAS_HW_EVENT_ACK;
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
31988c2ecf20Sopenharmony_ci
31998c2ecf20Sopenharmony_ci	memset((u8 *)&payload, 0, sizeof(payload));
32008c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[Qnum];
32018c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(1);
32028c2ecf20Sopenharmony_ci	payload.phyid_sea_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) |
32038c2ecf20Sopenharmony_ci		((phyId & 0xFF) << 24) | (port_id & 0xFF));
32048c2ecf20Sopenharmony_ci	payload.param0 = cpu_to_le32(param0);
32058c2ecf20Sopenharmony_ci	payload.param1 = cpu_to_le32(param1);
32068c2ecf20Sopenharmony_ci	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
32078c2ecf20Sopenharmony_ci			sizeof(payload), 0);
32088c2ecf20Sopenharmony_ci}
32098c2ecf20Sopenharmony_ci
32108c2ecf20Sopenharmony_cistatic int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
32118c2ecf20Sopenharmony_ci	u32 phyId, u32 phy_op);
32128c2ecf20Sopenharmony_ci
32138c2ecf20Sopenharmony_cistatic void hw_event_port_recover(struct pm8001_hba_info *pm8001_ha,
32148c2ecf20Sopenharmony_ci					void *piomb)
32158c2ecf20Sopenharmony_ci{
32168c2ecf20Sopenharmony_ci	struct hw_event_resp *pPayload = (struct hw_event_resp *)(piomb + 4);
32178c2ecf20Sopenharmony_ci	u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
32188c2ecf20Sopenharmony_ci	u8 phy_id = (u8)((phyid_npip_portstate & 0xFF0000) >> 16);
32198c2ecf20Sopenharmony_ci	u32 lr_status_evt_portid =
32208c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->lr_status_evt_portid);
32218c2ecf20Sopenharmony_ci	u8 deviceType = pPayload->sas_identify.dev_type;
32228c2ecf20Sopenharmony_ci	u8 link_rate = (u8)((lr_status_evt_portid & 0xF0000000) >> 28);
32238c2ecf20Sopenharmony_ci	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
32248c2ecf20Sopenharmony_ci	u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
32258c2ecf20Sopenharmony_ci	struct pm8001_port *port = &pm8001_ha->port[port_id];
32268c2ecf20Sopenharmony_ci
32278c2ecf20Sopenharmony_ci	if (deviceType == SAS_END_DEVICE) {
32288c2ecf20Sopenharmony_ci		pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id,
32298c2ecf20Sopenharmony_ci					PHY_NOTIFY_ENABLE_SPINUP);
32308c2ecf20Sopenharmony_ci	}
32318c2ecf20Sopenharmony_ci
32328c2ecf20Sopenharmony_ci	port->wide_port_phymap |= (1U << phy_id);
32338c2ecf20Sopenharmony_ci	pm8001_get_lrate_mode(phy, link_rate);
32348c2ecf20Sopenharmony_ci	phy->sas_phy.oob_mode = SAS_OOB_MODE;
32358c2ecf20Sopenharmony_ci	phy->phy_state = PHY_STATE_LINK_UP_SPCV;
32368c2ecf20Sopenharmony_ci	phy->phy_attached = 1;
32378c2ecf20Sopenharmony_ci}
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci/**
32408c2ecf20Sopenharmony_ci * hw_event_sas_phy_up -FW tells me a SAS phy up event.
32418c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
32428c2ecf20Sopenharmony_ci * @piomb: IO message buffer
32438c2ecf20Sopenharmony_ci */
32448c2ecf20Sopenharmony_cistatic void
32458c2ecf20Sopenharmony_cihw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
32468c2ecf20Sopenharmony_ci{
32478c2ecf20Sopenharmony_ci	struct hw_event_resp *pPayload =
32488c2ecf20Sopenharmony_ci		(struct hw_event_resp *)(piomb + 4);
32498c2ecf20Sopenharmony_ci	u32 lr_status_evt_portid =
32508c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->lr_status_evt_portid);
32518c2ecf20Sopenharmony_ci	u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
32528c2ecf20Sopenharmony_ci
32538c2ecf20Sopenharmony_ci	u8 link_rate =
32548c2ecf20Sopenharmony_ci		(u8)((lr_status_evt_portid & 0xF0000000) >> 28);
32558c2ecf20Sopenharmony_ci	u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
32568c2ecf20Sopenharmony_ci	u8 phy_id =
32578c2ecf20Sopenharmony_ci		(u8)((phyid_npip_portstate & 0xFF0000) >> 16);
32588c2ecf20Sopenharmony_ci	u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
32598c2ecf20Sopenharmony_ci
32608c2ecf20Sopenharmony_ci	struct pm8001_port *port = &pm8001_ha->port[port_id];
32618c2ecf20Sopenharmony_ci	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
32628c2ecf20Sopenharmony_ci	unsigned long flags;
32638c2ecf20Sopenharmony_ci	u8 deviceType = pPayload->sas_identify.dev_type;
32648c2ecf20Sopenharmony_ci	port->port_state = portstate;
32658c2ecf20Sopenharmony_ci	port->wide_port_phymap |= (1U << phy_id);
32668c2ecf20Sopenharmony_ci	phy->phy_state = PHY_STATE_LINK_UP_SPCV;
32678c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG,
32688c2ecf20Sopenharmony_ci		   "portid:%d; phyid:%d; linkrate:%d; portstate:%x; devicetype:%x\n",
32698c2ecf20Sopenharmony_ci		   port_id, phy_id, link_rate, portstate, deviceType);
32708c2ecf20Sopenharmony_ci
32718c2ecf20Sopenharmony_ci	switch (deviceType) {
32728c2ecf20Sopenharmony_ci	case SAS_PHY_UNUSED:
32738c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "device type no device.\n");
32748c2ecf20Sopenharmony_ci		break;
32758c2ecf20Sopenharmony_ci	case SAS_END_DEVICE:
32768c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "end device.\n");
32778c2ecf20Sopenharmony_ci		pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id,
32788c2ecf20Sopenharmony_ci			PHY_NOTIFY_ENABLE_SPINUP);
32798c2ecf20Sopenharmony_ci		port->port_attached = 1;
32808c2ecf20Sopenharmony_ci		pm8001_get_lrate_mode(phy, link_rate);
32818c2ecf20Sopenharmony_ci		break;
32828c2ecf20Sopenharmony_ci	case SAS_EDGE_EXPANDER_DEVICE:
32838c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "expander device.\n");
32848c2ecf20Sopenharmony_ci		port->port_attached = 1;
32858c2ecf20Sopenharmony_ci		pm8001_get_lrate_mode(phy, link_rate);
32868c2ecf20Sopenharmony_ci		break;
32878c2ecf20Sopenharmony_ci	case SAS_FANOUT_EXPANDER_DEVICE:
32888c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "fanout expander device.\n");
32898c2ecf20Sopenharmony_ci		port->port_attached = 1;
32908c2ecf20Sopenharmony_ci		pm8001_get_lrate_mode(phy, link_rate);
32918c2ecf20Sopenharmony_ci		break;
32928c2ecf20Sopenharmony_ci	default:
32938c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO, "unknown device type(%x)\n",
32948c2ecf20Sopenharmony_ci			   deviceType);
32958c2ecf20Sopenharmony_ci		break;
32968c2ecf20Sopenharmony_ci	}
32978c2ecf20Sopenharmony_ci	phy->phy_type |= PORT_TYPE_SAS;
32988c2ecf20Sopenharmony_ci	phy->identify.device_type = deviceType;
32998c2ecf20Sopenharmony_ci	phy->phy_attached = 1;
33008c2ecf20Sopenharmony_ci	if (phy->identify.device_type == SAS_END_DEVICE)
33018c2ecf20Sopenharmony_ci		phy->identify.target_port_protocols = SAS_PROTOCOL_SSP;
33028c2ecf20Sopenharmony_ci	else if (phy->identify.device_type != SAS_PHY_UNUSED)
33038c2ecf20Sopenharmony_ci		phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
33048c2ecf20Sopenharmony_ci	phy->sas_phy.oob_mode = SAS_OOB_MODE;
33058c2ecf20Sopenharmony_ci	sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
33068c2ecf20Sopenharmony_ci	spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
33078c2ecf20Sopenharmony_ci	memcpy(phy->frame_rcvd, &pPayload->sas_identify,
33088c2ecf20Sopenharmony_ci		sizeof(struct sas_identify_frame)-4);
33098c2ecf20Sopenharmony_ci	phy->frame_rcvd_size = sizeof(struct sas_identify_frame) - 4;
33108c2ecf20Sopenharmony_ci	pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
33118c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
33128c2ecf20Sopenharmony_ci	if (pm8001_ha->flags == PM8001F_RUN_TIME)
33138c2ecf20Sopenharmony_ci		mdelay(200); /* delay a moment to wait for disk to spin up */
33148c2ecf20Sopenharmony_ci	pm8001_bytes_dmaed(pm8001_ha, phy_id);
33158c2ecf20Sopenharmony_ci}
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ci/**
33188c2ecf20Sopenharmony_ci * hw_event_sata_phy_up -FW tells me a SATA phy up event.
33198c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
33208c2ecf20Sopenharmony_ci * @piomb: IO message buffer
33218c2ecf20Sopenharmony_ci */
33228c2ecf20Sopenharmony_cistatic void
33238c2ecf20Sopenharmony_cihw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
33248c2ecf20Sopenharmony_ci{
33258c2ecf20Sopenharmony_ci	struct hw_event_resp *pPayload =
33268c2ecf20Sopenharmony_ci		(struct hw_event_resp *)(piomb + 4);
33278c2ecf20Sopenharmony_ci	u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
33288c2ecf20Sopenharmony_ci	u32 lr_status_evt_portid =
33298c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->lr_status_evt_portid);
33308c2ecf20Sopenharmony_ci	u8 link_rate =
33318c2ecf20Sopenharmony_ci		(u8)((lr_status_evt_portid & 0xF0000000) >> 28);
33328c2ecf20Sopenharmony_ci	u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
33338c2ecf20Sopenharmony_ci	u8 phy_id =
33348c2ecf20Sopenharmony_ci		(u8)((phyid_npip_portstate & 0xFF0000) >> 16);
33358c2ecf20Sopenharmony_ci
33368c2ecf20Sopenharmony_ci	u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci	struct pm8001_port *port = &pm8001_ha->port[port_id];
33398c2ecf20Sopenharmony_ci	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
33408c2ecf20Sopenharmony_ci	unsigned long flags;
33418c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEVIO,
33428c2ecf20Sopenharmony_ci		   "port id %d, phy id %d link_rate %d portstate 0x%x\n",
33438c2ecf20Sopenharmony_ci		   port_id, phy_id, link_rate, portstate);
33448c2ecf20Sopenharmony_ci
33458c2ecf20Sopenharmony_ci	port->port_state = portstate;
33468c2ecf20Sopenharmony_ci	phy->phy_state = PHY_STATE_LINK_UP_SPCV;
33478c2ecf20Sopenharmony_ci	port->port_attached = 1;
33488c2ecf20Sopenharmony_ci	pm8001_get_lrate_mode(phy, link_rate);
33498c2ecf20Sopenharmony_ci	phy->phy_type |= PORT_TYPE_SATA;
33508c2ecf20Sopenharmony_ci	phy->phy_attached = 1;
33518c2ecf20Sopenharmony_ci	phy->sas_phy.oob_mode = SATA_OOB_MODE;
33528c2ecf20Sopenharmony_ci	sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
33538c2ecf20Sopenharmony_ci	spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
33548c2ecf20Sopenharmony_ci	memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4),
33558c2ecf20Sopenharmony_ci		sizeof(struct dev_to_host_fis));
33568c2ecf20Sopenharmony_ci	phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
33578c2ecf20Sopenharmony_ci	phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
33588c2ecf20Sopenharmony_ci	phy->identify.device_type = SAS_SATA_DEV;
33598c2ecf20Sopenharmony_ci	pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
33608c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
33618c2ecf20Sopenharmony_ci	pm8001_bytes_dmaed(pm8001_ha, phy_id);
33628c2ecf20Sopenharmony_ci}
33638c2ecf20Sopenharmony_ci
33648c2ecf20Sopenharmony_ci/**
33658c2ecf20Sopenharmony_ci * hw_event_phy_down -we should notify the libsas the phy is down.
33668c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
33678c2ecf20Sopenharmony_ci * @piomb: IO message buffer
33688c2ecf20Sopenharmony_ci */
33698c2ecf20Sopenharmony_cistatic void
33708c2ecf20Sopenharmony_cihw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb)
33718c2ecf20Sopenharmony_ci{
33728c2ecf20Sopenharmony_ci	struct hw_event_resp *pPayload =
33738c2ecf20Sopenharmony_ci		(struct hw_event_resp *)(piomb + 4);
33748c2ecf20Sopenharmony_ci
33758c2ecf20Sopenharmony_ci	u32 lr_status_evt_portid =
33768c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->lr_status_evt_portid);
33778c2ecf20Sopenharmony_ci	u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
33788c2ecf20Sopenharmony_ci	u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
33798c2ecf20Sopenharmony_ci	u8 phy_id =
33808c2ecf20Sopenharmony_ci		(u8)((phyid_npip_portstate & 0xFF0000) >> 16);
33818c2ecf20Sopenharmony_ci	u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci	struct pm8001_port *port = &pm8001_ha->port[port_id];
33848c2ecf20Sopenharmony_ci	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
33858c2ecf20Sopenharmony_ci	u32 port_sata = (phy->phy_type & PORT_TYPE_SATA);
33868c2ecf20Sopenharmony_ci	port->port_state = portstate;
33878c2ecf20Sopenharmony_ci	phy->identify.device_type = 0;
33888c2ecf20Sopenharmony_ci	phy->phy_attached = 0;
33898c2ecf20Sopenharmony_ci	switch (portstate) {
33908c2ecf20Sopenharmony_ci	case PORT_VALID:
33918c2ecf20Sopenharmony_ci		break;
33928c2ecf20Sopenharmony_ci	case PORT_INVALID:
33938c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n",
33948c2ecf20Sopenharmony_ci			   port_id);
33958c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
33968c2ecf20Sopenharmony_ci			   " Last phy Down and port invalid\n");
33978c2ecf20Sopenharmony_ci		if (port_sata) {
33988c2ecf20Sopenharmony_ci			phy->phy_type = 0;
33998c2ecf20Sopenharmony_ci			port->port_attached = 0;
34008c2ecf20Sopenharmony_ci			pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
34018c2ecf20Sopenharmony_ci					port_id, phy_id, 0, 0);
34028c2ecf20Sopenharmony_ci		}
34038c2ecf20Sopenharmony_ci		sas_phy_disconnected(&phy->sas_phy);
34048c2ecf20Sopenharmony_ci		break;
34058c2ecf20Sopenharmony_ci	case PORT_IN_RESET:
34068c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n",
34078c2ecf20Sopenharmony_ci			   port_id);
34088c2ecf20Sopenharmony_ci		break;
34098c2ecf20Sopenharmony_ci	case PORT_NOT_ESTABLISHED:
34108c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
34118c2ecf20Sopenharmony_ci			   " Phy Down and PORT_NOT_ESTABLISHED\n");
34128c2ecf20Sopenharmony_ci		port->port_attached = 0;
34138c2ecf20Sopenharmony_ci		break;
34148c2ecf20Sopenharmony_ci	case PORT_LOSTCOMM:
34158c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, " Phy Down and PORT_LOSTCOMM\n");
34168c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
34178c2ecf20Sopenharmony_ci			   " Last phy Down and port invalid\n");
34188c2ecf20Sopenharmony_ci		if (port_sata) {
34198c2ecf20Sopenharmony_ci			port->port_attached = 0;
34208c2ecf20Sopenharmony_ci			phy->phy_type = 0;
34218c2ecf20Sopenharmony_ci			pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
34228c2ecf20Sopenharmony_ci					port_id, phy_id, 0, 0);
34238c2ecf20Sopenharmony_ci		}
34248c2ecf20Sopenharmony_ci		sas_phy_disconnected(&phy->sas_phy);
34258c2ecf20Sopenharmony_ci		break;
34268c2ecf20Sopenharmony_ci	default:
34278c2ecf20Sopenharmony_ci		port->port_attached = 0;
34288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO,
34298c2ecf20Sopenharmony_ci			   " Phy Down and(default) = 0x%x\n",
34308c2ecf20Sopenharmony_ci			   portstate);
34318c2ecf20Sopenharmony_ci		break;
34328c2ecf20Sopenharmony_ci
34338c2ecf20Sopenharmony_ci	}
34348c2ecf20Sopenharmony_ci	if (port_sata && (portstate != PORT_IN_RESET))
34358c2ecf20Sopenharmony_ci		sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
34368c2ecf20Sopenharmony_ci}
34378c2ecf20Sopenharmony_ci
34388c2ecf20Sopenharmony_cistatic int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
34398c2ecf20Sopenharmony_ci{
34408c2ecf20Sopenharmony_ci	struct phy_start_resp *pPayload =
34418c2ecf20Sopenharmony_ci		(struct phy_start_resp *)(piomb + 4);
34428c2ecf20Sopenharmony_ci	u32 status =
34438c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->status);
34448c2ecf20Sopenharmony_ci	u32 phy_id =
34458c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->phyid);
34468c2ecf20Sopenharmony_ci	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
34478c2ecf20Sopenharmony_ci
34488c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT,
34498c2ecf20Sopenharmony_ci		   "phy start resp status:0x%x, phyid:0x%x\n",
34508c2ecf20Sopenharmony_ci		   status, phy_id);
34518c2ecf20Sopenharmony_ci	if (status == 0)
34528c2ecf20Sopenharmony_ci		phy->phy_state = PHY_LINK_DOWN;
34538c2ecf20Sopenharmony_ci
34548c2ecf20Sopenharmony_ci	if (pm8001_ha->flags == PM8001F_RUN_TIME &&
34558c2ecf20Sopenharmony_ci			phy->enable_completion != NULL) {
34568c2ecf20Sopenharmony_ci		complete(phy->enable_completion);
34578c2ecf20Sopenharmony_ci		phy->enable_completion = NULL;
34588c2ecf20Sopenharmony_ci	}
34598c2ecf20Sopenharmony_ci	return 0;
34608c2ecf20Sopenharmony_ci
34618c2ecf20Sopenharmony_ci}
34628c2ecf20Sopenharmony_ci
34638c2ecf20Sopenharmony_ci/**
34648c2ecf20Sopenharmony_ci * mpi_thermal_hw_event -The hw event has come.
34658c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
34668c2ecf20Sopenharmony_ci * @piomb: IO message buffer
34678c2ecf20Sopenharmony_ci */
34688c2ecf20Sopenharmony_cistatic int mpi_thermal_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
34698c2ecf20Sopenharmony_ci{
34708c2ecf20Sopenharmony_ci	struct thermal_hw_event *pPayload =
34718c2ecf20Sopenharmony_ci		(struct thermal_hw_event *)(piomb + 4);
34728c2ecf20Sopenharmony_ci
34738c2ecf20Sopenharmony_ci	u32 thermal_event = le32_to_cpu(pPayload->thermal_event);
34748c2ecf20Sopenharmony_ci	u32 rht_lht = le32_to_cpu(pPayload->rht_lht);
34758c2ecf20Sopenharmony_ci
34768c2ecf20Sopenharmony_ci	if (thermal_event & 0x40) {
34778c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
34788c2ecf20Sopenharmony_ci			   "Thermal Event: Local high temperature violated!\n");
34798c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
34808c2ecf20Sopenharmony_ci			   "Thermal Event: Measured local high temperature %d\n",
34818c2ecf20Sopenharmony_ci			   ((rht_lht & 0xFF00) >> 8));
34828c2ecf20Sopenharmony_ci	}
34838c2ecf20Sopenharmony_ci	if (thermal_event & 0x10) {
34848c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
34858c2ecf20Sopenharmony_ci			   "Thermal Event: Remote high temperature violated!\n");
34868c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
34878c2ecf20Sopenharmony_ci			   "Thermal Event: Measured remote high temperature %d\n",
34888c2ecf20Sopenharmony_ci			   ((rht_lht & 0xFF000000) >> 24));
34898c2ecf20Sopenharmony_ci	}
34908c2ecf20Sopenharmony_ci	return 0;
34918c2ecf20Sopenharmony_ci}
34928c2ecf20Sopenharmony_ci
34938c2ecf20Sopenharmony_ci/**
34948c2ecf20Sopenharmony_ci * mpi_hw_event -The hw event has come.
34958c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
34968c2ecf20Sopenharmony_ci * @piomb: IO message buffer
34978c2ecf20Sopenharmony_ci */
34988c2ecf20Sopenharmony_cistatic int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
34998c2ecf20Sopenharmony_ci{
35008c2ecf20Sopenharmony_ci	unsigned long flags, i;
35018c2ecf20Sopenharmony_ci	struct hw_event_resp *pPayload =
35028c2ecf20Sopenharmony_ci		(struct hw_event_resp *)(piomb + 4);
35038c2ecf20Sopenharmony_ci	u32 lr_status_evt_portid =
35048c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->lr_status_evt_portid);
35058c2ecf20Sopenharmony_ci	u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate);
35068c2ecf20Sopenharmony_ci	u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF);
35078c2ecf20Sopenharmony_ci	u8 phy_id =
35088c2ecf20Sopenharmony_ci		(u8)((phyid_npip_portstate & 0xFF0000) >> 16);
35098c2ecf20Sopenharmony_ci	u16 eventType =
35108c2ecf20Sopenharmony_ci		(u16)((lr_status_evt_portid & 0x00FFFF00) >> 8);
35118c2ecf20Sopenharmony_ci	u8 status =
35128c2ecf20Sopenharmony_ci		(u8)((lr_status_evt_portid & 0x0F000000) >> 24);
35138c2ecf20Sopenharmony_ci	struct sas_ha_struct *sas_ha = pm8001_ha->sas;
35148c2ecf20Sopenharmony_ci	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
35158c2ecf20Sopenharmony_ci	struct pm8001_port *port = &pm8001_ha->port[port_id];
35168c2ecf20Sopenharmony_ci	struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
35178c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEV,
35188c2ecf20Sopenharmony_ci		   "portid:%d phyid:%d event:0x%x status:0x%x\n",
35198c2ecf20Sopenharmony_ci		   port_id, phy_id, eventType, status);
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ci	switch (eventType) {
35228c2ecf20Sopenharmony_ci
35238c2ecf20Sopenharmony_ci	case HW_EVENT_SAS_PHY_UP:
35248c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n");
35258c2ecf20Sopenharmony_ci		hw_event_sas_phy_up(pm8001_ha, piomb);
35268c2ecf20Sopenharmony_ci		break;
35278c2ecf20Sopenharmony_ci	case HW_EVENT_SATA_PHY_UP:
35288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n");
35298c2ecf20Sopenharmony_ci		hw_event_sata_phy_up(pm8001_ha, piomb);
35308c2ecf20Sopenharmony_ci		break;
35318c2ecf20Sopenharmony_ci	case HW_EVENT_SATA_SPINUP_HOLD:
35328c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
35338c2ecf20Sopenharmony_ci		sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
35348c2ecf20Sopenharmony_ci		break;
35358c2ecf20Sopenharmony_ci	case HW_EVENT_PHY_DOWN:
35368c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
35378c2ecf20Sopenharmony_ci		hw_event_phy_down(pm8001_ha, piomb);
35388c2ecf20Sopenharmony_ci		if (pm8001_ha->reset_in_progress) {
35398c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, MSG, "Reset in progress\n");
35408c2ecf20Sopenharmony_ci			return 0;
35418c2ecf20Sopenharmony_ci		}
35428c2ecf20Sopenharmony_ci		phy->phy_attached = 0;
35438c2ecf20Sopenharmony_ci		phy->phy_state = PHY_LINK_DISABLE;
35448c2ecf20Sopenharmony_ci		break;
35458c2ecf20Sopenharmony_ci	case HW_EVENT_PORT_INVALID:
35468c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
35478c2ecf20Sopenharmony_ci		sas_phy_disconnected(sas_phy);
35488c2ecf20Sopenharmony_ci		phy->phy_attached = 0;
35498c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
35508c2ecf20Sopenharmony_ci		break;
35518c2ecf20Sopenharmony_ci	/* the broadcast change primitive received, tell the LIBSAS this event
35528c2ecf20Sopenharmony_ci	to revalidate the sas domain*/
35538c2ecf20Sopenharmony_ci	case HW_EVENT_BROADCAST_CHANGE:
35548c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_CHANGE\n");
35558c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE,
35568c2ecf20Sopenharmony_ci			port_id, phy_id, 1, 0);
35578c2ecf20Sopenharmony_ci		spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
35588c2ecf20Sopenharmony_ci		sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
35598c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
35608c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
35618c2ecf20Sopenharmony_ci		break;
35628c2ecf20Sopenharmony_ci	case HW_EVENT_PHY_ERROR:
35638c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n");
35648c2ecf20Sopenharmony_ci		sas_phy_disconnected(&phy->sas_phy);
35658c2ecf20Sopenharmony_ci		phy->phy_attached = 0;
35668c2ecf20Sopenharmony_ci		sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
35678c2ecf20Sopenharmony_ci		break;
35688c2ecf20Sopenharmony_ci	case HW_EVENT_BROADCAST_EXP:
35698c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n");
35708c2ecf20Sopenharmony_ci		spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
35718c2ecf20Sopenharmony_ci		sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP;
35728c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
35738c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
35748c2ecf20Sopenharmony_ci		break;
35758c2ecf20Sopenharmony_ci	case HW_EVENT_LINK_ERR_INVALID_DWORD:
35768c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
35778c2ecf20Sopenharmony_ci			   "HW_EVENT_LINK_ERR_INVALID_DWORD\n");
35788c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0,
35798c2ecf20Sopenharmony_ci			HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0);
35808c2ecf20Sopenharmony_ci		break;
35818c2ecf20Sopenharmony_ci	case HW_EVENT_LINK_ERR_DISPARITY_ERROR:
35828c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
35838c2ecf20Sopenharmony_ci			   "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n");
35848c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0,
35858c2ecf20Sopenharmony_ci			HW_EVENT_LINK_ERR_DISPARITY_ERROR,
35868c2ecf20Sopenharmony_ci			port_id, phy_id, 0, 0);
35878c2ecf20Sopenharmony_ci		break;
35888c2ecf20Sopenharmony_ci	case HW_EVENT_LINK_ERR_CODE_VIOLATION:
35898c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
35908c2ecf20Sopenharmony_ci			   "HW_EVENT_LINK_ERR_CODE_VIOLATION\n");
35918c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0,
35928c2ecf20Sopenharmony_ci			HW_EVENT_LINK_ERR_CODE_VIOLATION,
35938c2ecf20Sopenharmony_ci			port_id, phy_id, 0, 0);
35948c2ecf20Sopenharmony_ci		break;
35958c2ecf20Sopenharmony_ci	case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:
35968c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
35978c2ecf20Sopenharmony_ci			   "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n");
35988c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0,
35998c2ecf20Sopenharmony_ci			HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,
36008c2ecf20Sopenharmony_ci			port_id, phy_id, 0, 0);
36018c2ecf20Sopenharmony_ci		break;
36028c2ecf20Sopenharmony_ci	case HW_EVENT_MALFUNCTION:
36038c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n");
36048c2ecf20Sopenharmony_ci		break;
36058c2ecf20Sopenharmony_ci	case HW_EVENT_BROADCAST_SES:
36068c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n");
36078c2ecf20Sopenharmony_ci		spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
36088c2ecf20Sopenharmony_ci		sas_phy->sas_prim = HW_EVENT_BROADCAST_SES;
36098c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
36108c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
36118c2ecf20Sopenharmony_ci		break;
36128c2ecf20Sopenharmony_ci	case HW_EVENT_INBOUND_CRC_ERROR:
36138c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n");
36148c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0,
36158c2ecf20Sopenharmony_ci			HW_EVENT_INBOUND_CRC_ERROR,
36168c2ecf20Sopenharmony_ci			port_id, phy_id, 0, 0);
36178c2ecf20Sopenharmony_ci		break;
36188c2ecf20Sopenharmony_ci	case HW_EVENT_HARD_RESET_RECEIVED:
36198c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n");
36208c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_HARD_RESET);
36218c2ecf20Sopenharmony_ci		break;
36228c2ecf20Sopenharmony_ci	case HW_EVENT_ID_FRAME_TIMEOUT:
36238c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n");
36248c2ecf20Sopenharmony_ci		sas_phy_disconnected(sas_phy);
36258c2ecf20Sopenharmony_ci		phy->phy_attached = 0;
36268c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
36278c2ecf20Sopenharmony_ci		break;
36288c2ecf20Sopenharmony_ci	case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
36298c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
36308c2ecf20Sopenharmony_ci			   "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n");
36318c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0,
36328c2ecf20Sopenharmony_ci			HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
36338c2ecf20Sopenharmony_ci			port_id, phy_id, 0, 0);
36348c2ecf20Sopenharmony_ci		sas_phy_disconnected(sas_phy);
36358c2ecf20Sopenharmony_ci		phy->phy_attached = 0;
36368c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
36378c2ecf20Sopenharmony_ci		break;
36388c2ecf20Sopenharmony_ci	case HW_EVENT_PORT_RESET_TIMER_TMO:
36398c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n");
36408c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
36418c2ecf20Sopenharmony_ci			port_id, phy_id, 0, 0);
36428c2ecf20Sopenharmony_ci		sas_phy_disconnected(sas_phy);
36438c2ecf20Sopenharmony_ci		phy->phy_attached = 0;
36448c2ecf20Sopenharmony_ci		sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
36458c2ecf20Sopenharmony_ci		if (pm8001_ha->phy[phy_id].reset_completion) {
36468c2ecf20Sopenharmony_ci			pm8001_ha->phy[phy_id].port_reset_status =
36478c2ecf20Sopenharmony_ci					PORT_RESET_TMO;
36488c2ecf20Sopenharmony_ci			complete(pm8001_ha->phy[phy_id].reset_completion);
36498c2ecf20Sopenharmony_ci			pm8001_ha->phy[phy_id].reset_completion = NULL;
36508c2ecf20Sopenharmony_ci		}
36518c2ecf20Sopenharmony_ci		break;
36528c2ecf20Sopenharmony_ci	case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
36538c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
36548c2ecf20Sopenharmony_ci			   "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n");
36558c2ecf20Sopenharmony_ci		pm80xx_hw_event_ack_req(pm8001_ha, 0,
36568c2ecf20Sopenharmony_ci			HW_EVENT_PORT_RECOVERY_TIMER_TMO,
36578c2ecf20Sopenharmony_ci			port_id, phy_id, 0, 0);
36588c2ecf20Sopenharmony_ci		for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
36598c2ecf20Sopenharmony_ci			if (port->wide_port_phymap & (1 << i)) {
36608c2ecf20Sopenharmony_ci				phy = &pm8001_ha->phy[i];
36618c2ecf20Sopenharmony_ci				sas_notify_phy_event(&phy->sas_phy,
36628c2ecf20Sopenharmony_ci						PHYE_LOSS_OF_SIGNAL);
36638c2ecf20Sopenharmony_ci				port->wide_port_phymap &= ~(1 << i);
36648c2ecf20Sopenharmony_ci			}
36658c2ecf20Sopenharmony_ci		}
36668c2ecf20Sopenharmony_ci		break;
36678c2ecf20Sopenharmony_ci	case HW_EVENT_PORT_RECOVER:
36688c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n");
36698c2ecf20Sopenharmony_ci		hw_event_port_recover(pm8001_ha, piomb);
36708c2ecf20Sopenharmony_ci		break;
36718c2ecf20Sopenharmony_ci	case HW_EVENT_PORT_RESET_COMPLETE:
36728c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n");
36738c2ecf20Sopenharmony_ci		if (pm8001_ha->phy[phy_id].reset_completion) {
36748c2ecf20Sopenharmony_ci			pm8001_ha->phy[phy_id].port_reset_status =
36758c2ecf20Sopenharmony_ci					PORT_RESET_SUCCESS;
36768c2ecf20Sopenharmony_ci			complete(pm8001_ha->phy[phy_id].reset_completion);
36778c2ecf20Sopenharmony_ci			pm8001_ha->phy[phy_id].reset_completion = NULL;
36788c2ecf20Sopenharmony_ci		}
36798c2ecf20Sopenharmony_ci		break;
36808c2ecf20Sopenharmony_ci	case EVENT_BROADCAST_ASYNCH_EVENT:
36818c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n");
36828c2ecf20Sopenharmony_ci		break;
36838c2ecf20Sopenharmony_ci	default:
36848c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type 0x%x\n",
36858c2ecf20Sopenharmony_ci			   eventType);
36868c2ecf20Sopenharmony_ci		break;
36878c2ecf20Sopenharmony_ci	}
36888c2ecf20Sopenharmony_ci	return 0;
36898c2ecf20Sopenharmony_ci}
36908c2ecf20Sopenharmony_ci
36918c2ecf20Sopenharmony_ci/**
36928c2ecf20Sopenharmony_ci * mpi_phy_stop_resp - SPCv specific
36938c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
36948c2ecf20Sopenharmony_ci * @piomb: IO message buffer
36958c2ecf20Sopenharmony_ci */
36968c2ecf20Sopenharmony_cistatic int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
36978c2ecf20Sopenharmony_ci{
36988c2ecf20Sopenharmony_ci	struct phy_stop_resp *pPayload =
36998c2ecf20Sopenharmony_ci		(struct phy_stop_resp *)(piomb + 4);
37008c2ecf20Sopenharmony_ci	u32 status =
37018c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->status);
37028c2ecf20Sopenharmony_ci	u32 phyid =
37038c2ecf20Sopenharmony_ci		le32_to_cpu(pPayload->phyid) & 0xFF;
37048c2ecf20Sopenharmony_ci	struct pm8001_phy *phy = &pm8001_ha->phy[phyid];
37058c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG, "phy:0x%x status:0x%x\n",
37068c2ecf20Sopenharmony_ci		   phyid, status);
37078c2ecf20Sopenharmony_ci	if (status == PHY_STOP_SUCCESS ||
37088c2ecf20Sopenharmony_ci		status == PHY_STOP_ERR_DEVICE_ATTACHED)
37098c2ecf20Sopenharmony_ci		phy->phy_state = PHY_LINK_DISABLE;
37108c2ecf20Sopenharmony_ci	return 0;
37118c2ecf20Sopenharmony_ci}
37128c2ecf20Sopenharmony_ci
37138c2ecf20Sopenharmony_ci/**
37148c2ecf20Sopenharmony_ci * mpi_set_controller_config_resp - SPCv specific
37158c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
37168c2ecf20Sopenharmony_ci * @piomb: IO message buffer
37178c2ecf20Sopenharmony_ci */
37188c2ecf20Sopenharmony_cistatic int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
37198c2ecf20Sopenharmony_ci			void *piomb)
37208c2ecf20Sopenharmony_ci{
37218c2ecf20Sopenharmony_ci	struct set_ctrl_cfg_resp *pPayload =
37228c2ecf20Sopenharmony_ci			(struct set_ctrl_cfg_resp *)(piomb + 4);
37238c2ecf20Sopenharmony_ci	u32 status = le32_to_cpu(pPayload->status);
37248c2ecf20Sopenharmony_ci	u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd);
37258c2ecf20Sopenharmony_ci	u32 tag = le32_to_cpu(pPayload->tag);
37268c2ecf20Sopenharmony_ci
37278c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG,
37288c2ecf20Sopenharmony_ci		   "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",
37298c2ecf20Sopenharmony_ci		   status, err_qlfr_pgcd);
37308c2ecf20Sopenharmony_ci	pm8001_tag_free(pm8001_ha, tag);
37318c2ecf20Sopenharmony_ci
37328c2ecf20Sopenharmony_ci	return 0;
37338c2ecf20Sopenharmony_ci}
37348c2ecf20Sopenharmony_ci
37358c2ecf20Sopenharmony_ci/**
37368c2ecf20Sopenharmony_ci * mpi_get_controller_config_resp - SPCv specific
37378c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
37388c2ecf20Sopenharmony_ci * @piomb: IO message buffer
37398c2ecf20Sopenharmony_ci */
37408c2ecf20Sopenharmony_cistatic int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
37418c2ecf20Sopenharmony_ci			void *piomb)
37428c2ecf20Sopenharmony_ci{
37438c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
37448c2ecf20Sopenharmony_ci
37458c2ecf20Sopenharmony_ci	return 0;
37468c2ecf20Sopenharmony_ci}
37478c2ecf20Sopenharmony_ci
37488c2ecf20Sopenharmony_ci/**
37498c2ecf20Sopenharmony_ci * mpi_get_phy_profile_resp - SPCv specific
37508c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
37518c2ecf20Sopenharmony_ci * @piomb: IO message buffer
37528c2ecf20Sopenharmony_ci */
37538c2ecf20Sopenharmony_cistatic int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
37548c2ecf20Sopenharmony_ci			void *piomb)
37558c2ecf20Sopenharmony_ci{
37568c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
37578c2ecf20Sopenharmony_ci
37588c2ecf20Sopenharmony_ci	return 0;
37598c2ecf20Sopenharmony_ci}
37608c2ecf20Sopenharmony_ci
37618c2ecf20Sopenharmony_ci/**
37628c2ecf20Sopenharmony_ci * mpi_flash_op_ext_resp - SPCv specific
37638c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
37648c2ecf20Sopenharmony_ci * @piomb: IO message buffer
37658c2ecf20Sopenharmony_ci */
37668c2ecf20Sopenharmony_cistatic int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
37678c2ecf20Sopenharmony_ci{
37688c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
37698c2ecf20Sopenharmony_ci
37708c2ecf20Sopenharmony_ci	return 0;
37718c2ecf20Sopenharmony_ci}
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci/**
37748c2ecf20Sopenharmony_ci * mpi_set_phy_profile_resp - SPCv specific
37758c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
37768c2ecf20Sopenharmony_ci * @piomb: IO message buffer
37778c2ecf20Sopenharmony_ci */
37788c2ecf20Sopenharmony_cistatic int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
37798c2ecf20Sopenharmony_ci			void *piomb)
37808c2ecf20Sopenharmony_ci{
37818c2ecf20Sopenharmony_ci	u32 tag;
37828c2ecf20Sopenharmony_ci	u8 page_code;
37838c2ecf20Sopenharmony_ci	int rc = 0;
37848c2ecf20Sopenharmony_ci	struct set_phy_profile_resp *pPayload =
37858c2ecf20Sopenharmony_ci		(struct set_phy_profile_resp *)(piomb + 4);
37868c2ecf20Sopenharmony_ci	u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid);
37878c2ecf20Sopenharmony_ci	u32 status = le32_to_cpu(pPayload->status);
37888c2ecf20Sopenharmony_ci
37898c2ecf20Sopenharmony_ci	tag = le32_to_cpu(pPayload->tag);
37908c2ecf20Sopenharmony_ci	page_code = (u8)((ppc_phyid & 0xFF00) >> 8);
37918c2ecf20Sopenharmony_ci	if (status) {
37928c2ecf20Sopenharmony_ci		/* status is FAILED */
37938c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL,
37948c2ecf20Sopenharmony_ci			   "PhyProfile command failed  with status 0x%08X\n",
37958c2ecf20Sopenharmony_ci			   status);
37968c2ecf20Sopenharmony_ci		rc = -1;
37978c2ecf20Sopenharmony_ci	} else {
37988c2ecf20Sopenharmony_ci		if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) {
37998c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, FAIL, "Invalid page code 0x%X\n",
38008c2ecf20Sopenharmony_ci				   page_code);
38018c2ecf20Sopenharmony_ci			rc = -1;
38028c2ecf20Sopenharmony_ci		}
38038c2ecf20Sopenharmony_ci	}
38048c2ecf20Sopenharmony_ci	pm8001_tag_free(pm8001_ha, tag);
38058c2ecf20Sopenharmony_ci	return rc;
38068c2ecf20Sopenharmony_ci}
38078c2ecf20Sopenharmony_ci
38088c2ecf20Sopenharmony_ci/**
38098c2ecf20Sopenharmony_ci * mpi_kek_management_resp - SPCv specific
38108c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
38118c2ecf20Sopenharmony_ci * @piomb: IO message buffer
38128c2ecf20Sopenharmony_ci */
38138c2ecf20Sopenharmony_cistatic int mpi_kek_management_resp(struct pm8001_hba_info *pm8001_ha,
38148c2ecf20Sopenharmony_ci			void *piomb)
38158c2ecf20Sopenharmony_ci{
38168c2ecf20Sopenharmony_ci	struct kek_mgmt_resp *pPayload = (struct kek_mgmt_resp *)(piomb + 4);
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_ci	u32 status = le32_to_cpu(pPayload->status);
38198c2ecf20Sopenharmony_ci	u32 kidx_new_curr_ksop = le32_to_cpu(pPayload->kidx_new_curr_ksop);
38208c2ecf20Sopenharmony_ci	u32 err_qlfr = le32_to_cpu(pPayload->err_qlfr);
38218c2ecf20Sopenharmony_ci
38228c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG,
38238c2ecf20Sopenharmony_ci		   "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n",
38248c2ecf20Sopenharmony_ci		   status, kidx_new_curr_ksop, err_qlfr);
38258c2ecf20Sopenharmony_ci
38268c2ecf20Sopenharmony_ci	return 0;
38278c2ecf20Sopenharmony_ci}
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci/**
38308c2ecf20Sopenharmony_ci * mpi_dek_management_resp - SPCv specific
38318c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
38328c2ecf20Sopenharmony_ci * @piomb: IO message buffer
38338c2ecf20Sopenharmony_ci */
38348c2ecf20Sopenharmony_cistatic int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha,
38358c2ecf20Sopenharmony_ci			void *piomb)
38368c2ecf20Sopenharmony_ci{
38378c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
38388c2ecf20Sopenharmony_ci
38398c2ecf20Sopenharmony_ci	return 0;
38408c2ecf20Sopenharmony_ci}
38418c2ecf20Sopenharmony_ci
38428c2ecf20Sopenharmony_ci/**
38438c2ecf20Sopenharmony_ci * ssp_coalesced_comp_resp - SPCv specific
38448c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
38458c2ecf20Sopenharmony_ci * @piomb: IO message buffer
38468c2ecf20Sopenharmony_ci */
38478c2ecf20Sopenharmony_cistatic int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
38488c2ecf20Sopenharmony_ci			void *piomb)
38498c2ecf20Sopenharmony_ci{
38508c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
38518c2ecf20Sopenharmony_ci
38528c2ecf20Sopenharmony_ci	return 0;
38538c2ecf20Sopenharmony_ci}
38548c2ecf20Sopenharmony_ci
38558c2ecf20Sopenharmony_ci/**
38568c2ecf20Sopenharmony_ci * process_one_iomb - process one outbound Queue memory block
38578c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information
38588c2ecf20Sopenharmony_ci * @piomb: IO message buffer
38598c2ecf20Sopenharmony_ci */
38608c2ecf20Sopenharmony_cistatic void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb)
38618c2ecf20Sopenharmony_ci{
38628c2ecf20Sopenharmony_ci	__le32 pHeader = *(__le32 *)piomb;
38638c2ecf20Sopenharmony_ci	u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF);
38648c2ecf20Sopenharmony_ci
38658c2ecf20Sopenharmony_ci	switch (opc) {
38668c2ecf20Sopenharmony_ci	case OPC_OUB_ECHO:
38678c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_ECHO\n");
38688c2ecf20Sopenharmony_ci		break;
38698c2ecf20Sopenharmony_ci	case OPC_OUB_HW_EVENT:
38708c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_HW_EVENT\n");
38718c2ecf20Sopenharmony_ci		mpi_hw_event(pm8001_ha, piomb);
38728c2ecf20Sopenharmony_ci		break;
38738c2ecf20Sopenharmony_ci	case OPC_OUB_THERM_HW_EVENT:
38748c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_THERMAL_EVENT\n");
38758c2ecf20Sopenharmony_ci		mpi_thermal_hw_event(pm8001_ha, piomb);
38768c2ecf20Sopenharmony_ci		break;
38778c2ecf20Sopenharmony_ci	case OPC_OUB_SSP_COMP:
38788c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_COMP\n");
38798c2ecf20Sopenharmony_ci		mpi_ssp_completion(pm8001_ha, piomb);
38808c2ecf20Sopenharmony_ci		break;
38818c2ecf20Sopenharmony_ci	case OPC_OUB_SMP_COMP:
38828c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_COMP\n");
38838c2ecf20Sopenharmony_ci		mpi_smp_completion(pm8001_ha, piomb);
38848c2ecf20Sopenharmony_ci		break;
38858c2ecf20Sopenharmony_ci	case OPC_OUB_LOCAL_PHY_CNTRL:
38868c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_LOCAL_PHY_CNTRL\n");
38878c2ecf20Sopenharmony_ci		pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);
38888c2ecf20Sopenharmony_ci		break;
38898c2ecf20Sopenharmony_ci	case OPC_OUB_DEV_REGIST:
38908c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_REGIST\n");
38918c2ecf20Sopenharmony_ci		pm8001_mpi_reg_resp(pm8001_ha, piomb);
38928c2ecf20Sopenharmony_ci		break;
38938c2ecf20Sopenharmony_ci	case OPC_OUB_DEREG_DEV:
38948c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "unregister the device\n");
38958c2ecf20Sopenharmony_ci		pm8001_mpi_dereg_resp(pm8001_ha, piomb);
38968c2ecf20Sopenharmony_ci		break;
38978c2ecf20Sopenharmony_ci	case OPC_OUB_GET_DEV_HANDLE:
38988c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEV_HANDLE\n");
38998c2ecf20Sopenharmony_ci		break;
39008c2ecf20Sopenharmony_ci	case OPC_OUB_SATA_COMP:
39018c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n");
39028c2ecf20Sopenharmony_ci		mpi_sata_completion(pm8001_ha, piomb);
39038c2ecf20Sopenharmony_ci		break;
39048c2ecf20Sopenharmony_ci	case OPC_OUB_SATA_EVENT:
39058c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n");
39068c2ecf20Sopenharmony_ci		mpi_sata_event(pm8001_ha, piomb);
39078c2ecf20Sopenharmony_ci		break;
39088c2ecf20Sopenharmony_ci	case OPC_OUB_SSP_EVENT:
39098c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n");
39108c2ecf20Sopenharmony_ci		mpi_ssp_event(pm8001_ha, piomb);
39118c2ecf20Sopenharmony_ci		break;
39128c2ecf20Sopenharmony_ci	case OPC_OUB_DEV_HANDLE_ARRIV:
39138c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_HANDLE_ARRIV\n");
39148c2ecf20Sopenharmony_ci		/*This is for target*/
39158c2ecf20Sopenharmony_ci		break;
39168c2ecf20Sopenharmony_ci	case OPC_OUB_SSP_RECV_EVENT:
39178c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_RECV_EVENT\n");
39188c2ecf20Sopenharmony_ci		/*This is for target*/
39198c2ecf20Sopenharmony_ci		break;
39208c2ecf20Sopenharmony_ci	case OPC_OUB_FW_FLASH_UPDATE:
39218c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_FW_FLASH_UPDATE\n");
39228c2ecf20Sopenharmony_ci		pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);
39238c2ecf20Sopenharmony_ci		break;
39248c2ecf20Sopenharmony_ci	case OPC_OUB_GPIO_RESPONSE:
39258c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_RESPONSE\n");
39268c2ecf20Sopenharmony_ci		break;
39278c2ecf20Sopenharmony_ci	case OPC_OUB_GPIO_EVENT:
39288c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_EVENT\n");
39298c2ecf20Sopenharmony_ci		break;
39308c2ecf20Sopenharmony_ci	case OPC_OUB_GENERAL_EVENT:
39318c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GENERAL_EVENT\n");
39328c2ecf20Sopenharmony_ci		pm8001_mpi_general_event(pm8001_ha, piomb);
39338c2ecf20Sopenharmony_ci		break;
39348c2ecf20Sopenharmony_ci	case OPC_OUB_SSP_ABORT_RSP:
39358c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_ABORT_RSP\n");
39368c2ecf20Sopenharmony_ci		pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
39378c2ecf20Sopenharmony_ci		break;
39388c2ecf20Sopenharmony_ci	case OPC_OUB_SATA_ABORT_RSP:
39398c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_ABORT_RSP\n");
39408c2ecf20Sopenharmony_ci		pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
39418c2ecf20Sopenharmony_ci		break;
39428c2ecf20Sopenharmony_ci	case OPC_OUB_SAS_DIAG_MODE_START_END:
39438c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
39448c2ecf20Sopenharmony_ci			   "OPC_OUB_SAS_DIAG_MODE_START_END\n");
39458c2ecf20Sopenharmony_ci		break;
39468c2ecf20Sopenharmony_ci	case OPC_OUB_SAS_DIAG_EXECUTE:
39478c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_DIAG_EXECUTE\n");
39488c2ecf20Sopenharmony_ci		break;
39498c2ecf20Sopenharmony_ci	case OPC_OUB_GET_TIME_STAMP:
39508c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_TIME_STAMP\n");
39518c2ecf20Sopenharmony_ci		break;
39528c2ecf20Sopenharmony_ci	case OPC_OUB_SAS_HW_EVENT_ACK:
39538c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_HW_EVENT_ACK\n");
39548c2ecf20Sopenharmony_ci		break;
39558c2ecf20Sopenharmony_ci	case OPC_OUB_PORT_CONTROL:
39568c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_PORT_CONTROL\n");
39578c2ecf20Sopenharmony_ci		break;
39588c2ecf20Sopenharmony_ci	case OPC_OUB_SMP_ABORT_RSP:
39598c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_ABORT_RSP\n");
39608c2ecf20Sopenharmony_ci		pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
39618c2ecf20Sopenharmony_ci		break;
39628c2ecf20Sopenharmony_ci	case OPC_OUB_GET_NVMD_DATA:
39638c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_NVMD_DATA\n");
39648c2ecf20Sopenharmony_ci		pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);
39658c2ecf20Sopenharmony_ci		break;
39668c2ecf20Sopenharmony_ci	case OPC_OUB_SET_NVMD_DATA:
39678c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_NVMD_DATA\n");
39688c2ecf20Sopenharmony_ci		pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);
39698c2ecf20Sopenharmony_ci		break;
39708c2ecf20Sopenharmony_ci	case OPC_OUB_DEVICE_HANDLE_REMOVAL:
39718c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEVICE_HANDLE_REMOVAL\n");
39728c2ecf20Sopenharmony_ci		break;
39738c2ecf20Sopenharmony_ci	case OPC_OUB_SET_DEVICE_STATE:
39748c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEVICE_STATE\n");
39758c2ecf20Sopenharmony_ci		pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);
39768c2ecf20Sopenharmony_ci		break;
39778c2ecf20Sopenharmony_ci	case OPC_OUB_GET_DEVICE_STATE:
39788c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEVICE_STATE\n");
39798c2ecf20Sopenharmony_ci		break;
39808c2ecf20Sopenharmony_ci	case OPC_OUB_SET_DEV_INFO:
39818c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEV_INFO\n");
39828c2ecf20Sopenharmony_ci		break;
39838c2ecf20Sopenharmony_ci	/* spcv specifc commands */
39848c2ecf20Sopenharmony_ci	case OPC_OUB_PHY_START_RESP:
39858c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
39868c2ecf20Sopenharmony_ci			   "OPC_OUB_PHY_START_RESP opcode:%x\n", opc);
39878c2ecf20Sopenharmony_ci		mpi_phy_start_resp(pm8001_ha, piomb);
39888c2ecf20Sopenharmony_ci		break;
39898c2ecf20Sopenharmony_ci	case OPC_OUB_PHY_STOP_RESP:
39908c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
39918c2ecf20Sopenharmony_ci			   "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc);
39928c2ecf20Sopenharmony_ci		mpi_phy_stop_resp(pm8001_ha, piomb);
39938c2ecf20Sopenharmony_ci		break;
39948c2ecf20Sopenharmony_ci	case OPC_OUB_SET_CONTROLLER_CONFIG:
39958c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
39968c2ecf20Sopenharmony_ci			   "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc);
39978c2ecf20Sopenharmony_ci		mpi_set_controller_config_resp(pm8001_ha, piomb);
39988c2ecf20Sopenharmony_ci		break;
39998c2ecf20Sopenharmony_ci	case OPC_OUB_GET_CONTROLLER_CONFIG:
40008c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
40018c2ecf20Sopenharmony_ci			   "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc);
40028c2ecf20Sopenharmony_ci		mpi_get_controller_config_resp(pm8001_ha, piomb);
40038c2ecf20Sopenharmony_ci		break;
40048c2ecf20Sopenharmony_ci	case OPC_OUB_GET_PHY_PROFILE:
40058c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
40068c2ecf20Sopenharmony_ci			   "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc);
40078c2ecf20Sopenharmony_ci		mpi_get_phy_profile_resp(pm8001_ha, piomb);
40088c2ecf20Sopenharmony_ci		break;
40098c2ecf20Sopenharmony_ci	case OPC_OUB_FLASH_OP_EXT:
40108c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
40118c2ecf20Sopenharmony_ci			   "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc);
40128c2ecf20Sopenharmony_ci		mpi_flash_op_ext_resp(pm8001_ha, piomb);
40138c2ecf20Sopenharmony_ci		break;
40148c2ecf20Sopenharmony_ci	case OPC_OUB_SET_PHY_PROFILE:
40158c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
40168c2ecf20Sopenharmony_ci			   "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc);
40178c2ecf20Sopenharmony_ci		mpi_set_phy_profile_resp(pm8001_ha, piomb);
40188c2ecf20Sopenharmony_ci		break;
40198c2ecf20Sopenharmony_ci	case OPC_OUB_KEK_MANAGEMENT_RESP:
40208c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
40218c2ecf20Sopenharmony_ci			   "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc);
40228c2ecf20Sopenharmony_ci		mpi_kek_management_resp(pm8001_ha, piomb);
40238c2ecf20Sopenharmony_ci		break;
40248c2ecf20Sopenharmony_ci	case OPC_OUB_DEK_MANAGEMENT_RESP:
40258c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
40268c2ecf20Sopenharmony_ci			   "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc);
40278c2ecf20Sopenharmony_ci		mpi_dek_management_resp(pm8001_ha, piomb);
40288c2ecf20Sopenharmony_ci		break;
40298c2ecf20Sopenharmony_ci	case OPC_OUB_SSP_COALESCED_COMP_RESP:
40308c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, MSG,
40318c2ecf20Sopenharmony_ci			   "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc);
40328c2ecf20Sopenharmony_ci		ssp_coalesced_comp_resp(pm8001_ha, piomb);
40338c2ecf20Sopenharmony_ci		break;
40348c2ecf20Sopenharmony_ci	default:
40358c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, DEVIO,
40368c2ecf20Sopenharmony_ci			   "Unknown outbound Queue IOMB OPC = 0x%x\n", opc);
40378c2ecf20Sopenharmony_ci		break;
40388c2ecf20Sopenharmony_ci	}
40398c2ecf20Sopenharmony_ci}
40408c2ecf20Sopenharmony_ci
40418c2ecf20Sopenharmony_cistatic void print_scratchpad_registers(struct pm8001_hba_info *pm8001_ha)
40428c2ecf20Sopenharmony_ci{
40438c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_0: 0x%x\n",
40448c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0));
40458c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_1:0x%x\n",
40468c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1));
40478c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_2: 0x%x\n",
40488c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2));
40498c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_3: 0x%x\n",
40508c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3));
40518c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_0: 0x%x\n",
40528c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0));
40538c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_1: 0x%x\n",
40548c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1));
40558c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_2: 0x%x\n",
40568c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2));
40578c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_3: 0x%x\n",
40588c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3));
40598c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_4: 0x%x\n",
40608c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4));
40618c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_5: 0x%x\n",
40628c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5));
40638c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n",
40648c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_6));
40658c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n",
40668c2ecf20Sopenharmony_ci		   pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7));
40678c2ecf20Sopenharmony_ci}
40688c2ecf20Sopenharmony_ci
40698c2ecf20Sopenharmony_cistatic int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
40708c2ecf20Sopenharmony_ci{
40718c2ecf20Sopenharmony_ci	struct outbound_queue_table *circularQ;
40728c2ecf20Sopenharmony_ci	void *pMsg1 = NULL;
40738c2ecf20Sopenharmony_ci	u8 bc;
40748c2ecf20Sopenharmony_ci	u32 ret = MPI_IO_STATUS_FAIL;
40758c2ecf20Sopenharmony_ci	unsigned long flags;
40768c2ecf20Sopenharmony_ci	u32 regval;
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_ci	/*
40798c2ecf20Sopenharmony_ci	 * Fatal errors are programmed to be signalled in irq vector
40808c2ecf20Sopenharmony_ci	 * pm8001_ha->max_q_num - 1 through pm8001_ha->main_cfg_tbl.pm80xx_tbl.
40818c2ecf20Sopenharmony_ci	 * fatal_err_interrupt
40828c2ecf20Sopenharmony_ci	 */
40838c2ecf20Sopenharmony_ci	if (vec == (pm8001_ha->max_q_num - 1)) {
40848c2ecf20Sopenharmony_ci		u32 mipsall_ready;
40858c2ecf20Sopenharmony_ci
40868c2ecf20Sopenharmony_ci		if (pm8001_ha->chip_id == chip_8008 ||
40878c2ecf20Sopenharmony_ci		    pm8001_ha->chip_id == chip_8009)
40888c2ecf20Sopenharmony_ci			mipsall_ready = SCRATCH_PAD_MIPSALL_READY_8PORT;
40898c2ecf20Sopenharmony_ci		else
40908c2ecf20Sopenharmony_ci			mipsall_ready = SCRATCH_PAD_MIPSALL_READY_16PORT;
40918c2ecf20Sopenharmony_ci
40928c2ecf20Sopenharmony_ci		regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
40938c2ecf20Sopenharmony_ci		if ((regval & mipsall_ready) != mipsall_ready) {
40948c2ecf20Sopenharmony_ci			pm8001_ha->controller_fatal_error = true;
40958c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, FAIL,
40968c2ecf20Sopenharmony_ci				   "Firmware Fatal error! Regval:0x%x\n",
40978c2ecf20Sopenharmony_ci				   regval);
40988c2ecf20Sopenharmony_ci			print_scratchpad_registers(pm8001_ha);
40998c2ecf20Sopenharmony_ci			return ret;
41008c2ecf20Sopenharmony_ci		}
41018c2ecf20Sopenharmony_ci	}
41028c2ecf20Sopenharmony_ci	spin_lock_irqsave(&pm8001_ha->lock, flags);
41038c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->outbnd_q_tbl[vec];
41048c2ecf20Sopenharmony_ci	do {
41058c2ecf20Sopenharmony_ci		/* spurious interrupt during setup if kexec-ing and
41068c2ecf20Sopenharmony_ci		 * driver doing a doorbell access w/ the pre-kexec oq
41078c2ecf20Sopenharmony_ci		 * interrupt setup.
41088c2ecf20Sopenharmony_ci		 */
41098c2ecf20Sopenharmony_ci		if (!circularQ->pi_virt)
41108c2ecf20Sopenharmony_ci			break;
41118c2ecf20Sopenharmony_ci		ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc);
41128c2ecf20Sopenharmony_ci		if (MPI_IO_STATUS_SUCCESS == ret) {
41138c2ecf20Sopenharmony_ci			/* process the outbound message */
41148c2ecf20Sopenharmony_ci			process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4));
41158c2ecf20Sopenharmony_ci			/* free the message from the outbound circular buffer */
41168c2ecf20Sopenharmony_ci			pm8001_mpi_msg_free_set(pm8001_ha, pMsg1,
41178c2ecf20Sopenharmony_ci							circularQ, bc);
41188c2ecf20Sopenharmony_ci		}
41198c2ecf20Sopenharmony_ci		if (MPI_IO_STATUS_BUSY == ret) {
41208c2ecf20Sopenharmony_ci			/* Update the producer index from SPC */
41218c2ecf20Sopenharmony_ci			circularQ->producer_index =
41228c2ecf20Sopenharmony_ci				cpu_to_le32(pm8001_read_32(circularQ->pi_virt));
41238c2ecf20Sopenharmony_ci			if (le32_to_cpu(circularQ->producer_index) ==
41248c2ecf20Sopenharmony_ci				circularQ->consumer_idx)
41258c2ecf20Sopenharmony_ci				/* OQ is empty */
41268c2ecf20Sopenharmony_ci				break;
41278c2ecf20Sopenharmony_ci		}
41288c2ecf20Sopenharmony_ci	} while (1);
41298c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&pm8001_ha->lock, flags);
41308c2ecf20Sopenharmony_ci	return ret;
41318c2ecf20Sopenharmony_ci}
41328c2ecf20Sopenharmony_ci
41338c2ecf20Sopenharmony_ci/* DMA_... to our direction translation. */
41348c2ecf20Sopenharmony_cistatic const u8 data_dir_flags[] = {
41358c2ecf20Sopenharmony_ci	[DMA_BIDIRECTIONAL]	= DATA_DIR_BYRECIPIENT,	/* UNSPECIFIED */
41368c2ecf20Sopenharmony_ci	[DMA_TO_DEVICE]		= DATA_DIR_OUT,		/* OUTBOUND */
41378c2ecf20Sopenharmony_ci	[DMA_FROM_DEVICE]	= DATA_DIR_IN,		/* INBOUND */
41388c2ecf20Sopenharmony_ci	[DMA_NONE]		= DATA_DIR_NONE,	/* NO TRANSFER */
41398c2ecf20Sopenharmony_ci};
41408c2ecf20Sopenharmony_ci
41418c2ecf20Sopenharmony_cistatic void build_smp_cmd(u32 deviceID, __le32 hTag,
41428c2ecf20Sopenharmony_ci			struct smp_req *psmp_cmd, int mode, int length)
41438c2ecf20Sopenharmony_ci{
41448c2ecf20Sopenharmony_ci	psmp_cmd->tag = hTag;
41458c2ecf20Sopenharmony_ci	psmp_cmd->device_id = cpu_to_le32(deviceID);
41468c2ecf20Sopenharmony_ci	if (mode == SMP_DIRECT) {
41478c2ecf20Sopenharmony_ci		length = length - 4; /* subtract crc */
41488c2ecf20Sopenharmony_ci		psmp_cmd->len_ip_ir = cpu_to_le32(length << 16);
41498c2ecf20Sopenharmony_ci	} else {
41508c2ecf20Sopenharmony_ci		psmp_cmd->len_ip_ir = cpu_to_le32(1|(1 << 1));
41518c2ecf20Sopenharmony_ci	}
41528c2ecf20Sopenharmony_ci}
41538c2ecf20Sopenharmony_ci
41548c2ecf20Sopenharmony_ci/**
41558c2ecf20Sopenharmony_ci * pm8001_chip_smp_req - send a SMP task to FW
41568c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
41578c2ecf20Sopenharmony_ci * @ccb: the ccb information this request used.
41588c2ecf20Sopenharmony_ci */
41598c2ecf20Sopenharmony_cistatic int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
41608c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb)
41618c2ecf20Sopenharmony_ci{
41628c2ecf20Sopenharmony_ci	int elem, rc;
41638c2ecf20Sopenharmony_ci	struct sas_task *task = ccb->task;
41648c2ecf20Sopenharmony_ci	struct domain_device *dev = task->dev;
41658c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev = dev->lldd_dev;
41668c2ecf20Sopenharmony_ci	struct scatterlist *sg_req, *sg_resp;
41678c2ecf20Sopenharmony_ci	u32 req_len, resp_len;
41688c2ecf20Sopenharmony_ci	struct smp_req smp_cmd;
41698c2ecf20Sopenharmony_ci	u32 opc;
41708c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
41718c2ecf20Sopenharmony_ci	char *preq_dma_addr = NULL;
41728c2ecf20Sopenharmony_ci	__le64 tmp_addr;
41738c2ecf20Sopenharmony_ci	u32 i, length;
41748c2ecf20Sopenharmony_ci
41758c2ecf20Sopenharmony_ci	memset(&smp_cmd, 0, sizeof(smp_cmd));
41768c2ecf20Sopenharmony_ci	/*
41778c2ecf20Sopenharmony_ci	 * DMA-map SMP request, response buffers
41788c2ecf20Sopenharmony_ci	 */
41798c2ecf20Sopenharmony_ci	sg_req = &task->smp_task.smp_req;
41808c2ecf20Sopenharmony_ci	elem = dma_map_sg(pm8001_ha->dev, sg_req, 1, DMA_TO_DEVICE);
41818c2ecf20Sopenharmony_ci	if (!elem)
41828c2ecf20Sopenharmony_ci		return -ENOMEM;
41838c2ecf20Sopenharmony_ci	req_len = sg_dma_len(sg_req);
41848c2ecf20Sopenharmony_ci
41858c2ecf20Sopenharmony_ci	sg_resp = &task->smp_task.smp_resp;
41868c2ecf20Sopenharmony_ci	elem = dma_map_sg(pm8001_ha->dev, sg_resp, 1, DMA_FROM_DEVICE);
41878c2ecf20Sopenharmony_ci	if (!elem) {
41888c2ecf20Sopenharmony_ci		rc = -ENOMEM;
41898c2ecf20Sopenharmony_ci		goto err_out;
41908c2ecf20Sopenharmony_ci	}
41918c2ecf20Sopenharmony_ci	resp_len = sg_dma_len(sg_resp);
41928c2ecf20Sopenharmony_ci	/* must be in dwords */
41938c2ecf20Sopenharmony_ci	if ((req_len & 0x3) || (resp_len & 0x3)) {
41948c2ecf20Sopenharmony_ci		rc = -EINVAL;
41958c2ecf20Sopenharmony_ci		goto err_out_2;
41968c2ecf20Sopenharmony_ci	}
41978c2ecf20Sopenharmony_ci
41988c2ecf20Sopenharmony_ci	opc = OPC_INB_SMP_REQUEST;
41998c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
42008c2ecf20Sopenharmony_ci	smp_cmd.tag = cpu_to_le32(ccb->ccb_tag);
42018c2ecf20Sopenharmony_ci
42028c2ecf20Sopenharmony_ci	length = sg_req->length;
42038c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, IO, "SMP Frame Length %d\n", sg_req->length);
42048c2ecf20Sopenharmony_ci	if (!(length - 8))
42058c2ecf20Sopenharmony_ci		pm8001_ha->smp_exp_mode = SMP_DIRECT;
42068c2ecf20Sopenharmony_ci	else
42078c2ecf20Sopenharmony_ci		pm8001_ha->smp_exp_mode = SMP_INDIRECT;
42088c2ecf20Sopenharmony_ci
42098c2ecf20Sopenharmony_ci
42108c2ecf20Sopenharmony_ci	tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req));
42118c2ecf20Sopenharmony_ci	preq_dma_addr = (char *)phys_to_virt(tmp_addr);
42128c2ecf20Sopenharmony_ci
42138c2ecf20Sopenharmony_ci	/* INDIRECT MODE command settings. Use DMA */
42148c2ecf20Sopenharmony_ci	if (pm8001_ha->smp_exp_mode == SMP_INDIRECT) {
42158c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "SMP REQUEST INDIRECT MODE\n");
42168c2ecf20Sopenharmony_ci		/* for SPCv indirect mode. Place the top 4 bytes of
42178c2ecf20Sopenharmony_ci		 * SMP Request header here. */
42188c2ecf20Sopenharmony_ci		for (i = 0; i < 4; i++)
42198c2ecf20Sopenharmony_ci			smp_cmd.smp_req16[i] = *(preq_dma_addr + i);
42208c2ecf20Sopenharmony_ci		/* exclude top 4 bytes for SMP req header */
42218c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_req_addr =
42228c2ecf20Sopenharmony_ci			cpu_to_le64((u64)sg_dma_address
42238c2ecf20Sopenharmony_ci				(&task->smp_task.smp_req) + 4);
42248c2ecf20Sopenharmony_ci		/* exclude 4 bytes for SMP req header and CRC */
42258c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_req_size =
42268c2ecf20Sopenharmony_ci			cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8);
42278c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_resp_addr =
42288c2ecf20Sopenharmony_ci				cpu_to_le64((u64)sg_dma_address
42298c2ecf20Sopenharmony_ci					(&task->smp_task.smp_resp));
42308c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_resp_size =
42318c2ecf20Sopenharmony_ci				cpu_to_le32((u32)sg_dma_len
42328c2ecf20Sopenharmony_ci					(&task->smp_task.smp_resp)-4);
42338c2ecf20Sopenharmony_ci	} else { /* DIRECT MODE */
42348c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_req_addr =
42358c2ecf20Sopenharmony_ci			cpu_to_le64((u64)sg_dma_address
42368c2ecf20Sopenharmony_ci					(&task->smp_task.smp_req));
42378c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_req_size =
42388c2ecf20Sopenharmony_ci			cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-4);
42398c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_resp_addr =
42408c2ecf20Sopenharmony_ci			cpu_to_le64((u64)sg_dma_address
42418c2ecf20Sopenharmony_ci				(&task->smp_task.smp_resp));
42428c2ecf20Sopenharmony_ci		smp_cmd.long_smp_req.long_resp_size =
42438c2ecf20Sopenharmony_ci			cpu_to_le32
42448c2ecf20Sopenharmony_ci			((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
42458c2ecf20Sopenharmony_ci	}
42468c2ecf20Sopenharmony_ci	if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
42478c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "SMP REQUEST DIRECT MODE\n");
42488c2ecf20Sopenharmony_ci		for (i = 0; i < length; i++)
42498c2ecf20Sopenharmony_ci			if (i < 16) {
42508c2ecf20Sopenharmony_ci				smp_cmd.smp_req16[i] = *(preq_dma_addr+i);
42518c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, IO,
42528c2ecf20Sopenharmony_ci					   "Byte[%d]:%x (DMA data:%x)\n",
42538c2ecf20Sopenharmony_ci					   i, smp_cmd.smp_req16[i],
42548c2ecf20Sopenharmony_ci					   *(preq_dma_addr));
42558c2ecf20Sopenharmony_ci			} else {
42568c2ecf20Sopenharmony_ci				smp_cmd.smp_req[i] = *(preq_dma_addr+i);
42578c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, IO,
42588c2ecf20Sopenharmony_ci					   "Byte[%d]:%x (DMA data:%x)\n",
42598c2ecf20Sopenharmony_ci					   i, smp_cmd.smp_req[i],
42608c2ecf20Sopenharmony_ci					   *(preq_dma_addr));
42618c2ecf20Sopenharmony_ci			}
42628c2ecf20Sopenharmony_ci	}
42638c2ecf20Sopenharmony_ci
42648c2ecf20Sopenharmony_ci	build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
42658c2ecf20Sopenharmony_ci				&smp_cmd, pm8001_ha->smp_exp_mode, length);
42668c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
42678c2ecf20Sopenharmony_ci			sizeof(smp_cmd), 0);
42688c2ecf20Sopenharmony_ci	if (rc)
42698c2ecf20Sopenharmony_ci		goto err_out_2;
42708c2ecf20Sopenharmony_ci	return 0;
42718c2ecf20Sopenharmony_ci
42728c2ecf20Sopenharmony_cierr_out_2:
42738c2ecf20Sopenharmony_ci	dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_resp, 1,
42748c2ecf20Sopenharmony_ci			DMA_FROM_DEVICE);
42758c2ecf20Sopenharmony_cierr_out:
42768c2ecf20Sopenharmony_ci	dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_req, 1,
42778c2ecf20Sopenharmony_ci			DMA_TO_DEVICE);
42788c2ecf20Sopenharmony_ci	return rc;
42798c2ecf20Sopenharmony_ci}
42808c2ecf20Sopenharmony_ci
42818c2ecf20Sopenharmony_cistatic int check_enc_sas_cmd(struct sas_task *task)
42828c2ecf20Sopenharmony_ci{
42838c2ecf20Sopenharmony_ci	u8 cmd = task->ssp_task.cmd->cmnd[0];
42848c2ecf20Sopenharmony_ci
42858c2ecf20Sopenharmony_ci	if (cmd == READ_10 || cmd == WRITE_10 || cmd == WRITE_VERIFY)
42868c2ecf20Sopenharmony_ci		return 1;
42878c2ecf20Sopenharmony_ci	else
42888c2ecf20Sopenharmony_ci		return 0;
42898c2ecf20Sopenharmony_ci}
42908c2ecf20Sopenharmony_ci
42918c2ecf20Sopenharmony_cistatic int check_enc_sat_cmd(struct sas_task *task)
42928c2ecf20Sopenharmony_ci{
42938c2ecf20Sopenharmony_ci	int ret = 0;
42948c2ecf20Sopenharmony_ci	switch (task->ata_task.fis.command) {
42958c2ecf20Sopenharmony_ci	case ATA_CMD_FPDMA_READ:
42968c2ecf20Sopenharmony_ci	case ATA_CMD_READ_EXT:
42978c2ecf20Sopenharmony_ci	case ATA_CMD_READ:
42988c2ecf20Sopenharmony_ci	case ATA_CMD_FPDMA_WRITE:
42998c2ecf20Sopenharmony_ci	case ATA_CMD_WRITE_EXT:
43008c2ecf20Sopenharmony_ci	case ATA_CMD_WRITE:
43018c2ecf20Sopenharmony_ci	case ATA_CMD_PIO_READ:
43028c2ecf20Sopenharmony_ci	case ATA_CMD_PIO_READ_EXT:
43038c2ecf20Sopenharmony_ci	case ATA_CMD_PIO_WRITE:
43048c2ecf20Sopenharmony_ci	case ATA_CMD_PIO_WRITE_EXT:
43058c2ecf20Sopenharmony_ci		ret = 1;
43068c2ecf20Sopenharmony_ci		break;
43078c2ecf20Sopenharmony_ci	default:
43088c2ecf20Sopenharmony_ci		ret = 0;
43098c2ecf20Sopenharmony_ci		break;
43108c2ecf20Sopenharmony_ci	}
43118c2ecf20Sopenharmony_ci	return ret;
43128c2ecf20Sopenharmony_ci}
43138c2ecf20Sopenharmony_ci
43148c2ecf20Sopenharmony_ci/**
43158c2ecf20Sopenharmony_ci * pm80xx_chip_ssp_io_req - send a SSP task to FW
43168c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
43178c2ecf20Sopenharmony_ci * @ccb: the ccb information this request used.
43188c2ecf20Sopenharmony_ci */
43198c2ecf20Sopenharmony_cistatic int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
43208c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb)
43218c2ecf20Sopenharmony_ci{
43228c2ecf20Sopenharmony_ci	struct sas_task *task = ccb->task;
43238c2ecf20Sopenharmony_ci	struct domain_device *dev = task->dev;
43248c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev = dev->lldd_dev;
43258c2ecf20Sopenharmony_ci	struct ssp_ini_io_start_req ssp_cmd;
43268c2ecf20Sopenharmony_ci	u32 tag = ccb->ccb_tag;
43278c2ecf20Sopenharmony_ci	int ret;
43288c2ecf20Sopenharmony_ci	u64 phys_addr, end_addr;
43298c2ecf20Sopenharmony_ci	u32 end_addr_high, end_addr_low;
43308c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
43318c2ecf20Sopenharmony_ci	u32 q_index, cpu_id;
43328c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SSPINIIOSTART;
43338c2ecf20Sopenharmony_ci
43348c2ecf20Sopenharmony_ci	memset(&ssp_cmd, 0, sizeof(ssp_cmd));
43358c2ecf20Sopenharmony_ci	memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
43368c2ecf20Sopenharmony_ci
43378c2ecf20Sopenharmony_ci	/* data address domain added for spcv; set to 0 by host,
43388c2ecf20Sopenharmony_ci	 * used internally by controller
43398c2ecf20Sopenharmony_ci	 * 0 for SAS 1.1 and SAS 2.0 compatible TLR
43408c2ecf20Sopenharmony_ci	 */
43418c2ecf20Sopenharmony_ci	ssp_cmd.dad_dir_m_tlr =
43428c2ecf20Sopenharmony_ci		cpu_to_le32(data_dir_flags[task->data_dir] << 8 | 0x0);
43438c2ecf20Sopenharmony_ci	ssp_cmd.data_len = cpu_to_le32(task->total_xfer_len);
43448c2ecf20Sopenharmony_ci	ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);
43458c2ecf20Sopenharmony_ci	ssp_cmd.tag = cpu_to_le32(tag);
43468c2ecf20Sopenharmony_ci	if (task->ssp_task.enable_first_burst)
43478c2ecf20Sopenharmony_ci		ssp_cmd.ssp_iu.efb_prio_attr = 0x80;
43488c2ecf20Sopenharmony_ci	ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3);
43498c2ecf20Sopenharmony_ci	ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
43508c2ecf20Sopenharmony_ci	memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
43518c2ecf20Sopenharmony_ci		       task->ssp_task.cmd->cmd_len);
43528c2ecf20Sopenharmony_ci	cpu_id = smp_processor_id();
43538c2ecf20Sopenharmony_ci	q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
43548c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
43558c2ecf20Sopenharmony_ci
43568c2ecf20Sopenharmony_ci	/* Check if encryption is set */
43578c2ecf20Sopenharmony_ci	if (pm8001_ha->chip->encrypt &&
43588c2ecf20Sopenharmony_ci		!(pm8001_ha->encrypt_info.status) && check_enc_sas_cmd(task)) {
43598c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
43608c2ecf20Sopenharmony_ci			   "Encryption enabled.Sending Encrypt SAS command 0x%x\n",
43618c2ecf20Sopenharmony_ci			   task->ssp_task.cmd->cmnd[0]);
43628c2ecf20Sopenharmony_ci		opc = OPC_INB_SSP_INI_DIF_ENC_IO;
43638c2ecf20Sopenharmony_ci		/* enable encryption. 0 for SAS 1.1 and SAS 2.0 compatible TLR*/
43648c2ecf20Sopenharmony_ci		ssp_cmd.dad_dir_m_tlr =	cpu_to_le32
43658c2ecf20Sopenharmony_ci			((data_dir_flags[task->data_dir] << 8) | 0x20 | 0x0);
43668c2ecf20Sopenharmony_ci
43678c2ecf20Sopenharmony_ci		/* fill in PRD (scatter/gather) table, if any */
43688c2ecf20Sopenharmony_ci		if (task->num_scatter > 1) {
43698c2ecf20Sopenharmony_ci			pm8001_chip_make_sg(task->scatter,
43708c2ecf20Sopenharmony_ci						ccb->n_elem, ccb->buf_prd);
43718c2ecf20Sopenharmony_ci			phys_addr = ccb->ccb_dma_handle;
43728c2ecf20Sopenharmony_ci			ssp_cmd.enc_addr_low =
43738c2ecf20Sopenharmony_ci				cpu_to_le32(lower_32_bits(phys_addr));
43748c2ecf20Sopenharmony_ci			ssp_cmd.enc_addr_high =
43758c2ecf20Sopenharmony_ci				cpu_to_le32(upper_32_bits(phys_addr));
43768c2ecf20Sopenharmony_ci			ssp_cmd.enc_esgl = cpu_to_le32(1<<31);
43778c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 1) {
43788c2ecf20Sopenharmony_ci			u64 dma_addr = sg_dma_address(task->scatter);
43798c2ecf20Sopenharmony_ci
43808c2ecf20Sopenharmony_ci			ssp_cmd.enc_addr_low =
43818c2ecf20Sopenharmony_ci				cpu_to_le32(lower_32_bits(dma_addr));
43828c2ecf20Sopenharmony_ci			ssp_cmd.enc_addr_high =
43838c2ecf20Sopenharmony_ci				cpu_to_le32(upper_32_bits(dma_addr));
43848c2ecf20Sopenharmony_ci			ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
43858c2ecf20Sopenharmony_ci			ssp_cmd.enc_esgl = 0;
43868c2ecf20Sopenharmony_ci
43878c2ecf20Sopenharmony_ci			/* Check 4G Boundary */
43888c2ecf20Sopenharmony_ci			end_addr = dma_addr + le32_to_cpu(ssp_cmd.enc_len) - 1;
43898c2ecf20Sopenharmony_ci			end_addr_low = lower_32_bits(end_addr);
43908c2ecf20Sopenharmony_ci			end_addr_high = upper_32_bits(end_addr);
43918c2ecf20Sopenharmony_ci
43928c2ecf20Sopenharmony_ci			if (end_addr_high != le32_to_cpu(ssp_cmd.enc_addr_high)) {
43938c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
43948c2ecf20Sopenharmony_ci					   "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",
43958c2ecf20Sopenharmony_ci					   dma_addr,
43968c2ecf20Sopenharmony_ci					   le32_to_cpu(ssp_cmd.enc_len),
43978c2ecf20Sopenharmony_ci					   end_addr_high, end_addr_low);
43988c2ecf20Sopenharmony_ci				pm8001_chip_make_sg(task->scatter, 1,
43998c2ecf20Sopenharmony_ci					ccb->buf_prd);
44008c2ecf20Sopenharmony_ci				phys_addr = ccb->ccb_dma_handle;
44018c2ecf20Sopenharmony_ci				ssp_cmd.enc_addr_low =
44028c2ecf20Sopenharmony_ci					cpu_to_le32(lower_32_bits(phys_addr));
44038c2ecf20Sopenharmony_ci				ssp_cmd.enc_addr_high =
44048c2ecf20Sopenharmony_ci					cpu_to_le32(upper_32_bits(phys_addr));
44058c2ecf20Sopenharmony_ci				ssp_cmd.enc_esgl = cpu_to_le32(1U<<31);
44068c2ecf20Sopenharmony_ci			}
44078c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 0) {
44088c2ecf20Sopenharmony_ci			ssp_cmd.enc_addr_low = 0;
44098c2ecf20Sopenharmony_ci			ssp_cmd.enc_addr_high = 0;
44108c2ecf20Sopenharmony_ci			ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
44118c2ecf20Sopenharmony_ci			ssp_cmd.enc_esgl = 0;
44128c2ecf20Sopenharmony_ci		}
44138c2ecf20Sopenharmony_ci
44148c2ecf20Sopenharmony_ci		/* XTS mode. All other fields are 0 */
44158c2ecf20Sopenharmony_ci		ssp_cmd.key_cmode = cpu_to_le32(0x6 << 4);
44168c2ecf20Sopenharmony_ci
44178c2ecf20Sopenharmony_ci		/* set tweak values. Should be the start lba */
44188c2ecf20Sopenharmony_ci		ssp_cmd.twk_val0 = cpu_to_le32((task->ssp_task.cmd->cmnd[2] << 24) |
44198c2ecf20Sopenharmony_ci						(task->ssp_task.cmd->cmnd[3] << 16) |
44208c2ecf20Sopenharmony_ci						(task->ssp_task.cmd->cmnd[4] << 8) |
44218c2ecf20Sopenharmony_ci						(task->ssp_task.cmd->cmnd[5]));
44228c2ecf20Sopenharmony_ci	} else {
44238c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
44248c2ecf20Sopenharmony_ci			   "Sending Normal SAS command 0x%x inb q %x\n",
44258c2ecf20Sopenharmony_ci			   task->ssp_task.cmd->cmnd[0], q_index);
44268c2ecf20Sopenharmony_ci		/* fill in PRD (scatter/gather) table, if any */
44278c2ecf20Sopenharmony_ci		if (task->num_scatter > 1) {
44288c2ecf20Sopenharmony_ci			pm8001_chip_make_sg(task->scatter, ccb->n_elem,
44298c2ecf20Sopenharmony_ci					ccb->buf_prd);
44308c2ecf20Sopenharmony_ci			phys_addr = ccb->ccb_dma_handle;
44318c2ecf20Sopenharmony_ci			ssp_cmd.addr_low =
44328c2ecf20Sopenharmony_ci				cpu_to_le32(lower_32_bits(phys_addr));
44338c2ecf20Sopenharmony_ci			ssp_cmd.addr_high =
44348c2ecf20Sopenharmony_ci				cpu_to_le32(upper_32_bits(phys_addr));
44358c2ecf20Sopenharmony_ci			ssp_cmd.esgl = cpu_to_le32(1<<31);
44368c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 1) {
44378c2ecf20Sopenharmony_ci			u64 dma_addr = sg_dma_address(task->scatter);
44388c2ecf20Sopenharmony_ci
44398c2ecf20Sopenharmony_ci			ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr));
44408c2ecf20Sopenharmony_ci			ssp_cmd.addr_high =
44418c2ecf20Sopenharmony_ci				cpu_to_le32(upper_32_bits(dma_addr));
44428c2ecf20Sopenharmony_ci			ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
44438c2ecf20Sopenharmony_ci			ssp_cmd.esgl = 0;
44448c2ecf20Sopenharmony_ci
44458c2ecf20Sopenharmony_ci			/* Check 4G Boundary */
44468c2ecf20Sopenharmony_ci			end_addr = dma_addr + le32_to_cpu(ssp_cmd.len) - 1;
44478c2ecf20Sopenharmony_ci			end_addr_low = lower_32_bits(end_addr);
44488c2ecf20Sopenharmony_ci			end_addr_high = upper_32_bits(end_addr);
44498c2ecf20Sopenharmony_ci			if (end_addr_high != le32_to_cpu(ssp_cmd.addr_high)) {
44508c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
44518c2ecf20Sopenharmony_ci					   "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",
44528c2ecf20Sopenharmony_ci					   dma_addr,
44538c2ecf20Sopenharmony_ci					   le32_to_cpu(ssp_cmd.len),
44548c2ecf20Sopenharmony_ci					   end_addr_high, end_addr_low);
44558c2ecf20Sopenharmony_ci				pm8001_chip_make_sg(task->scatter, 1,
44568c2ecf20Sopenharmony_ci					ccb->buf_prd);
44578c2ecf20Sopenharmony_ci				phys_addr = ccb->ccb_dma_handle;
44588c2ecf20Sopenharmony_ci				ssp_cmd.addr_low =
44598c2ecf20Sopenharmony_ci					cpu_to_le32(lower_32_bits(phys_addr));
44608c2ecf20Sopenharmony_ci				ssp_cmd.addr_high =
44618c2ecf20Sopenharmony_ci					cpu_to_le32(upper_32_bits(phys_addr));
44628c2ecf20Sopenharmony_ci				ssp_cmd.esgl = cpu_to_le32(1<<31);
44638c2ecf20Sopenharmony_ci			}
44648c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 0) {
44658c2ecf20Sopenharmony_ci			ssp_cmd.addr_low = 0;
44668c2ecf20Sopenharmony_ci			ssp_cmd.addr_high = 0;
44678c2ecf20Sopenharmony_ci			ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
44688c2ecf20Sopenharmony_ci			ssp_cmd.esgl = 0;
44698c2ecf20Sopenharmony_ci		}
44708c2ecf20Sopenharmony_ci	}
44718c2ecf20Sopenharmony_ci	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
44728c2ecf20Sopenharmony_ci			&ssp_cmd, sizeof(ssp_cmd), q_index);
44738c2ecf20Sopenharmony_ci	return ret;
44748c2ecf20Sopenharmony_ci}
44758c2ecf20Sopenharmony_ci
44768c2ecf20Sopenharmony_cistatic int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
44778c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb)
44788c2ecf20Sopenharmony_ci{
44798c2ecf20Sopenharmony_ci	struct sas_task *task = ccb->task;
44808c2ecf20Sopenharmony_ci	struct domain_device *dev = task->dev;
44818c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
44828c2ecf20Sopenharmony_ci	u32 tag = ccb->ccb_tag;
44838c2ecf20Sopenharmony_ci	int ret;
44848c2ecf20Sopenharmony_ci	u32 q_index, cpu_id;
44858c2ecf20Sopenharmony_ci	struct sata_start_req sata_cmd;
44868c2ecf20Sopenharmony_ci	u32 hdr_tag, ncg_tag = 0;
44878c2ecf20Sopenharmony_ci	u64 phys_addr, end_addr;
44888c2ecf20Sopenharmony_ci	u32 end_addr_high, end_addr_low;
44898c2ecf20Sopenharmony_ci	u32 ATAP = 0x0;
44908c2ecf20Sopenharmony_ci	u32 dir;
44918c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
44928c2ecf20Sopenharmony_ci	unsigned long flags;
44938c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SATA_HOST_OPSTART;
44948c2ecf20Sopenharmony_ci	memset(&sata_cmd, 0, sizeof(sata_cmd));
44958c2ecf20Sopenharmony_ci	cpu_id = smp_processor_id();
44968c2ecf20Sopenharmony_ci	q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
44978c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
44988c2ecf20Sopenharmony_ci
44998c2ecf20Sopenharmony_ci	if (task->data_dir == DMA_NONE && !task->ata_task.use_ncq) {
45008c2ecf20Sopenharmony_ci		ATAP = 0x04; /* no data*/
45018c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO, "no data\n");
45028c2ecf20Sopenharmony_ci	} else if (likely(!task->ata_task.device_control_reg_update)) {
45038c2ecf20Sopenharmony_ci		if (task->ata_task.use_ncq &&
45048c2ecf20Sopenharmony_ci		    dev->sata_dev.class != ATA_DEV_ATAPI) {
45058c2ecf20Sopenharmony_ci			ATAP = 0x07; /* FPDMA */
45068c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
45078c2ecf20Sopenharmony_ci		} else if (task->ata_task.dma_xfer) {
45088c2ecf20Sopenharmony_ci			ATAP = 0x06; /* DMA */
45098c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, IO, "DMA\n");
45108c2ecf20Sopenharmony_ci		} else {
45118c2ecf20Sopenharmony_ci			ATAP = 0x05; /* PIO*/
45128c2ecf20Sopenharmony_ci			pm8001_dbg(pm8001_ha, IO, "PIO\n");
45138c2ecf20Sopenharmony_ci		}
45148c2ecf20Sopenharmony_ci	}
45158c2ecf20Sopenharmony_ci	if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
45168c2ecf20Sopenharmony_ci		task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
45178c2ecf20Sopenharmony_ci		ncg_tag = hdr_tag;
45188c2ecf20Sopenharmony_ci	}
45198c2ecf20Sopenharmony_ci	dir = data_dir_flags[task->data_dir] << 8;
45208c2ecf20Sopenharmony_ci	sata_cmd.tag = cpu_to_le32(tag);
45218c2ecf20Sopenharmony_ci	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
45228c2ecf20Sopenharmony_ci	sata_cmd.data_len = cpu_to_le32(task->total_xfer_len);
45238c2ecf20Sopenharmony_ci
45248c2ecf20Sopenharmony_ci	sata_cmd.sata_fis = task->ata_task.fis;
45258c2ecf20Sopenharmony_ci	if (likely(!task->ata_task.device_control_reg_update))
45268c2ecf20Sopenharmony_ci		sata_cmd.sata_fis.flags |= 0x80;/* C=1: update ATA cmd reg */
45278c2ecf20Sopenharmony_ci	sata_cmd.sata_fis.flags &= 0xF0;/* PM_PORT field shall be 0 */
45288c2ecf20Sopenharmony_ci
45298c2ecf20Sopenharmony_ci	/* Check if encryption is set */
45308c2ecf20Sopenharmony_ci	if (pm8001_ha->chip->encrypt &&
45318c2ecf20Sopenharmony_ci		!(pm8001_ha->encrypt_info.status) && check_enc_sat_cmd(task)) {
45328c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
45338c2ecf20Sopenharmony_ci			   "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n",
45348c2ecf20Sopenharmony_ci			   sata_cmd.sata_fis.command);
45358c2ecf20Sopenharmony_ci		opc = OPC_INB_SATA_DIF_ENC_IO;
45368c2ecf20Sopenharmony_ci
45378c2ecf20Sopenharmony_ci		/* set encryption bit */
45388c2ecf20Sopenharmony_ci		sata_cmd.ncqtag_atap_dir_m_dad =
45398c2ecf20Sopenharmony_ci			cpu_to_le32(((ncg_tag & 0xff)<<16)|
45408c2ecf20Sopenharmony_ci				((ATAP & 0x3f) << 10) | 0x20 | dir);
45418c2ecf20Sopenharmony_ci							/* dad (bit 0-1) is 0 */
45428c2ecf20Sopenharmony_ci		/* fill in PRD (scatter/gather) table, if any */
45438c2ecf20Sopenharmony_ci		if (task->num_scatter > 1) {
45448c2ecf20Sopenharmony_ci			pm8001_chip_make_sg(task->scatter,
45458c2ecf20Sopenharmony_ci						ccb->n_elem, ccb->buf_prd);
45468c2ecf20Sopenharmony_ci			phys_addr = ccb->ccb_dma_handle;
45478c2ecf20Sopenharmony_ci			sata_cmd.enc_addr_low =
45488c2ecf20Sopenharmony_ci				cpu_to_le32(lower_32_bits(phys_addr));
45498c2ecf20Sopenharmony_ci			sata_cmd.enc_addr_high =
45508c2ecf20Sopenharmony_ci				cpu_to_le32(upper_32_bits(phys_addr));
45518c2ecf20Sopenharmony_ci			sata_cmd.enc_esgl = cpu_to_le32(1 << 31);
45528c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 1) {
45538c2ecf20Sopenharmony_ci			u64 dma_addr = sg_dma_address(task->scatter);
45548c2ecf20Sopenharmony_ci
45558c2ecf20Sopenharmony_ci			sata_cmd.enc_addr_low =
45568c2ecf20Sopenharmony_ci				cpu_to_le32(lower_32_bits(dma_addr));
45578c2ecf20Sopenharmony_ci			sata_cmd.enc_addr_high =
45588c2ecf20Sopenharmony_ci				cpu_to_le32(upper_32_bits(dma_addr));
45598c2ecf20Sopenharmony_ci			sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
45608c2ecf20Sopenharmony_ci			sata_cmd.enc_esgl = 0;
45618c2ecf20Sopenharmony_ci
45628c2ecf20Sopenharmony_ci			/* Check 4G Boundary */
45638c2ecf20Sopenharmony_ci			end_addr = dma_addr + le32_to_cpu(sata_cmd.enc_len) - 1;
45648c2ecf20Sopenharmony_ci			end_addr_low = lower_32_bits(end_addr);
45658c2ecf20Sopenharmony_ci			end_addr_high = upper_32_bits(end_addr);
45668c2ecf20Sopenharmony_ci			if (end_addr_high != le32_to_cpu(sata_cmd.enc_addr_high)) {
45678c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
45688c2ecf20Sopenharmony_ci					   "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",
45698c2ecf20Sopenharmony_ci					   dma_addr,
45708c2ecf20Sopenharmony_ci					   le32_to_cpu(sata_cmd.enc_len),
45718c2ecf20Sopenharmony_ci					   end_addr_high, end_addr_low);
45728c2ecf20Sopenharmony_ci				pm8001_chip_make_sg(task->scatter, 1,
45738c2ecf20Sopenharmony_ci					ccb->buf_prd);
45748c2ecf20Sopenharmony_ci				phys_addr = ccb->ccb_dma_handle;
45758c2ecf20Sopenharmony_ci				sata_cmd.enc_addr_low =
45768c2ecf20Sopenharmony_ci					cpu_to_le32(lower_32_bits(phys_addr));
45778c2ecf20Sopenharmony_ci				sata_cmd.enc_addr_high =
45788c2ecf20Sopenharmony_ci					cpu_to_le32(upper_32_bits(phys_addr));
45798c2ecf20Sopenharmony_ci				sata_cmd.enc_esgl =
45808c2ecf20Sopenharmony_ci					cpu_to_le32(1 << 31);
45818c2ecf20Sopenharmony_ci			}
45828c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 0) {
45838c2ecf20Sopenharmony_ci			sata_cmd.enc_addr_low = 0;
45848c2ecf20Sopenharmony_ci			sata_cmd.enc_addr_high = 0;
45858c2ecf20Sopenharmony_ci			sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len);
45868c2ecf20Sopenharmony_ci			sata_cmd.enc_esgl = 0;
45878c2ecf20Sopenharmony_ci		}
45888c2ecf20Sopenharmony_ci		/* XTS mode. All other fields are 0 */
45898c2ecf20Sopenharmony_ci		sata_cmd.key_index_mode = cpu_to_le32(0x6 << 4);
45908c2ecf20Sopenharmony_ci
45918c2ecf20Sopenharmony_ci		/* set tweak values. Should be the start lba */
45928c2ecf20Sopenharmony_ci		sata_cmd.twk_val0 =
45938c2ecf20Sopenharmony_ci			cpu_to_le32((sata_cmd.sata_fis.lbal_exp << 24) |
45948c2ecf20Sopenharmony_ci					(sata_cmd.sata_fis.lbah << 16) |
45958c2ecf20Sopenharmony_ci					(sata_cmd.sata_fis.lbam << 8) |
45968c2ecf20Sopenharmony_ci					(sata_cmd.sata_fis.lbal));
45978c2ecf20Sopenharmony_ci		sata_cmd.twk_val1 =
45988c2ecf20Sopenharmony_ci			cpu_to_le32((sata_cmd.sata_fis.lbah_exp << 8) |
45998c2ecf20Sopenharmony_ci					 (sata_cmd.sata_fis.lbam_exp));
46008c2ecf20Sopenharmony_ci	} else {
46018c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, IO,
46028c2ecf20Sopenharmony_ci			   "Sending Normal SATA command 0x%x inb %x\n",
46038c2ecf20Sopenharmony_ci			   sata_cmd.sata_fis.command, q_index);
46048c2ecf20Sopenharmony_ci		/* dad (bit 0-1) is 0 */
46058c2ecf20Sopenharmony_ci		sata_cmd.ncqtag_atap_dir_m_dad =
46068c2ecf20Sopenharmony_ci			cpu_to_le32(((ncg_tag & 0xff)<<16) |
46078c2ecf20Sopenharmony_ci					((ATAP & 0x3f) << 10) | dir);
46088c2ecf20Sopenharmony_ci
46098c2ecf20Sopenharmony_ci		/* fill in PRD (scatter/gather) table, if any */
46108c2ecf20Sopenharmony_ci		if (task->num_scatter > 1) {
46118c2ecf20Sopenharmony_ci			pm8001_chip_make_sg(task->scatter,
46128c2ecf20Sopenharmony_ci					ccb->n_elem, ccb->buf_prd);
46138c2ecf20Sopenharmony_ci			phys_addr = ccb->ccb_dma_handle;
46148c2ecf20Sopenharmony_ci			sata_cmd.addr_low = lower_32_bits(phys_addr);
46158c2ecf20Sopenharmony_ci			sata_cmd.addr_high = upper_32_bits(phys_addr);
46168c2ecf20Sopenharmony_ci			sata_cmd.esgl = cpu_to_le32(1U << 31);
46178c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 1) {
46188c2ecf20Sopenharmony_ci			u64 dma_addr = sg_dma_address(task->scatter);
46198c2ecf20Sopenharmony_ci
46208c2ecf20Sopenharmony_ci			sata_cmd.addr_low = lower_32_bits(dma_addr);
46218c2ecf20Sopenharmony_ci			sata_cmd.addr_high = upper_32_bits(dma_addr);
46228c2ecf20Sopenharmony_ci			sata_cmd.len = cpu_to_le32(task->total_xfer_len);
46238c2ecf20Sopenharmony_ci			sata_cmd.esgl = 0;
46248c2ecf20Sopenharmony_ci
46258c2ecf20Sopenharmony_ci			/* Check 4G Boundary */
46268c2ecf20Sopenharmony_ci			end_addr = dma_addr + le32_to_cpu(sata_cmd.len) - 1;
46278c2ecf20Sopenharmony_ci			end_addr_low = lower_32_bits(end_addr);
46288c2ecf20Sopenharmony_ci			end_addr_high = upper_32_bits(end_addr);
46298c2ecf20Sopenharmony_ci			if (end_addr_high != sata_cmd.addr_high) {
46308c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
46318c2ecf20Sopenharmony_ci					   "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",
46328c2ecf20Sopenharmony_ci					   dma_addr,
46338c2ecf20Sopenharmony_ci					   le32_to_cpu(sata_cmd.len),
46348c2ecf20Sopenharmony_ci					   end_addr_high, end_addr_low);
46358c2ecf20Sopenharmony_ci				pm8001_chip_make_sg(task->scatter, 1,
46368c2ecf20Sopenharmony_ci					ccb->buf_prd);
46378c2ecf20Sopenharmony_ci				phys_addr = ccb->ccb_dma_handle;
46388c2ecf20Sopenharmony_ci				sata_cmd.addr_low = lower_32_bits(phys_addr);
46398c2ecf20Sopenharmony_ci				sata_cmd.addr_high = upper_32_bits(phys_addr);
46408c2ecf20Sopenharmony_ci				sata_cmd.esgl = cpu_to_le32(1U << 31);
46418c2ecf20Sopenharmony_ci			}
46428c2ecf20Sopenharmony_ci		} else if (task->num_scatter == 0) {
46438c2ecf20Sopenharmony_ci			sata_cmd.addr_low = 0;
46448c2ecf20Sopenharmony_ci			sata_cmd.addr_high = 0;
46458c2ecf20Sopenharmony_ci			sata_cmd.len = cpu_to_le32(task->total_xfer_len);
46468c2ecf20Sopenharmony_ci			sata_cmd.esgl = 0;
46478c2ecf20Sopenharmony_ci		}
46488c2ecf20Sopenharmony_ci
46498c2ecf20Sopenharmony_ci		/* scsi cdb */
46508c2ecf20Sopenharmony_ci		sata_cmd.atapi_scsi_cdb[0] =
46518c2ecf20Sopenharmony_ci			cpu_to_le32(((task->ata_task.atapi_packet[0]) |
46528c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[1] << 8) |
46538c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[2] << 16) |
46548c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[3] << 24)));
46558c2ecf20Sopenharmony_ci		sata_cmd.atapi_scsi_cdb[1] =
46568c2ecf20Sopenharmony_ci			cpu_to_le32(((task->ata_task.atapi_packet[4]) |
46578c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[5] << 8) |
46588c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[6] << 16) |
46598c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[7] << 24)));
46608c2ecf20Sopenharmony_ci		sata_cmd.atapi_scsi_cdb[2] =
46618c2ecf20Sopenharmony_ci			cpu_to_le32(((task->ata_task.atapi_packet[8]) |
46628c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[9] << 8) |
46638c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[10] << 16) |
46648c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[11] << 24)));
46658c2ecf20Sopenharmony_ci		sata_cmd.atapi_scsi_cdb[3] =
46668c2ecf20Sopenharmony_ci			cpu_to_le32(((task->ata_task.atapi_packet[12]) |
46678c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[13] << 8) |
46688c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[14] << 16) |
46698c2ecf20Sopenharmony_ci				     (task->ata_task.atapi_packet[15] << 24)));
46708c2ecf20Sopenharmony_ci	}
46718c2ecf20Sopenharmony_ci
46728c2ecf20Sopenharmony_ci	/* Check for read log for failed drive and return */
46738c2ecf20Sopenharmony_ci	if (sata_cmd.sata_fis.command == 0x2f) {
46748c2ecf20Sopenharmony_ci		if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) ||
46758c2ecf20Sopenharmony_ci			(pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
46768c2ecf20Sopenharmony_ci			(pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {
46778c2ecf20Sopenharmony_ci			struct task_status_struct *ts;
46788c2ecf20Sopenharmony_ci
46798c2ecf20Sopenharmony_ci			pm8001_ha_dev->id &= 0xDFFFFFFF;
46808c2ecf20Sopenharmony_ci			ts = &task->task_status;
46818c2ecf20Sopenharmony_ci
46828c2ecf20Sopenharmony_ci			spin_lock_irqsave(&task->task_state_lock, flags);
46838c2ecf20Sopenharmony_ci			ts->resp = SAS_TASK_COMPLETE;
46848c2ecf20Sopenharmony_ci			ts->stat = SAS_SAM_STAT_GOOD;
46858c2ecf20Sopenharmony_ci			task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
46868c2ecf20Sopenharmony_ci			task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
46878c2ecf20Sopenharmony_ci			task->task_state_flags |= SAS_TASK_STATE_DONE;
46888c2ecf20Sopenharmony_ci			if (unlikely((task->task_state_flags &
46898c2ecf20Sopenharmony_ci					SAS_TASK_STATE_ABORTED))) {
46908c2ecf20Sopenharmony_ci				spin_unlock_irqrestore(&task->task_state_lock,
46918c2ecf20Sopenharmony_ci							flags);
46928c2ecf20Sopenharmony_ci				pm8001_dbg(pm8001_ha, FAIL,
46938c2ecf20Sopenharmony_ci					   "task 0x%p resp 0x%x  stat 0x%x but aborted by upper layer\n",
46948c2ecf20Sopenharmony_ci					   task, ts->resp,
46958c2ecf20Sopenharmony_ci					   ts->stat);
46968c2ecf20Sopenharmony_ci				pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
46978c2ecf20Sopenharmony_ci				return 0;
46988c2ecf20Sopenharmony_ci			} else {
46998c2ecf20Sopenharmony_ci				spin_unlock_irqrestore(&task->task_state_lock,
47008c2ecf20Sopenharmony_ci							flags);
47018c2ecf20Sopenharmony_ci				pm8001_ccb_task_free_done(pm8001_ha, task,
47028c2ecf20Sopenharmony_ci								ccb, tag);
47038c2ecf20Sopenharmony_ci				atomic_dec(&pm8001_ha_dev->running_req);
47048c2ecf20Sopenharmony_ci				return 0;
47058c2ecf20Sopenharmony_ci			}
47068c2ecf20Sopenharmony_ci		}
47078c2ecf20Sopenharmony_ci	}
47088c2ecf20Sopenharmony_ci	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
47098c2ecf20Sopenharmony_ci			&sata_cmd, sizeof(sata_cmd), q_index);
47108c2ecf20Sopenharmony_ci	return ret;
47118c2ecf20Sopenharmony_ci}
47128c2ecf20Sopenharmony_ci
47138c2ecf20Sopenharmony_ci/**
47148c2ecf20Sopenharmony_ci * pm80xx_chip_phy_start_req - start phy via PHY_START COMMAND
47158c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
47168c2ecf20Sopenharmony_ci * @phy_id: the phy id which we wanted to start up.
47178c2ecf20Sopenharmony_ci */
47188c2ecf20Sopenharmony_cistatic int
47198c2ecf20Sopenharmony_cipm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
47208c2ecf20Sopenharmony_ci{
47218c2ecf20Sopenharmony_ci	struct phy_start_req payload;
47228c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
47238c2ecf20Sopenharmony_ci	int ret;
47248c2ecf20Sopenharmony_ci	u32 tag = 0x01;
47258c2ecf20Sopenharmony_ci	u32 opcode = OPC_INB_PHYSTART;
47268c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
47278c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(payload));
47288c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
47298c2ecf20Sopenharmony_ci
47308c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "PHY START REQ for phy_id %d\n", phy_id);
47318c2ecf20Sopenharmony_ci
47328c2ecf20Sopenharmony_ci	payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
47338c2ecf20Sopenharmony_ci			LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);
47348c2ecf20Sopenharmony_ci	/* SSC Disable and SAS Analog ST configuration */
47358c2ecf20Sopenharmony_ci	/**
47368c2ecf20Sopenharmony_ci	payload.ase_sh_lm_slr_phyid =
47378c2ecf20Sopenharmony_ci		cpu_to_le32(SSC_DISABLE_30 | SAS_ASE | SPINHOLD_DISABLE |
47388c2ecf20Sopenharmony_ci		LINKMODE_AUTO | LINKRATE_15 | LINKRATE_30 | LINKRATE_60 |
47398c2ecf20Sopenharmony_ci		phy_id);
47408c2ecf20Sopenharmony_ci	Have to add "SAS PHY Analog Setup SPASTI 1 Byte" Based on need
47418c2ecf20Sopenharmony_ci	**/
47428c2ecf20Sopenharmony_ci
47438c2ecf20Sopenharmony_ci	payload.sas_identify.dev_type = SAS_END_DEVICE;
47448c2ecf20Sopenharmony_ci	payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
47458c2ecf20Sopenharmony_ci	memcpy(payload.sas_identify.sas_addr,
47468c2ecf20Sopenharmony_ci		&pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
47478c2ecf20Sopenharmony_ci	payload.sas_identify.phy_id = phy_id;
47488c2ecf20Sopenharmony_ci	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
47498c2ecf20Sopenharmony_ci			sizeof(payload), 0);
47508c2ecf20Sopenharmony_ci	return ret;
47518c2ecf20Sopenharmony_ci}
47528c2ecf20Sopenharmony_ci
47538c2ecf20Sopenharmony_ci/**
47548c2ecf20Sopenharmony_ci * pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND
47558c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
47568c2ecf20Sopenharmony_ci * @phy_id: the phy id which we wanted to start up.
47578c2ecf20Sopenharmony_ci */
47588c2ecf20Sopenharmony_cistatic int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
47598c2ecf20Sopenharmony_ci	u8 phy_id)
47608c2ecf20Sopenharmony_ci{
47618c2ecf20Sopenharmony_ci	struct phy_stop_req payload;
47628c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
47638c2ecf20Sopenharmony_ci	int ret;
47648c2ecf20Sopenharmony_ci	u32 tag = 0x01;
47658c2ecf20Sopenharmony_ci	u32 opcode = OPC_INB_PHYSTOP;
47668c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
47678c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(payload));
47688c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
47698c2ecf20Sopenharmony_ci	payload.phy_id = cpu_to_le32(phy_id);
47708c2ecf20Sopenharmony_ci	ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
47718c2ecf20Sopenharmony_ci			sizeof(payload), 0);
47728c2ecf20Sopenharmony_ci	return ret;
47738c2ecf20Sopenharmony_ci}
47748c2ecf20Sopenharmony_ci
47758c2ecf20Sopenharmony_ci/*
47768c2ecf20Sopenharmony_ci * see comments on pm8001_mpi_reg_resp.
47778c2ecf20Sopenharmony_ci */
47788c2ecf20Sopenharmony_cistatic int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
47798c2ecf20Sopenharmony_ci	struct pm8001_device *pm8001_dev, u32 flag)
47808c2ecf20Sopenharmony_ci{
47818c2ecf20Sopenharmony_ci	struct reg_dev_req payload;
47828c2ecf20Sopenharmony_ci	u32	opc;
47838c2ecf20Sopenharmony_ci	u32 stp_sspsmp_sata = 0x4;
47848c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
47858c2ecf20Sopenharmony_ci	u32 linkrate, phy_id;
47868c2ecf20Sopenharmony_ci	int rc, tag = 0xdeadbeef;
47878c2ecf20Sopenharmony_ci	struct pm8001_ccb_info *ccb;
47888c2ecf20Sopenharmony_ci	u8 retryFlag = 0x1;
47898c2ecf20Sopenharmony_ci	u16 firstBurstSize = 0;
47908c2ecf20Sopenharmony_ci	u16 ITNT = 2000;
47918c2ecf20Sopenharmony_ci	struct domain_device *dev = pm8001_dev->sas_device;
47928c2ecf20Sopenharmony_ci	struct domain_device *parent_dev = dev->parent;
47938c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
47948c2ecf20Sopenharmony_ci
47958c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(payload));
47968c2ecf20Sopenharmony_ci	rc = pm8001_tag_alloc(pm8001_ha, &tag);
47978c2ecf20Sopenharmony_ci	if (rc)
47988c2ecf20Sopenharmony_ci		return rc;
47998c2ecf20Sopenharmony_ci	ccb = &pm8001_ha->ccb_info[tag];
48008c2ecf20Sopenharmony_ci	ccb->device = pm8001_dev;
48018c2ecf20Sopenharmony_ci	ccb->ccb_tag = tag;
48028c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
48038c2ecf20Sopenharmony_ci
48048c2ecf20Sopenharmony_ci	if (flag == 1) {
48058c2ecf20Sopenharmony_ci		stp_sspsmp_sata = 0x02; /*direct attached sata */
48068c2ecf20Sopenharmony_ci	} else {
48078c2ecf20Sopenharmony_ci		if (pm8001_dev->dev_type == SAS_SATA_DEV)
48088c2ecf20Sopenharmony_ci			stp_sspsmp_sata = 0x00; /* stp*/
48098c2ecf20Sopenharmony_ci		else if (pm8001_dev->dev_type == SAS_END_DEVICE ||
48108c2ecf20Sopenharmony_ci			pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE ||
48118c2ecf20Sopenharmony_ci			pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)
48128c2ecf20Sopenharmony_ci			stp_sspsmp_sata = 0x01; /*ssp or smp*/
48138c2ecf20Sopenharmony_ci	}
48148c2ecf20Sopenharmony_ci	if (parent_dev && dev_is_expander(parent_dev->dev_type))
48158c2ecf20Sopenharmony_ci		phy_id = parent_dev->ex_dev.ex_phy->phy_id;
48168c2ecf20Sopenharmony_ci	else
48178c2ecf20Sopenharmony_ci		phy_id = pm8001_dev->attached_phy;
48188c2ecf20Sopenharmony_ci
48198c2ecf20Sopenharmony_ci	opc = OPC_INB_REG_DEV;
48208c2ecf20Sopenharmony_ci
48218c2ecf20Sopenharmony_ci	linkrate = (pm8001_dev->sas_device->linkrate < dev->port->linkrate) ?
48228c2ecf20Sopenharmony_ci			pm8001_dev->sas_device->linkrate : dev->port->linkrate;
48238c2ecf20Sopenharmony_ci
48248c2ecf20Sopenharmony_ci	payload.phyid_portid =
48258c2ecf20Sopenharmony_ci		cpu_to_le32(((pm8001_dev->sas_device->port->id) & 0xFF) |
48268c2ecf20Sopenharmony_ci		((phy_id & 0xFF) << 8));
48278c2ecf20Sopenharmony_ci
48288c2ecf20Sopenharmony_ci	payload.dtype_dlr_mcn_ir_retry = cpu_to_le32((retryFlag & 0x01) |
48298c2ecf20Sopenharmony_ci		((linkrate & 0x0F) << 24) |
48308c2ecf20Sopenharmony_ci		((stp_sspsmp_sata & 0x03) << 28));
48318c2ecf20Sopenharmony_ci	payload.firstburstsize_ITNexustimeout =
48328c2ecf20Sopenharmony_ci		cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
48338c2ecf20Sopenharmony_ci
48348c2ecf20Sopenharmony_ci	memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
48358c2ecf20Sopenharmony_ci		SAS_ADDR_SIZE);
48368c2ecf20Sopenharmony_ci
48378c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
48388c2ecf20Sopenharmony_ci			sizeof(payload), 0);
48398c2ecf20Sopenharmony_ci	if (rc)
48408c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, tag);
48418c2ecf20Sopenharmony_ci
48428c2ecf20Sopenharmony_ci	return rc;
48438c2ecf20Sopenharmony_ci}
48448c2ecf20Sopenharmony_ci
48458c2ecf20Sopenharmony_ci/**
48468c2ecf20Sopenharmony_ci * pm80xx_chip_phy_ctl_req - support the local phy operation
48478c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
48488c2ecf20Sopenharmony_ci * @phyId: the phy id which we wanted to operate
48498c2ecf20Sopenharmony_ci * @phy_op: phy operation to request
48508c2ecf20Sopenharmony_ci */
48518c2ecf20Sopenharmony_cistatic int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
48528c2ecf20Sopenharmony_ci	u32 phyId, u32 phy_op)
48538c2ecf20Sopenharmony_ci{
48548c2ecf20Sopenharmony_ci	u32 tag;
48558c2ecf20Sopenharmony_ci	int rc;
48568c2ecf20Sopenharmony_ci	struct local_phy_ctl_req payload;
48578c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
48588c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
48598c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(payload));
48608c2ecf20Sopenharmony_ci	rc = pm8001_tag_alloc(pm8001_ha, &tag);
48618c2ecf20Sopenharmony_ci	if (rc)
48628c2ecf20Sopenharmony_ci		return rc;
48638c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
48648c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
48658c2ecf20Sopenharmony_ci	payload.phyop_phyid =
48668c2ecf20Sopenharmony_ci		cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
48678c2ecf20Sopenharmony_ci
48688c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
48698c2ecf20Sopenharmony_ci				  sizeof(payload), 0);
48708c2ecf20Sopenharmony_ci	if (rc)
48718c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, tag);
48728c2ecf20Sopenharmony_ci
48738c2ecf20Sopenharmony_ci	return rc;
48748c2ecf20Sopenharmony_ci}
48758c2ecf20Sopenharmony_ci
48768c2ecf20Sopenharmony_cistatic u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)
48778c2ecf20Sopenharmony_ci{
48788c2ecf20Sopenharmony_ci#ifdef PM8001_USE_MSIX
48798c2ecf20Sopenharmony_ci	return 1;
48808c2ecf20Sopenharmony_ci#else
48818c2ecf20Sopenharmony_ci	u32 value;
48828c2ecf20Sopenharmony_ci
48838c2ecf20Sopenharmony_ci	value = pm8001_cr32(pm8001_ha, 0, MSGU_ODR);
48848c2ecf20Sopenharmony_ci	if (value)
48858c2ecf20Sopenharmony_ci		return 1;
48868c2ecf20Sopenharmony_ci	return 0;
48878c2ecf20Sopenharmony_ci#endif
48888c2ecf20Sopenharmony_ci}
48898c2ecf20Sopenharmony_ci
48908c2ecf20Sopenharmony_ci/**
48918c2ecf20Sopenharmony_ci * pm8001_chip_isr - PM8001 isr handler.
48928c2ecf20Sopenharmony_ci * @pm8001_ha: our hba card information.
48938c2ecf20Sopenharmony_ci * @vec: irq number.
48948c2ecf20Sopenharmony_ci */
48958c2ecf20Sopenharmony_cistatic irqreturn_t
48968c2ecf20Sopenharmony_cipm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
48978c2ecf20Sopenharmony_ci{
48988c2ecf20Sopenharmony_ci	pm80xx_chip_interrupt_disable(pm8001_ha, vec);
48998c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, DEVIO,
49008c2ecf20Sopenharmony_ci		   "irq vec %d, ODMR:0x%x\n",
49018c2ecf20Sopenharmony_ci		   vec, pm8001_cr32(pm8001_ha, 0, 0x30));
49028c2ecf20Sopenharmony_ci	process_oq(pm8001_ha, vec);
49038c2ecf20Sopenharmony_ci	pm80xx_chip_interrupt_enable(pm8001_ha, vec);
49048c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
49058c2ecf20Sopenharmony_ci}
49068c2ecf20Sopenharmony_ci
49078c2ecf20Sopenharmony_cistatic void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
49088c2ecf20Sopenharmony_ci				    u32 operation, u32 phyid,
49098c2ecf20Sopenharmony_ci				    u32 length, u32 *buf)
49108c2ecf20Sopenharmony_ci{
49118c2ecf20Sopenharmony_ci	u32 tag , i, j = 0;
49128c2ecf20Sopenharmony_ci	int rc;
49138c2ecf20Sopenharmony_ci	struct set_phy_profile_req payload;
49148c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
49158c2ecf20Sopenharmony_ci	u32 opc = OPC_INB_SET_PHY_PROFILE;
49168c2ecf20Sopenharmony_ci
49178c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(payload));
49188c2ecf20Sopenharmony_ci	rc = pm8001_tag_alloc(pm8001_ha, &tag);
49198c2ecf20Sopenharmony_ci	if (rc)
49208c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, FAIL, "Invalid tag\n");
49218c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
49228c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
49238c2ecf20Sopenharmony_ci	payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid  & 0xFF));
49248c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT,
49258c2ecf20Sopenharmony_ci		   " phy profile command for phy %x ,length is %d\n",
49268c2ecf20Sopenharmony_ci		   payload.ppc_phyid, length);
49278c2ecf20Sopenharmony_ci	for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) {
49288c2ecf20Sopenharmony_ci		payload.reserved[j] =  cpu_to_le32(*((u32 *)buf + i));
49298c2ecf20Sopenharmony_ci		j++;
49308c2ecf20Sopenharmony_ci	}
49318c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
49328c2ecf20Sopenharmony_ci			sizeof(payload), 0);
49338c2ecf20Sopenharmony_ci	if (rc)
49348c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, tag);
49358c2ecf20Sopenharmony_ci}
49368c2ecf20Sopenharmony_ci
49378c2ecf20Sopenharmony_civoid pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
49388c2ecf20Sopenharmony_ci	u32 length, u8 *buf)
49398c2ecf20Sopenharmony_ci{
49408c2ecf20Sopenharmony_ci	u32 i;
49418c2ecf20Sopenharmony_ci
49428c2ecf20Sopenharmony_ci	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
49438c2ecf20Sopenharmony_ci		mpi_set_phy_profile_req(pm8001_ha,
49448c2ecf20Sopenharmony_ci			SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf);
49458c2ecf20Sopenharmony_ci		length = length + PHY_DWORD_LENGTH;
49468c2ecf20Sopenharmony_ci	}
49478c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "phy settings completed\n");
49488c2ecf20Sopenharmony_ci}
49498c2ecf20Sopenharmony_ci
49508c2ecf20Sopenharmony_civoid pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
49518c2ecf20Sopenharmony_ci		u32 phy, u32 length, u32 *buf)
49528c2ecf20Sopenharmony_ci{
49538c2ecf20Sopenharmony_ci	u32 tag, opc;
49548c2ecf20Sopenharmony_ci	int rc, i;
49558c2ecf20Sopenharmony_ci	struct set_phy_profile_req payload;
49568c2ecf20Sopenharmony_ci	struct inbound_queue_table *circularQ;
49578c2ecf20Sopenharmony_ci
49588c2ecf20Sopenharmony_ci	memset(&payload, 0, sizeof(payload));
49598c2ecf20Sopenharmony_ci
49608c2ecf20Sopenharmony_ci	rc = pm8001_tag_alloc(pm8001_ha, &tag);
49618c2ecf20Sopenharmony_ci	if (rc)
49628c2ecf20Sopenharmony_ci		pm8001_dbg(pm8001_ha, INIT, "Invalid tag\n");
49638c2ecf20Sopenharmony_ci
49648c2ecf20Sopenharmony_ci	circularQ = &pm8001_ha->inbnd_q_tbl[0];
49658c2ecf20Sopenharmony_ci	opc = OPC_INB_SET_PHY_PROFILE;
49668c2ecf20Sopenharmony_ci
49678c2ecf20Sopenharmony_ci	payload.tag = cpu_to_le32(tag);
49688c2ecf20Sopenharmony_ci	payload.ppc_phyid = (((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8)
49698c2ecf20Sopenharmony_ci				| (phy & 0xFF));
49708c2ecf20Sopenharmony_ci
49718c2ecf20Sopenharmony_ci	for (i = 0; i < length; i++)
49728c2ecf20Sopenharmony_ci		payload.reserved[i] = cpu_to_le32(*(buf + i));
49738c2ecf20Sopenharmony_ci
49748c2ecf20Sopenharmony_ci	rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
49758c2ecf20Sopenharmony_ci			sizeof(payload), 0);
49768c2ecf20Sopenharmony_ci	if (rc)
49778c2ecf20Sopenharmony_ci		pm8001_tag_free(pm8001_ha, tag);
49788c2ecf20Sopenharmony_ci
49798c2ecf20Sopenharmony_ci	pm8001_dbg(pm8001_ha, INIT, "PHY %d settings applied\n", phy);
49808c2ecf20Sopenharmony_ci}
49818c2ecf20Sopenharmony_ciconst struct pm8001_dispatch pm8001_80xx_dispatch = {
49828c2ecf20Sopenharmony_ci	.name			= "pmc80xx",
49838c2ecf20Sopenharmony_ci	.chip_init		= pm80xx_chip_init,
49848c2ecf20Sopenharmony_ci	.chip_soft_rst		= pm80xx_chip_soft_rst,
49858c2ecf20Sopenharmony_ci	.chip_rst		= pm80xx_hw_chip_rst,
49868c2ecf20Sopenharmony_ci	.chip_iounmap		= pm8001_chip_iounmap,
49878c2ecf20Sopenharmony_ci	.isr			= pm80xx_chip_isr,
49888c2ecf20Sopenharmony_ci	.is_our_interrupt	= pm80xx_chip_is_our_interrupt,
49898c2ecf20Sopenharmony_ci	.isr_process_oq		= process_oq,
49908c2ecf20Sopenharmony_ci	.interrupt_enable	= pm80xx_chip_interrupt_enable,
49918c2ecf20Sopenharmony_ci	.interrupt_disable	= pm80xx_chip_interrupt_disable,
49928c2ecf20Sopenharmony_ci	.make_prd		= pm8001_chip_make_sg,
49938c2ecf20Sopenharmony_ci	.smp_req		= pm80xx_chip_smp_req,
49948c2ecf20Sopenharmony_ci	.ssp_io_req		= pm80xx_chip_ssp_io_req,
49958c2ecf20Sopenharmony_ci	.sata_req		= pm80xx_chip_sata_req,
49968c2ecf20Sopenharmony_ci	.phy_start_req		= pm80xx_chip_phy_start_req,
49978c2ecf20Sopenharmony_ci	.phy_stop_req		= pm80xx_chip_phy_stop_req,
49988c2ecf20Sopenharmony_ci	.reg_dev_req		= pm80xx_chip_reg_dev_req,
49998c2ecf20Sopenharmony_ci	.dereg_dev_req		= pm8001_chip_dereg_dev_req,
50008c2ecf20Sopenharmony_ci	.phy_ctl_req		= pm80xx_chip_phy_ctl_req,
50018c2ecf20Sopenharmony_ci	.task_abort		= pm8001_chip_abort_task,
50028c2ecf20Sopenharmony_ci	.ssp_tm_req		= pm8001_chip_ssp_tm_req,
50038c2ecf20Sopenharmony_ci	.get_nvmd_req		= pm8001_chip_get_nvmd_req,
50048c2ecf20Sopenharmony_ci	.set_nvmd_req		= pm8001_chip_set_nvmd_req,
50058c2ecf20Sopenharmony_ci	.fw_flash_update_req	= pm8001_chip_fw_flash_update_req,
50068c2ecf20Sopenharmony_ci	.set_dev_state_req	= pm8001_chip_set_dev_state_req,
50078c2ecf20Sopenharmony_ci};
5008