2 * Copyright (c) 2018 Microsemi Corporation.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include "smartpqi_includes.h"
32 void sis_disable_msix(pqisrc_softstate_t *softs)
38 db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
40 db_reg &= ~SIS_ENABLE_MSIX;
41 PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
42 LEGACY_SIS_IDBR, db_reg);
47 void sis_enable_intx(pqisrc_softstate_t *softs)
53 db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
55 db_reg |= SIS_ENABLE_INTX;
56 PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
57 LEGACY_SIS_IDBR, db_reg);
58 if (pqisrc_sis_wait_for_db_bit_to_clear(softs,SIS_ENABLE_INTX)
59 != PQI_STATUS_SUCCESS) {
60 DBG_ERR("Failed to wait for enable intx db bit to clear\n");
65 void sis_disable_intx(pqisrc_softstate_t *softs)
71 db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
73 db_reg &= ~SIS_ENABLE_INTX;
74 PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
75 LEGACY_SIS_IDBR, db_reg);
80 void sis_disable_interrupt(pqisrc_softstate_t *softs)
84 switch(softs->intr_type) {
86 pqisrc_configure_legacy_intx(softs,false);
87 sis_disable_intx(softs);
91 sis_disable_msix(softs);
94 DBG_ERR("Inerrupt mode none!\n");
101 /* Trigger a NMI as part of taking controller offline procedure */
102 void pqisrc_trigger_nmi_sis(pqisrc_softstate_t *softs)
107 PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
108 LEGACY_SIS_IDBR, LE_32(TRIGGER_NMI_SIS));
112 /* Switch the adapter back to SIS mode during uninitialization */
113 int pqisrc_reenable_sis(pqisrc_softstate_t *softs)
115 int ret = PQI_STATUS_SUCCESS;
116 uint32_t timeout = SIS_ENABLE_TIMEOUT;
120 PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
121 LEGACY_SIS_IDBR, LE_32(REENABLE_SIS));
123 COND_WAIT(((PCI_MEM_GET32(softs, &softs->ioa_reg->ioa_to_host_db, LEGACY_SIS_ODBR_R) &
124 REENABLE_SIS) == 0), timeout)
126 DBG_WARN(" [ %s ] failed to re enable sis\n",__func__);
127 ret = PQI_STATUS_TIMEOUT;
134 /* Validate the FW status PQI_CTRL_KERNEL_UP_AND_RUNNING */
135 int pqisrc_check_fw_status(pqisrc_softstate_t *softs)
137 int ret = PQI_STATUS_SUCCESS;
138 uint32_t timeout = SIS_STATUS_OK_TIMEOUT;
143 COND_WAIT((GET_FW_STATUS(softs) &
144 PQI_CTRL_KERNEL_UP_AND_RUNNING), timeout);
146 DBG_ERR("FW check status timedout\n");
147 ret = PQI_STATUS_TIMEOUT;
154 /* Function used to submit a SIS command to the adapter */
155 static int pqisrc_send_sis_cmd(pqisrc_softstate_t *softs,
158 int ret = PQI_STATUS_SUCCESS;
160 uint32_t timeout = SIS_CMD_COMPLETE_TIMEOUT;
166 /* Copy Command to mailbox */
167 for (i = 0; i < 6; i++)
168 PCI_MEM_PUT32(softs, &softs->ioa_reg->mb[i],
169 LEGACY_SIS_SRCV_MAILBOX+i*4, LE_32(mb[i]));
171 PCI_MEM_PUT32(softs, &softs->ioa_reg->ioa_to_host_db_clr,
172 LEGACY_SIS_ODBR_R, LE_32(0x1000));
174 /* Submit the command */
175 PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
176 LEGACY_SIS_IDBR, LE_32(SIS_CMD_SUBMIT));
179 /* Wait for 20 milli sec to poll */
180 OS_BUSYWAIT(SIS_POLL_START_WAIT_TIME);
183 val = PCI_MEM_GET32(softs, &softs->ioa_reg->ioa_to_host_db, LEGACY_SIS_ODBR_R);
185 DBG_FUNC("val : %x\n",val);
186 /* Spin waiting for the command to complete */
187 COND_WAIT((PCI_MEM_GET32(softs, &softs->ioa_reg->ioa_to_host_db, LEGACY_SIS_ODBR_R) &
188 SIS_CMD_COMPLETE), timeout);
190 DBG_ERR("Sync command %x, timedout\n", mb[0]);
191 ret = PQI_STATUS_TIMEOUT;
194 /* Check command status */
195 mb[0] = LE_32(PCI_MEM_GET32(softs, &softs->ioa_reg->mb[0], LEGACY_SIS_SRCV_MAILBOX));
197 if (mb[0] != SIS_CMD_STATUS_SUCCESS) {
198 DBG_ERR("SIS cmd failed with status = 0x%x\n",
200 ret = PQI_STATUS_FAILURE;
204 /* Copy the mailbox back */
205 for (i = 1; i < 6; i++)
206 mb[i] = LE_32(PCI_MEM_GET32(softs, &softs->ioa_reg->mb[i], LEGACY_SIS_SRCV_MAILBOX+i*4));
212 DBG_FUNC("OUT failed\n");
216 /* First SIS command for the adapter to check PQI support */
217 int pqisrc_get_adapter_properties(pqisrc_softstate_t *softs,
218 uint32_t *prop, uint32_t *ext_prop)
220 int ret = PQI_STATUS_SUCCESS;
221 uint32_t mb[6] = {0};
225 mb[0] = SIS_CMD_GET_ADAPTER_PROPERTIES;
226 ret = pqisrc_send_sis_cmd(softs, mb);
228 DBG_INIT("GET_PROPERTIES prop = %x, ext_prop = %x\n",
238 /* Second SIS command to the adapter GET_COMM_PREFERRED_SETTINGS */
239 int pqisrc_get_preferred_settings(pqisrc_softstate_t *softs)
241 int ret = PQI_STATUS_SUCCESS;
242 uint32_t mb[6] = {0};
246 mb[0] = SIS_CMD_GET_COMM_PREFERRED_SETTINGS;
247 ret = pqisrc_send_sis_cmd(softs, mb);
249 /* 31:16 maximum command size in KB */
250 softs->pref_settings.max_cmd_size = mb[1] >> 16;
251 /* 15:00: Maximum FIB size in bytes */
252 softs->pref_settings.max_fib_size = mb[1] & 0x0000FFFF;
253 DBG_INIT("cmd size = %x, fib size = %x\n",
254 softs->pref_settings.max_cmd_size,
255 softs->pref_settings.max_fib_size);
262 /* Get supported PQI capabilities from the adapter */
263 int pqisrc_get_sis_pqi_cap(pqisrc_softstate_t *softs)
265 int ret = PQI_STATUS_SUCCESS;
266 uint32_t mb[6] = {0};
270 mb[0] = SIS_CMD_GET_PQI_CAPABILITIES;
271 ret = pqisrc_send_sis_cmd(softs, mb);
273 softs->pqi_cap.max_sg_elem = mb[1];
274 softs->pqi_cap.max_transfer_size = mb[2];
275 softs->pqi_cap.max_outstanding_io = mb[3];
276 softs->pqi_cap.conf_tab_off = mb[4];
277 softs->pqi_cap.conf_tab_sz = mb[5];
279 DBG_INIT("max_sg_elem = %x\n",
280 softs->pqi_cap.max_sg_elem);
281 DBG_INIT("max_transfer_size = %x\n",
282 softs->pqi_cap.max_transfer_size);
283 DBG_INIT("max_outstanding_io = %x\n",
284 softs->pqi_cap.max_outstanding_io);
291 /* Send INIT STRUCT BASE ADDR - one of the SIS command */
292 int pqisrc_init_struct_base(pqisrc_softstate_t *softs)
294 int ret = PQI_STATUS_SUCCESS;
295 uint32_t elem_size = 0;
296 uint32_t num_elem = 0;
297 struct dma_mem init_struct_mem = {0};
298 struct init_base_struct *init_struct = NULL;
299 uint32_t mb[6] = {0};
303 /* Allocate init struct */
304 memset(&init_struct_mem, 0, sizeof(struct dma_mem));
305 init_struct_mem.size = sizeof(struct init_base_struct);
306 init_struct_mem.align = PQISRC_INIT_STRUCT_DMA_ALIGN;
307 init_struct_mem.tag = "init_struct";
308 ret = os_dma_mem_alloc(softs, &init_struct_mem);
310 DBG_ERR("Failed to Allocate error buffer ret : %d\n",
315 /* Calculate error buffer size */
316 /* The valid tag values are from 1, 2, ..., softs->max_outstanding_io
317 * The rcb and error buffer will be accessed by using the tag as index
318 * As 0 tag index is not used, we need to allocate one extra.
320 num_elem = softs->pqi_cap.max_outstanding_io + 1;
321 elem_size = PQISRC_ERR_BUF_ELEM_SIZE;
322 softs->err_buf_dma_mem.size = num_elem * elem_size;
324 /* Allocate error buffer */
325 softs->err_buf_dma_mem.align = PQISRC_ERR_BUF_DMA_ALIGN;
326 softs->err_buf_dma_mem.tag = "error_buffer";
327 ret = os_dma_mem_alloc(softs, &softs->err_buf_dma_mem);
329 DBG_ERR("Failed to Allocate error buffer ret : %d\n",
331 goto err_error_buf_alloc;
334 /* Fill init struct */
335 init_struct = (struct init_base_struct *)DMA_TO_VIRT(&init_struct_mem);
336 init_struct->revision = PQISRC_INIT_STRUCT_REVISION;
337 init_struct->flags = 0;
338 init_struct->err_buf_paddr_l = DMA_PHYS_LOW(&softs->err_buf_dma_mem);
339 init_struct->err_buf_paddr_h = DMA_PHYS_HIGH(&softs->err_buf_dma_mem);
340 init_struct->err_buf_elem_len = elem_size;
341 init_struct->err_buf_num_elem = num_elem;
343 mb[0] = SIS_CMD_INIT_BASE_STRUCT_ADDRESS;
344 mb[1] = DMA_PHYS_LOW(&init_struct_mem);
345 mb[2] = DMA_PHYS_HIGH(&init_struct_mem);
346 mb[3] = init_struct_mem.size;
348 ret = pqisrc_send_sis_cmd(softs, mb);
353 os_dma_mem_free(softs, &init_struct_mem);
357 os_dma_mem_free(softs, &softs->err_buf_dma_mem);
359 os_dma_mem_free(softs, &init_struct_mem);
361 DBG_FUNC("OUT failed %d\n", ret);
362 return PQI_STATUS_FAILURE;
366 * SIS initialization of the adapter in a sequence of
367 * - GET_ADAPTER_PROPERTIES
368 * - GET_COMM_PREFERRED_SETTINGS
369 * - GET_PQI_CAPABILITIES
370 * - INIT_STRUCT_BASE ADDR
372 int pqisrc_sis_init(pqisrc_softstate_t *softs)
374 int ret = PQI_STATUS_SUCCESS;
376 uint32_t ext_prop = 0;
380 ret = pqisrc_force_sis(softs);
382 DBG_ERR("Failed to switch back the adapter to SIS mode!\n");
386 /* Check FW status ready */
387 ret = pqisrc_check_fw_status(softs);
389 DBG_ERR("PQI Controller is not ready !!!\n");
393 /* Check For PQI support(19h) */
394 ret = pqisrc_get_adapter_properties(softs, &prop, &ext_prop);
396 DBG_ERR("Failed to get adapter properties\n");
399 if (!((prop & SIS_SUPPORT_EXT_OPT) &&
400 (ext_prop & SIS_SUPPORT_PQI))) {
401 DBG_ERR("PQI Mode Not Supported\n");
402 ret = PQI_STATUS_FAILURE;
406 softs->pqi_reset_quiesce_allowed = false;
407 if (ext_prop & SIS_SUPPORT_PQI_RESET_QUIESCE)
408 softs->pqi_reset_quiesce_allowed = true;
410 /* Send GET_COMM_PREFERRED_SETTINGS (26h) */
411 ret = pqisrc_get_preferred_settings(softs);
413 DBG_ERR("Failed to get adapter pref settings\n");
417 /* Get PQI settings , 3000h*/
418 ret = pqisrc_get_sis_pqi_cap(softs);
420 DBG_ERR("Failed to get PQI Capabilities\n");
424 /* Init struct base addr */
425 ret = pqisrc_init_struct_base(softs);
427 DBG_ERR("Failed to set init struct base addr\n");
435 DBG_FUNC("OUT failed\n");
439 /* Deallocate the resources used during SIS initialization */
440 void pqisrc_sis_uninit(pqisrc_softstate_t *softs)
444 os_dma_mem_free(softs, &softs->err_buf_dma_mem);
445 os_resource_free(softs);
451 int pqisrc_sis_wait_for_db_bit_to_clear(pqisrc_softstate_t *softs, uint32_t bit)
453 int rcode = PQI_STATUS_SUCCESS;
455 uint32_t loop_cnt = 0;
460 db_reg = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
462 if ((db_reg & bit) == 0)
464 if (GET_FW_STATUS(softs) & PQI_CTRL_KERNEL_PANIC) {
465 DBG_ERR("controller kernel panic\n");
466 rcode = PQI_STATUS_FAILURE;
469 if (loop_cnt++ == SIS_DB_BIT_CLEAR_TIMEOUT_CNT) {
470 DBG_ERR("door-bell reg bit 0x%x not cleared\n", bit);
471 rcode = PQI_STATUS_TIMEOUT;