xref: /freebsd/sys/dev/smartpqi/smartpqi_sis.c (revision 7ea28254ec5376b5deb86c136e1838d0134dbb22)
11e66f787SSean Bruno /*-
2*7ea28254SJohn Hall  * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries.
31e66f787SSean Bruno  *
41e66f787SSean Bruno  * Redistribution and use in source and binary forms, with or without
51e66f787SSean Bruno  * modification, are permitted provided that the following conditions
61e66f787SSean Bruno  * are met:
71e66f787SSean Bruno  * 1. Redistributions of source code must retain the above copyright
81e66f787SSean Bruno  *    notice, this list of conditions and the following disclaimer.
91e66f787SSean Bruno  * 2. Redistributions in binary form must reproduce the above copyright
101e66f787SSean Bruno  *    notice, this list of conditions and the following disclaimer in the
111e66f787SSean Bruno  *    documentation and/or other materials provided with the distribution.
121e66f787SSean Bruno  *
131e66f787SSean Bruno  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
141e66f787SSean Bruno  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
151e66f787SSean Bruno  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
161e66f787SSean Bruno  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
171e66f787SSean Bruno  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
181e66f787SSean Bruno  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
191e66f787SSean Bruno  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201e66f787SSean Bruno  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
211e66f787SSean Bruno  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
221e66f787SSean Bruno  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
231e66f787SSean Bruno  * SUCH DAMAGE.
241e66f787SSean Bruno  */
251e66f787SSean Bruno 
261e66f787SSean Bruno 
271e66f787SSean Bruno #include "smartpqi_includes.h"
281e66f787SSean Bruno 
299fac68fcSPAPANI SRIKANTH /* Function for disabling msix interrupots */
309fac68fcSPAPANI SRIKANTH void
sis_disable_msix(pqisrc_softstate_t * softs)319fac68fcSPAPANI SRIKANTH sis_disable_msix(pqisrc_softstate_t *softs)
321e66f787SSean Bruno {
331e66f787SSean Bruno 	uint32_t db_reg;
341e66f787SSean Bruno 
351e66f787SSean Bruno 	DBG_FUNC("IN\n");
361e66f787SSean Bruno 
371e66f787SSean Bruno 	db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
381e66f787SSean Bruno 			LEGACY_SIS_IDBR);
391e66f787SSean Bruno 	db_reg &= ~SIS_ENABLE_MSIX;
401e66f787SSean Bruno 	PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
411e66f787SSean Bruno 			LEGACY_SIS_IDBR, db_reg);
42*7ea28254SJohn Hall 	OS_SLEEP(1000);     /* 1 ms delay for PCI W/R ordering issue */
431e66f787SSean Bruno 
441e66f787SSean Bruno 	DBG_FUNC("OUT\n");
451e66f787SSean Bruno }
461e66f787SSean Bruno 
479fac68fcSPAPANI SRIKANTH void
sis_enable_intx(pqisrc_softstate_t * softs)489fac68fcSPAPANI SRIKANTH sis_enable_intx(pqisrc_softstate_t *softs)
49b17f4335SSean Bruno {
50b17f4335SSean Bruno 	uint32_t db_reg;
51b17f4335SSean Bruno 
52b17f4335SSean Bruno 	DBG_FUNC("IN\n");
53b17f4335SSean Bruno 
54b17f4335SSean Bruno 	db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
55b17f4335SSean Bruno 		LEGACY_SIS_IDBR);
56b17f4335SSean Bruno 	db_reg |= SIS_ENABLE_INTX;
57b17f4335SSean Bruno 	PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
58b17f4335SSean Bruno 			LEGACY_SIS_IDBR, db_reg);
59*7ea28254SJohn Hall 	OS_SLEEP(1000);     /* 1 ms delay for PCI W/R ordering issue */
60b17f4335SSean Bruno 	if (pqisrc_sis_wait_for_db_bit_to_clear(softs,SIS_ENABLE_INTX)
61b17f4335SSean Bruno 		!= PQI_STATUS_SUCCESS) {
62b17f4335SSean Bruno 		DBG_ERR("Failed to wait for enable intx db bit to clear\n");
63b17f4335SSean Bruno 	}
64b17f4335SSean Bruno 	DBG_FUNC("OUT\n");
65b17f4335SSean Bruno }
66b17f4335SSean Bruno 
679fac68fcSPAPANI SRIKANTH void
sis_disable_intx(pqisrc_softstate_t * softs)689fac68fcSPAPANI SRIKANTH sis_disable_intx(pqisrc_softstate_t *softs)
69b17f4335SSean Bruno {
70b17f4335SSean Bruno 	uint32_t db_reg;
71b17f4335SSean Bruno 
72b17f4335SSean Bruno 	DBG_FUNC("IN\n");
73b17f4335SSean Bruno 
74b17f4335SSean Bruno 	db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
75b17f4335SSean Bruno 			LEGACY_SIS_IDBR);
76b17f4335SSean Bruno 	db_reg &= ~SIS_ENABLE_INTX;
77b17f4335SSean Bruno 	PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
78b17f4335SSean Bruno 			LEGACY_SIS_IDBR, db_reg);
79*7ea28254SJohn Hall 	OS_SLEEP(1000);     /* 1 ms delay for PCI W/R ordering issue */
80b17f4335SSean Bruno 
81b17f4335SSean Bruno 	DBG_FUNC("OUT\n");
82b17f4335SSean Bruno }
83b17f4335SSean Bruno 
849fac68fcSPAPANI SRIKANTH void
sis_disable_interrupt(pqisrc_softstate_t * softs)859fac68fcSPAPANI SRIKANTH sis_disable_interrupt(pqisrc_softstate_t *softs)
86b17f4335SSean Bruno {
87b17f4335SSean Bruno 	DBG_FUNC("IN");
88b17f4335SSean Bruno 
89b17f4335SSean Bruno 	switch(softs->intr_type) {
90b17f4335SSean Bruno 		case INTR_TYPE_FIXED:
91b17f4335SSean Bruno 			pqisrc_configure_legacy_intx(softs,false);
92b17f4335SSean Bruno 			sis_disable_intx(softs);
93b17f4335SSean Bruno 			break;
94b17f4335SSean Bruno 		case INTR_TYPE_MSI:
95b17f4335SSean Bruno 		case INTR_TYPE_MSIX:
96b17f4335SSean Bruno  			sis_disable_msix(softs);
97b17f4335SSean Bruno 			break;
98b17f4335SSean Bruno 		default:
99b17f4335SSean Bruno 			DBG_ERR("Inerrupt mode none!\n");
100b17f4335SSean Bruno 			break;
101b17f4335SSean Bruno 	}
102b17f4335SSean Bruno 
103b17f4335SSean Bruno 	DBG_FUNC("OUT");
104b17f4335SSean Bruno }
105b17f4335SSean Bruno 
1069fac68fcSPAPANI SRIKANTH 
1071e66f787SSean Bruno /* Trigger a NMI as part of taking controller offline procedure */
1089fac68fcSPAPANI SRIKANTH void
pqisrc_trigger_nmi_sis(pqisrc_softstate_t * softs)1099fac68fcSPAPANI SRIKANTH pqisrc_trigger_nmi_sis(pqisrc_softstate_t *softs)
1101e66f787SSean Bruno {
1111e66f787SSean Bruno 
1121e66f787SSean Bruno 	DBG_FUNC("IN\n");
1131e66f787SSean Bruno 
1141e66f787SSean Bruno 	PCI_MEM_PUT32(softs,  &softs->ioa_reg->host_to_ioa_db,
1151e66f787SSean Bruno 			LEGACY_SIS_IDBR, LE_32(TRIGGER_NMI_SIS));
1161e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1171e66f787SSean Bruno }
1181e66f787SSean Bruno 
1191e66f787SSean Bruno /* Switch the adapter back to SIS mode during uninitialization */
1209fac68fcSPAPANI SRIKANTH int
pqisrc_reenable_sis(pqisrc_softstate_t * softs)1219fac68fcSPAPANI SRIKANTH pqisrc_reenable_sis(pqisrc_softstate_t *softs)
1221e66f787SSean Bruno {
1231e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
1241e66f787SSean Bruno 	uint32_t timeout = SIS_ENABLE_TIMEOUT;
1251e66f787SSean Bruno 
1261e66f787SSean Bruno 	DBG_FUNC("IN\n");
1271e66f787SSean Bruno 
1281e66f787SSean Bruno 	PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
1291e66f787SSean Bruno         LEGACY_SIS_IDBR, LE_32(REENABLE_SIS));
130*7ea28254SJohn Hall 	OS_SLEEP(1000);     /* 1 ms delay for PCI W/R ordering issue */
1311e66f787SSean Bruno 
1321e66f787SSean Bruno 	COND_WAIT(((PCI_MEM_GET32(softs, &softs->ioa_reg->ioa_to_host_db, LEGACY_SIS_ODBR_R) &
1331e66f787SSean Bruno 				REENABLE_SIS) == 0), timeout)
1341e66f787SSean Bruno 	if (!timeout) {
1351e66f787SSean Bruno 		DBG_WARN(" [ %s ] failed to re enable sis\n",__func__);
1361e66f787SSean Bruno 		ret = PQI_STATUS_TIMEOUT;
1371e66f787SSean Bruno 	}
1381e66f787SSean Bruno 
1391e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1401e66f787SSean Bruno 	return ret;
1411e66f787SSean Bruno }
1421e66f787SSean Bruno 
1431e66f787SSean Bruno /* Validate the FW status PQI_CTRL_KERNEL_UP_AND_RUNNING */
1449fac68fcSPAPANI SRIKANTH int
pqisrc_check_fw_status(pqisrc_softstate_t * softs)1459fac68fcSPAPANI SRIKANTH pqisrc_check_fw_status(pqisrc_softstate_t *softs)
1461e66f787SSean Bruno {
1471e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
1481e66f787SSean Bruno 	uint32_t timeout = SIS_STATUS_OK_TIMEOUT;
1491e66f787SSean Bruno 
1501e66f787SSean Bruno 	DBG_FUNC("IN\n");
1511e66f787SSean Bruno 
1521e66f787SSean Bruno 	OS_SLEEP(1000000);
1531e66f787SSean Bruno 	COND_WAIT((GET_FW_STATUS(softs) &
1541e66f787SSean Bruno 		PQI_CTRL_KERNEL_UP_AND_RUNNING), timeout);
1551e66f787SSean Bruno 	if (!timeout) {
1561e66f787SSean Bruno 		DBG_ERR("FW check status timedout\n");
1571e66f787SSean Bruno 		ret = PQI_STATUS_TIMEOUT;
1581e66f787SSean Bruno 	}
1591e66f787SSean Bruno 
1601e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1611e66f787SSean Bruno 	return ret;
1621e66f787SSean Bruno }
1631e66f787SSean Bruno 
1641e66f787SSean Bruno /* Function used to submit a SIS command to the adapter */
1659fac68fcSPAPANI SRIKANTH static int
pqisrc_send_sis_cmd(pqisrc_softstate_t * softs,uint32_t * mb)1669fac68fcSPAPANI SRIKANTH pqisrc_send_sis_cmd(pqisrc_softstate_t *softs, uint32_t *mb)
1671e66f787SSean Bruno {
1681e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
1691e66f787SSean Bruno 	int i = 0;
1701e66f787SSean Bruno 	uint32_t timeout = SIS_CMD_COMPLETE_TIMEOUT;
1711e66f787SSean Bruno 
1721e66f787SSean Bruno 	int val;
1731e66f787SSean Bruno 
1741e66f787SSean Bruno 	DBG_FUNC("IN\n");
1751e66f787SSean Bruno 
1769fac68fcSPAPANI SRIKANTH 
1771e66f787SSean Bruno 	/* Copy Command to mailbox */
1781e66f787SSean Bruno 	for (i = 0; i < 6; i++)
1791e66f787SSean Bruno 		PCI_MEM_PUT32(softs, &softs->ioa_reg->mb[i],
1801e66f787SSean Bruno             LEGACY_SIS_SRCV_MAILBOX+i*4, LE_32(mb[i]));
1811e66f787SSean Bruno 
1829fac68fcSPAPANI SRIKANTH 	/* TODO : Switch to INTX Mode ?*/
1831e66f787SSean Bruno 	PCI_MEM_PUT32(softs, &softs->ioa_reg->ioa_to_host_db_clr,
1841e66f787SSean Bruno 		LEGACY_SIS_ODBR_R, LE_32(0x1000));
1851e66f787SSean Bruno 
1861e66f787SSean Bruno 	/* Submit the command */
1871e66f787SSean Bruno 	PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
1881e66f787SSean Bruno 		LEGACY_SIS_IDBR, LE_32(SIS_CMD_SUBMIT));
1891e66f787SSean Bruno 
1901e66f787SSean Bruno #ifdef SIS_POLL_WAIT
1911e66f787SSean Bruno 	/* Wait for 20  milli sec to poll */
1921e66f787SSean Bruno 	OS_BUSYWAIT(SIS_POLL_START_WAIT_TIME);
1931e66f787SSean Bruno #endif
1941e66f787SSean Bruno 
1951e66f787SSean Bruno 	val = PCI_MEM_GET32(softs, &softs->ioa_reg->ioa_to_host_db, LEGACY_SIS_ODBR_R);
1961e66f787SSean Bruno 
1971e66f787SSean Bruno 	DBG_FUNC("val : %x\n",val);
1981e66f787SSean Bruno 	/* Spin waiting for the command to complete */
1991e66f787SSean Bruno 	COND_WAIT((PCI_MEM_GET32(softs, &softs->ioa_reg->ioa_to_host_db, LEGACY_SIS_ODBR_R) &
2001e66f787SSean Bruno 		SIS_CMD_COMPLETE), timeout);
2011e66f787SSean Bruno 	if (!timeout) {
2021e66f787SSean Bruno 		DBG_ERR("Sync command %x, timedout\n", mb[0]);
2031e66f787SSean Bruno 		ret = PQI_STATUS_TIMEOUT;
2041e66f787SSean Bruno 		goto err_out;
2051e66f787SSean Bruno 	}
2061e66f787SSean Bruno 	/* Check command status */
2071e66f787SSean Bruno 	mb[0] = LE_32(PCI_MEM_GET32(softs, &softs->ioa_reg->mb[0], LEGACY_SIS_SRCV_MAILBOX));
2081e66f787SSean Bruno 
2091e66f787SSean Bruno 	if (mb[0] != SIS_CMD_STATUS_SUCCESS) {
2101e66f787SSean Bruno 		DBG_ERR("SIS cmd failed with status = 0x%x\n",
2111e66f787SSean Bruno 			mb[0]);
2121e66f787SSean Bruno 		ret = PQI_STATUS_FAILURE;
2131e66f787SSean Bruno 		goto err_out;
2141e66f787SSean Bruno 	}
2151e66f787SSean Bruno 
2161e66f787SSean Bruno 	/* Copy the mailbox back  */
2171e66f787SSean Bruno 	for (i = 1; i < 6; i++)
2181e66f787SSean Bruno 		mb[i] =	LE_32(PCI_MEM_GET32(softs, &softs->ioa_reg->mb[i], LEGACY_SIS_SRCV_MAILBOX+i*4));
2191e66f787SSean Bruno 
2201e66f787SSean Bruno 	DBG_FUNC("OUT\n");
2211e66f787SSean Bruno 	return ret;
2221e66f787SSean Bruno 
2231e66f787SSean Bruno err_out:
2241e66f787SSean Bruno 	DBG_FUNC("OUT failed\n");
2251e66f787SSean Bruno 	return ret;
2261e66f787SSean Bruno }
2271e66f787SSean Bruno 
2281e66f787SSean Bruno /* First SIS command for the adapter to check PQI support */
2299fac68fcSPAPANI SRIKANTH int
pqisrc_get_adapter_properties(pqisrc_softstate_t * softs,uint32_t * prop,uint32_t * ext_prop)2309fac68fcSPAPANI SRIKANTH pqisrc_get_adapter_properties(pqisrc_softstate_t *softs,
2311e66f787SSean Bruno 				uint32_t *prop, uint32_t *ext_prop)
2321e66f787SSean Bruno {
2331e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
2341e66f787SSean Bruno 	uint32_t mb[6] = {0};
2351e66f787SSean Bruno 
2361e66f787SSean Bruno 	DBG_FUNC("IN\n");
2371e66f787SSean Bruno 
2381e66f787SSean Bruno 	mb[0] = SIS_CMD_GET_ADAPTER_PROPERTIES;
2391e66f787SSean Bruno 	ret = pqisrc_send_sis_cmd(softs, mb);
2401e66f787SSean Bruno 	if (!ret) {
241b17f4335SSean Bruno 		DBG_INIT("GET_PROPERTIES prop = %x, ext_prop = %x\n",
2421e66f787SSean Bruno 					mb[1], mb[4]);
2431e66f787SSean Bruno 		*prop = mb[1];
2441e66f787SSean Bruno 		*ext_prop = mb[4];
2451e66f787SSean Bruno 	}
2461e66f787SSean Bruno 
2471e66f787SSean Bruno 	DBG_FUNC("OUT\n");
2481e66f787SSean Bruno 	return ret;
2491e66f787SSean Bruno }
2501e66f787SSean Bruno 
2511e66f787SSean Bruno /* Second SIS command to the adapter GET_COMM_PREFERRED_SETTINGS */
2529fac68fcSPAPANI SRIKANTH int
pqisrc_get_preferred_settings(pqisrc_softstate_t * softs)2539fac68fcSPAPANI SRIKANTH pqisrc_get_preferred_settings(pqisrc_softstate_t *softs)
2541e66f787SSean Bruno {
2551e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
2561e66f787SSean Bruno 	uint32_t mb[6] = {0};
2571e66f787SSean Bruno 
2581e66f787SSean Bruno 	DBG_FUNC("IN\n");
2591e66f787SSean Bruno 
2601e66f787SSean Bruno 	mb[0] = SIS_CMD_GET_COMM_PREFERRED_SETTINGS;
2611e66f787SSean Bruno 	ret = pqisrc_send_sis_cmd(softs, mb);
2621e66f787SSean Bruno 	if (!ret) {
2631e66f787SSean Bruno 		/* 31:16 maximum command size in KB */
2641e66f787SSean Bruno 		softs->pref_settings.max_cmd_size = mb[1] >> 16;
2651e66f787SSean Bruno 		/* 15:00: Maximum FIB size in bytes */
2661e66f787SSean Bruno 		softs->pref_settings.max_fib_size = mb[1] & 0x0000FFFF;
267b17f4335SSean Bruno 		DBG_INIT("cmd size = %x, fib size = %x\n",
2681e66f787SSean Bruno 			softs->pref_settings.max_cmd_size,
2691e66f787SSean Bruno 			softs->pref_settings.max_fib_size);
2701e66f787SSean Bruno 	}
2711e66f787SSean Bruno 
2721e66f787SSean Bruno 	DBG_FUNC("OUT\n");
2731e66f787SSean Bruno 	return ret;
2741e66f787SSean Bruno }
2751e66f787SSean Bruno 
2761e66f787SSean Bruno /* Get supported PQI capabilities from the adapter */
2779fac68fcSPAPANI SRIKANTH int
pqisrc_get_sis_pqi_cap(pqisrc_softstate_t * softs)2789fac68fcSPAPANI SRIKANTH pqisrc_get_sis_pqi_cap(pqisrc_softstate_t *softs)
2791e66f787SSean Bruno {
2801e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
2811e66f787SSean Bruno 	uint32_t mb[6] = {0};
2821e66f787SSean Bruno 
2831e66f787SSean Bruno 	DBG_FUNC("IN\n");
2841e66f787SSean Bruno 
2851e66f787SSean Bruno 	mb[0] = SIS_CMD_GET_PQI_CAPABILITIES;
2861e66f787SSean Bruno 	ret = pqisrc_send_sis_cmd(softs,  mb);
2871e66f787SSean Bruno 	if (!ret) {
2881e66f787SSean Bruno 		softs->pqi_cap.max_sg_elem = mb[1];
2891e66f787SSean Bruno 		softs->pqi_cap.max_transfer_size = mb[2];
2901e66f787SSean Bruno 		softs->pqi_cap.max_outstanding_io = mb[3];
291*7ea28254SJohn Hall 		if (softs->pqi_cap.max_outstanding_io >
292*7ea28254SJohn Hall 			PQISRC_MAX_OUTSTANDING_REQ) {
293*7ea28254SJohn Hall 			DBG_WARN("Controller-supported max outstanding "
294*7ea28254SJohn Hall 				"commands %u reduced to %d to align with "
295*7ea28254SJohn Hall 				"driver-supported max.\n",
296*7ea28254SJohn Hall 				softs->pqi_cap.max_outstanding_io,
297*7ea28254SJohn Hall 				PQISRC_MAX_OUTSTANDING_REQ);
298*7ea28254SJohn Hall 			softs->pqi_cap.max_outstanding_io =
299*7ea28254SJohn Hall 				PQISRC_MAX_OUTSTANDING_REQ;
300*7ea28254SJohn Hall 		}
301*7ea28254SJohn Hall 
302*7ea28254SJohn Hall #ifdef DEVICE_HINT
303*7ea28254SJohn Hall 		bsd_set_hint_adapter_cap(softs);
304*7ea28254SJohn Hall #endif
305*7ea28254SJohn Hall 
3061e66f787SSean Bruno 		softs->pqi_cap.conf_tab_off = mb[4];
3071e66f787SSean Bruno 		softs->pqi_cap.conf_tab_sz =  mb[5];
3081e66f787SSean Bruno 
3099fac68fcSPAPANI SRIKANTH 		os_update_dma_attributes(softs);
3109fac68fcSPAPANI SRIKANTH 
311b17f4335SSean Bruno 		DBG_INIT("max_sg_elem = %x\n",
3121e66f787SSean Bruno 					softs->pqi_cap.max_sg_elem);
313b17f4335SSean Bruno 		DBG_INIT("max_transfer_size = %x\n",
3141e66f787SSean Bruno 					softs->pqi_cap.max_transfer_size);
315b17f4335SSean Bruno 		DBG_INIT("max_outstanding_io = %x\n",
3161e66f787SSean Bruno 					softs->pqi_cap.max_outstanding_io);
317*7ea28254SJohn Hall 	/*	DBG_INIT("config_table_offset = %x\n",
318*7ea28254SJohn Hall 					softs->pqi_cap.conf_tab_off);
319*7ea28254SJohn Hall 		DBG_INIT("config_table_size = %x\n",
320*7ea28254SJohn Hall 					softs->pqi_cap.conf_tab_sz);
321*7ea28254SJohn Hall 	*/
3221e66f787SSean Bruno 	}
3231e66f787SSean Bruno 
3241e66f787SSean Bruno 	DBG_FUNC("OUT\n");
3251e66f787SSean Bruno 	return ret;
3261e66f787SSean Bruno }
3271e66f787SSean Bruno 
3281e66f787SSean Bruno /* Send INIT STRUCT BASE ADDR - one of the SIS command */
3299fac68fcSPAPANI SRIKANTH int
pqisrc_init_struct_base(pqisrc_softstate_t * softs)3309fac68fcSPAPANI SRIKANTH pqisrc_init_struct_base(pqisrc_softstate_t *softs)
3311e66f787SSean Bruno {
3321e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
3331e66f787SSean Bruno 	uint32_t elem_size = 0;
3341e66f787SSean Bruno 	uint32_t num_elem = 0;
3351e66f787SSean Bruno 	struct dma_mem init_struct_mem = {0};
3361e66f787SSean Bruno 	struct init_base_struct *init_struct = NULL;
3371e66f787SSean Bruno 	uint32_t mb[6] = {0};
3381e66f787SSean Bruno 
3391e66f787SSean Bruno 	DBG_FUNC("IN\n");
3401e66f787SSean Bruno 
3411e66f787SSean Bruno 	/* Allocate init struct */
3421e66f787SSean Bruno 	memset(&init_struct_mem, 0, sizeof(struct dma_mem));
3431e66f787SSean Bruno 	init_struct_mem.size = sizeof(struct init_base_struct);
3441e66f787SSean Bruno 	init_struct_mem.align = PQISRC_INIT_STRUCT_DMA_ALIGN;
345*7ea28254SJohn Hall 	os_strlcpy(init_struct_mem.tag, "init_struct", sizeof(init_struct_mem.tag));
3461e66f787SSean Bruno 	ret = os_dma_mem_alloc(softs, &init_struct_mem);
3471e66f787SSean Bruno 	if (ret) {
3481e66f787SSean Bruno 		DBG_ERR("Failed to Allocate error buffer ret : %d\n",
3491e66f787SSean Bruno 			ret);
3501e66f787SSean Bruno 		goto err_out;
3511e66f787SSean Bruno 	}
3521e66f787SSean Bruno 
3531e66f787SSean Bruno 	/* Calculate error buffer size */
3541e66f787SSean Bruno 	/* The valid tag values are from 1, 2, ..., softs->max_outstanding_io
3551e66f787SSean Bruno 	 * The rcb and error buffer will be accessed by using the tag as index
3561e66f787SSean Bruno 	 * As 0 tag  index is not used, we need to allocate one extra.
3571e66f787SSean Bruno 	 */
3581e66f787SSean Bruno 	num_elem = softs->pqi_cap.max_outstanding_io + 1;
3591e66f787SSean Bruno 	elem_size = PQISRC_ERR_BUF_ELEM_SIZE;
3601e66f787SSean Bruno 	softs->err_buf_dma_mem.size = num_elem * elem_size;
3611e66f787SSean Bruno 
3621e66f787SSean Bruno 	/* Allocate error buffer */
3631e66f787SSean Bruno 	softs->err_buf_dma_mem.align = PQISRC_ERR_BUF_DMA_ALIGN;
364*7ea28254SJohn Hall 	os_strlcpy(softs->err_buf_dma_mem.tag, "error_buffer", sizeof(softs->err_buf_dma_mem.tag));
3651e66f787SSean Bruno 	ret = os_dma_mem_alloc(softs, &softs->err_buf_dma_mem);
3661e66f787SSean Bruno 	if (ret) {
3671e66f787SSean Bruno 		DBG_ERR("Failed to Allocate error buffer ret : %d\n",
3681e66f787SSean Bruno 			ret);
3691e66f787SSean Bruno 		goto err_error_buf_alloc;
3701e66f787SSean Bruno 	}
3711e66f787SSean Bruno 
3721e66f787SSean Bruno 	/* Fill init struct */
3731e66f787SSean Bruno 	init_struct = (struct init_base_struct *)DMA_TO_VIRT(&init_struct_mem);
3741e66f787SSean Bruno 	init_struct->revision = PQISRC_INIT_STRUCT_REVISION;
3751e66f787SSean Bruno 	init_struct->flags    = 0;
3761e66f787SSean Bruno 	init_struct->err_buf_paddr_l = DMA_PHYS_LOW(&softs->err_buf_dma_mem);
3771e66f787SSean Bruno 	init_struct->err_buf_paddr_h = DMA_PHYS_HIGH(&softs->err_buf_dma_mem);
3781e66f787SSean Bruno 	init_struct->err_buf_elem_len = elem_size;
3791e66f787SSean Bruno 	init_struct->err_buf_num_elem = num_elem;
3801e66f787SSean Bruno 
3811e66f787SSean Bruno 	mb[0] = SIS_CMD_INIT_BASE_STRUCT_ADDRESS;
3821e66f787SSean Bruno 	mb[1] = DMA_PHYS_LOW(&init_struct_mem);
3831e66f787SSean Bruno 	mb[2] = DMA_PHYS_HIGH(&init_struct_mem);
3841e66f787SSean Bruno 	mb[3] = init_struct_mem.size;
3851e66f787SSean Bruno 
3861e66f787SSean Bruno 	ret = pqisrc_send_sis_cmd(softs, mb);
3871e66f787SSean Bruno 	if (ret)
3881e66f787SSean Bruno 		goto err_sis_cmd;
3891e66f787SSean Bruno 
3901e66f787SSean Bruno 	DBG_FUNC("OUT\n");
3911e66f787SSean Bruno 	os_dma_mem_free(softs, &init_struct_mem);
3921e66f787SSean Bruno 	return ret;
3931e66f787SSean Bruno 
3941e66f787SSean Bruno err_sis_cmd:
3951e66f787SSean Bruno 	os_dma_mem_free(softs, &softs->err_buf_dma_mem);
3961e66f787SSean Bruno err_error_buf_alloc:
3971e66f787SSean Bruno 	os_dma_mem_free(softs, &init_struct_mem);
3981e66f787SSean Bruno err_out:
3991e66f787SSean Bruno 	DBG_FUNC("OUT failed %d\n", ret);
4001e66f787SSean Bruno 	return PQI_STATUS_FAILURE;
4011e66f787SSean Bruno }
4021e66f787SSean Bruno 
4031e66f787SSean Bruno /*
4041e66f787SSean Bruno  * SIS initialization of the adapter in a sequence of
4051e66f787SSean Bruno  * - GET_ADAPTER_PROPERTIES
4061e66f787SSean Bruno  * - GET_COMM_PREFERRED_SETTINGS
4071e66f787SSean Bruno  * - GET_PQI_CAPABILITIES
4081e66f787SSean Bruno  * - INIT_STRUCT_BASE ADDR
4091e66f787SSean Bruno  */
4109fac68fcSPAPANI SRIKANTH int
pqisrc_sis_init(pqisrc_softstate_t * softs)4119fac68fcSPAPANI SRIKANTH pqisrc_sis_init(pqisrc_softstate_t *softs)
4121e66f787SSean Bruno {
4131e66f787SSean Bruno 	int ret = PQI_STATUS_SUCCESS;
4141e66f787SSean Bruno 	uint32_t prop = 0;
4151e66f787SSean Bruno 	uint32_t ext_prop = 0;
4161e66f787SSean Bruno 
4171e66f787SSean Bruno 	DBG_FUNC("IN\n");
4181e66f787SSean Bruno 
4191e66f787SSean Bruno 	ret = pqisrc_force_sis(softs);
4201e66f787SSean Bruno 	if (ret) {
4211e66f787SSean Bruno 		DBG_ERR("Failed to switch back the adapter to SIS mode!\n");
4221e66f787SSean Bruno 		goto err_out;
4231e66f787SSean Bruno 	}
4241e66f787SSean Bruno 
4251e66f787SSean Bruno 	/* Check FW status ready	*/
4261e66f787SSean Bruno 	ret = pqisrc_check_fw_status(softs);
4271e66f787SSean Bruno 	if (ret) {
4281e66f787SSean Bruno 		DBG_ERR("PQI Controller is not ready !!!\n");
4291e66f787SSean Bruno 		goto err_out;
4301e66f787SSean Bruno 	}
4311e66f787SSean Bruno 
4321e66f787SSean Bruno 	/* Check For PQI support(19h) */
4331e66f787SSean Bruno 	ret = pqisrc_get_adapter_properties(softs, &prop, &ext_prop);
4341e66f787SSean Bruno 	if (ret) {
4351e66f787SSean Bruno 		DBG_ERR("Failed to get adapter properties\n");
4361e66f787SSean Bruno 		goto err_out;
4371e66f787SSean Bruno 	}
4381e66f787SSean Bruno 	if (!((prop & SIS_SUPPORT_EXT_OPT) &&
4391e66f787SSean Bruno 		(ext_prop & SIS_SUPPORT_PQI))) {
4401e66f787SSean Bruno 		DBG_ERR("PQI Mode Not Supported\n");
4411e66f787SSean Bruno 		ret = PQI_STATUS_FAILURE;
4421e66f787SSean Bruno 		goto err_out;
4431e66f787SSean Bruno 	}
4441e66f787SSean Bruno 
4451e66f787SSean Bruno 	softs->pqi_reset_quiesce_allowed = false;
4461e66f787SSean Bruno 	if (ext_prop & SIS_SUPPORT_PQI_RESET_QUIESCE)
4471e66f787SSean Bruno 		softs->pqi_reset_quiesce_allowed = true;
4481e66f787SSean Bruno 
449*7ea28254SJohn Hall 	/* Send GET_COMM_PREFERRED_SETTINGS (26h), TODO : is it required */
4501e66f787SSean Bruno 	ret = pqisrc_get_preferred_settings(softs);
4511e66f787SSean Bruno 	if (ret) {
4521e66f787SSean Bruno 		DBG_ERR("Failed to get adapter pref settings\n");
4531e66f787SSean Bruno 		goto err_out;
4541e66f787SSean Bruno 	}
4551e66f787SSean Bruno 
4561e66f787SSean Bruno 	/* Get PQI settings , 3000h*/
4571e66f787SSean Bruno 	ret = pqisrc_get_sis_pqi_cap(softs);
4581e66f787SSean Bruno 	if (ret) {
4591e66f787SSean Bruno 		DBG_ERR("Failed to get PQI Capabilities\n");
4601e66f787SSean Bruno 		goto err_out;
4611e66f787SSean Bruno 	}
4621e66f787SSean Bruno 
4639fac68fcSPAPANI SRIKANTH 	/* We need to allocate DMA memory here ,
4649fac68fcSPAPANI SRIKANTH 	 * Do any os specific DMA setup.
4659fac68fcSPAPANI SRIKANTH 	 */
4669fac68fcSPAPANI SRIKANTH 	ret = os_dma_setup(softs);
4679fac68fcSPAPANI SRIKANTH 	if (ret) {
4689fac68fcSPAPANI SRIKANTH 		DBG_ERR("Failed to Setup DMA\n");
4699fac68fcSPAPANI SRIKANTH 		goto err_out;
4709fac68fcSPAPANI SRIKANTH 	}
4719fac68fcSPAPANI SRIKANTH 
4721e66f787SSean Bruno 	/* Init struct base addr */
4731e66f787SSean Bruno 	ret = pqisrc_init_struct_base(softs);
4741e66f787SSean Bruno 	if (ret) {
4751e66f787SSean Bruno 		DBG_ERR("Failed to set init struct base addr\n");
4769fac68fcSPAPANI SRIKANTH 		goto err_dma;
4771e66f787SSean Bruno 	}
4781e66f787SSean Bruno 
4799fac68fcSPAPANI SRIKANTH 
4801e66f787SSean Bruno 	DBG_FUNC("OUT\n");
4811e66f787SSean Bruno 	return ret;
4821e66f787SSean Bruno 
4839fac68fcSPAPANI SRIKANTH err_dma:
4849fac68fcSPAPANI SRIKANTH 	os_dma_destroy(softs);
4851e66f787SSean Bruno err_out:
4861e66f787SSean Bruno 	DBG_FUNC("OUT failed\n");
4871e66f787SSean Bruno 	return ret;
4881e66f787SSean Bruno }
4891e66f787SSean Bruno 
4901e66f787SSean Bruno /* Deallocate the resources used during SIS initialization */
4919fac68fcSPAPANI SRIKANTH void
pqisrc_sis_uninit(pqisrc_softstate_t * softs)4929fac68fcSPAPANI SRIKANTH pqisrc_sis_uninit(pqisrc_softstate_t *softs)
4931e66f787SSean Bruno {
4941e66f787SSean Bruno 	DBG_FUNC("IN\n");
4951e66f787SSean Bruno 
4961e66f787SSean Bruno 	os_dma_mem_free(softs, &softs->err_buf_dma_mem);
4979fac68fcSPAPANI SRIKANTH 
4989fac68fcSPAPANI SRIKANTH 	os_dma_destroy(softs);
4991e66f787SSean Bruno 	os_resource_free(softs);
5001e66f787SSean Bruno 	pqi_reset(softs);
5011e66f787SSean Bruno 
5029fac68fcSPAPANI SRIKANTH 
5031e66f787SSean Bruno 	DBG_FUNC("OUT\n");
5041e66f787SSean Bruno }
5051e66f787SSean Bruno 
5069fac68fcSPAPANI SRIKANTH int
pqisrc_sis_wait_for_db_bit_to_clear(pqisrc_softstate_t * softs,uint32_t bit)5079fac68fcSPAPANI SRIKANTH pqisrc_sis_wait_for_db_bit_to_clear(pqisrc_softstate_t *softs, uint32_t bit)
5081e66f787SSean Bruno {
5091e66f787SSean Bruno 	int rcode = PQI_STATUS_SUCCESS;
5101e66f787SSean Bruno 	uint32_t db_reg;
5111e66f787SSean Bruno 	uint32_t loop_cnt = 0;
5121e66f787SSean Bruno 
5131e66f787SSean Bruno 	DBG_FUNC("IN\n");
5141e66f787SSean Bruno 
5151e66f787SSean Bruno 	while (1) {
5161e66f787SSean Bruno 		db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
5171e66f787SSean Bruno 				LEGACY_SIS_IDBR);
5181e66f787SSean Bruno 		if ((db_reg & bit) == 0)
5191e66f787SSean Bruno 			break;
5201e66f787SSean Bruno 		if (GET_FW_STATUS(softs) & PQI_CTRL_KERNEL_PANIC) {
5211e66f787SSean Bruno 			DBG_ERR("controller kernel panic\n");
5221e66f787SSean Bruno 			rcode = PQI_STATUS_FAILURE;
5231e66f787SSean Bruno 			break;
5241e66f787SSean Bruno 		}
5251e66f787SSean Bruno 		if (loop_cnt++ == SIS_DB_BIT_CLEAR_TIMEOUT_CNT) {
5261e66f787SSean Bruno 			DBG_ERR("door-bell reg bit 0x%x not cleared\n", bit);
5271e66f787SSean Bruno 			rcode = PQI_STATUS_TIMEOUT;
5281e66f787SSean Bruno 			break;
5291e66f787SSean Bruno 		}
5301e66f787SSean Bruno 		OS_SLEEP(500);
5311e66f787SSean Bruno 	}
5321e66f787SSean Bruno 
5331e66f787SSean Bruno 	DBG_FUNC("OUT\n");
5341e66f787SSean Bruno 
5351e66f787SSean Bruno 	return rcode;
5361e66f787SSean Bruno }
537