]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/smartpqi/smartpqi_init.c
Import PCG-C into sys/contrib
[FreeBSD/FreeBSD.git] / sys / dev / smartpqi / smartpqi_init.c
1 /*-
2  * Copyright (c) 2018 Microsemi Corporation.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  */
26
27 /* $FreeBSD$ */
28
29 #include "smartpqi_includes.h"
30
31 /*
32  * Request the adapter to get PQI capabilities supported.
33  */
34 static int pqisrc_report_pqi_capability(pqisrc_softstate_t *softs)
35 {
36         int ret = PQI_STATUS_SUCCESS;
37         
38         DBG_FUNC("IN\n");
39
40         gen_adm_req_iu_t        admin_req;
41         gen_adm_resp_iu_t       admin_resp;
42         dma_mem_t               pqi_cap_dma_buf;
43         pqi_dev_cap_t           *capability = NULL;
44         pqi_iu_layer_desc_t     *iu_layer_desc = NULL;
45
46         /* Allocate Non DMA memory */
47         capability = os_mem_alloc(softs, sizeof(*capability));
48         if (!capability) {
49                 DBG_ERR("Failed to allocate memory for capability\n");
50                 ret = PQI_STATUS_FAILURE;
51                 goto err_out;
52         }
53
54         memset(&admin_req, 0, sizeof(admin_req));
55         memset(&admin_resp, 0, sizeof(admin_resp));
56
57         memset(&pqi_cap_dma_buf, 0, sizeof(struct dma_mem));
58         pqi_cap_dma_buf.tag = "pqi_cap_buf";
59         pqi_cap_dma_buf.size = REPORT_PQI_DEV_CAP_DATA_BUF_SIZE;
60         pqi_cap_dma_buf.align = PQISRC_DEFAULT_DMA_ALIGN;
61
62         ret = os_dma_mem_alloc(softs, &pqi_cap_dma_buf);
63         if (ret) {
64                 DBG_ERR("Failed to allocate capability DMA buffer : %d\n", ret);
65                 goto err_dma_alloc;
66         }
67         
68         admin_req.fn_code = PQI_FUNCTION_REPORT_DEV_CAP;
69         admin_req.req_type.general_func.buf_size = pqi_cap_dma_buf.size;
70         admin_req.req_type.general_func.sg_desc.length = pqi_cap_dma_buf.size;
71         admin_req.req_type.general_func.sg_desc.addr = pqi_cap_dma_buf.dma_addr;
72         admin_req.req_type.general_func.sg_desc.type =  SGL_DESCRIPTOR_CODE_DATA_BLOCK;
73
74         ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp);
75         if( PQI_STATUS_SUCCESS == ret) {
76                 memcpy(capability,
77                         pqi_cap_dma_buf.virt_addr,
78                         pqi_cap_dma_buf.size);
79         } else {
80                 DBG_ERR("Failed to send admin req report pqi device capability\n");
81                 goto err_admin_req;
82                 
83         }
84
85         softs->pqi_dev_cap.max_iqs = capability->max_iqs;
86         softs->pqi_dev_cap.max_iq_elements = capability->max_iq_elements;
87         softs->pqi_dev_cap.max_iq_elem_len = capability->max_iq_elem_len;
88         softs->pqi_dev_cap.min_iq_elem_len = capability->min_iq_elem_len;
89         softs->pqi_dev_cap.max_oqs = capability->max_oqs;
90         softs->pqi_dev_cap.max_oq_elements = capability->max_oq_elements;
91         softs->pqi_dev_cap.max_oq_elem_len = capability->max_oq_elem_len;
92         softs->pqi_dev_cap.intr_coales_time_granularity = capability->intr_coales_time_granularity;
93
94         iu_layer_desc = &capability->iu_layer_desc[PQI_PROTOCOL_SOP];
95         softs->max_ib_iu_length_per_fw = iu_layer_desc->max_ib_iu_len;
96         softs->ib_spanning_supported = iu_layer_desc->ib_spanning_supported;
97         softs->ob_spanning_supported = iu_layer_desc->ob_spanning_supported;
98
99         DBG_INIT("softs->pqi_dev_cap.max_iqs: %d\n", softs->pqi_dev_cap.max_iqs);
100         DBG_INIT("softs->pqi_dev_cap.max_iq_elements: %d\n", softs->pqi_dev_cap.max_iq_elements);
101         DBG_INIT("softs->pqi_dev_cap.max_iq_elem_len: %d\n", softs->pqi_dev_cap.max_iq_elem_len);
102         DBG_INIT("softs->pqi_dev_cap.min_iq_elem_len: %d\n", softs->pqi_dev_cap.min_iq_elem_len);
103         DBG_INIT("softs->pqi_dev_cap.max_oqs: %d\n", softs->pqi_dev_cap.max_oqs);
104         DBG_INIT("softs->pqi_dev_cap.max_oq_elements: %d\n", softs->pqi_dev_cap.max_oq_elements);
105         DBG_INIT("softs->pqi_dev_cap.max_oq_elem_len: %d\n", softs->pqi_dev_cap.max_oq_elem_len);
106         DBG_INIT("softs->pqi_dev_cap.intr_coales_time_granularity: %d\n", softs->pqi_dev_cap.intr_coales_time_granularity);
107         DBG_INIT("softs->max_ib_iu_length_per_fw: %d\n", softs->max_ib_iu_length_per_fw);
108         DBG_INIT("softs->ib_spanning_supported: %d\n", softs->ib_spanning_supported);
109         DBG_INIT("softs->ob_spanning_supported: %d\n", softs->ob_spanning_supported);
110         
111
112         os_mem_free(softs, (void *)capability,
113                     REPORT_PQI_DEV_CAP_DATA_BUF_SIZE);
114         os_dma_mem_free(softs, &pqi_cap_dma_buf);
115
116         DBG_FUNC("OUT\n");
117         return ret;
118
119 err_admin_req:
120         os_dma_mem_free(softs, &pqi_cap_dma_buf);
121 err_dma_alloc:
122         if (capability)
123                 os_mem_free(softs, (void *)capability,
124                             REPORT_PQI_DEV_CAP_DATA_BUF_SIZE);
125 err_out:
126         DBG_FUNC("failed OUT\n");
127         return PQI_STATUS_FAILURE;
128 }
129
130 /*
131  * Function used to deallocate the used rcb.
132  */
133 void pqisrc_free_rcb(pqisrc_softstate_t *softs, int req_count)
134 {
135         
136         uint32_t num_req;
137         size_t size;
138         int i;
139
140         DBG_FUNC("IN\n");
141         num_req = softs->max_outstanding_io + 1;
142         size = num_req * sizeof(rcb_t);
143         for (i = 1; i < req_count; i++)
144                 os_dma_mem_free(softs, &softs->sg_dma_desc[i]);
145         os_mem_free(softs, (void *)softs->rcb, size);
146         softs->rcb = NULL;
147         DBG_FUNC("OUT\n");
148 }
149
150
151 /*
152  * Allocate memory for rcb and SG descriptors.
153  */
154 static int pqisrc_allocate_rcb(pqisrc_softstate_t *softs)
155 {
156         int ret = PQI_STATUS_SUCCESS;
157         int i = 0;
158         uint32_t num_req = 0;
159         uint32_t sg_buf_size = 0;
160         uint64_t alloc_size = 0;
161         rcb_t *rcb = NULL;
162         rcb_t *prcb = NULL;
163         DBG_FUNC("IN\n");
164
165         /* Set maximum outstanding requests */
166         /* The valid tag values are from 1, 2, ..., softs->max_outstanding_io
167          * The rcb will be accessed by using the tag as index
168          * * As 0 tag index is not used, we need to allocate one extra.
169          */
170         softs->max_outstanding_io = softs->pqi_cap.max_outstanding_io;
171         num_req = softs->max_outstanding_io + 1;
172         DBG_INIT("Max Outstanding IO reset to %d\n", num_req);
173
174         alloc_size = num_req * sizeof(rcb_t);
175
176         /* Allocate Non DMA memory */
177         rcb = os_mem_alloc(softs, alloc_size);
178         if (!rcb) {
179                 DBG_ERR("Failed to allocate memory for rcb\n");
180                 ret = PQI_STATUS_FAILURE;
181                 goto err_out;
182         }
183         softs->rcb = rcb;
184         
185         /* Allocate sg dma memory for sg chain  */
186         sg_buf_size = softs->pqi_cap.max_sg_elem *
187                         sizeof(sgt_t);
188
189         prcb = &softs->rcb[1];
190         /* Initialize rcb */
191         for(i=1; i < num_req; i++) {
192                 char tag[15];
193                 sprintf(tag, "sg_dma_buf%d", i);
194                 softs->sg_dma_desc[i].tag = tag;
195                 softs->sg_dma_desc[i].size = sg_buf_size;
196                 softs->sg_dma_desc[i].align = PQISRC_DEFAULT_DMA_ALIGN;
197
198                 ret = os_dma_mem_alloc(softs, &softs->sg_dma_desc[i]);
199                 if (ret) {
200                         DBG_ERR("Failed to Allocate sg desc %d\n", ret);
201                         ret = PQI_STATUS_FAILURE;
202                         goto error;
203                 }
204                 prcb->sg_chain_virt = (sgt_t *)(softs->sg_dma_desc[i].virt_addr);
205                 prcb->sg_chain_dma = (dma_addr_t)(softs->sg_dma_desc[i].dma_addr);
206                 prcb ++;
207         }
208
209         DBG_FUNC("OUT\n");
210         return ret;
211 error:
212         pqisrc_free_rcb(softs, i);
213 err_out:
214         DBG_FUNC("failed OUT\n");
215         return ret;
216 }
217
218 /*
219  * Function used to decide the operational queue configuration params
220  * - no of ibq/obq, shared/non-shared interrupt resource, IU spanning support
221  */
222 void pqisrc_decide_opq_config(pqisrc_softstate_t *softs)
223 {
224         uint16_t total_iq_elements;
225
226         DBG_FUNC("IN\n");
227
228         DBG_INIT("softs->intr_count : %d  softs->num_cpus_online : %d", 
229                 softs->intr_count, softs->num_cpus_online);
230         
231         if (softs->intr_count == 1 || softs->num_cpus_online == 1) {
232                 /* Share the event and Operational queue. */
233                 softs->num_op_obq = 1;
234                 softs->share_opq_and_eventq = true;
235         }
236         else {
237                 /* Note :  One OBQ (OBQ0) reserved for event queue */
238                 softs->num_op_obq = MIN(softs->num_cpus_online, 
239                                         softs->intr_count) - 1;
240                 softs->num_op_obq = softs->intr_count - 1;
241                 softs->share_opq_and_eventq = false;
242         }
243
244         /* 
245          * softs->num_cpus_online is set as number of physical CPUs,
246          * So we can have more queues/interrupts .
247          */
248         if (softs->intr_count > 1)       
249                 softs->share_opq_and_eventq = false;
250         
251         DBG_INIT("softs->num_op_obq : %d\n",softs->num_op_obq);
252
253         softs->num_op_raid_ibq = softs->num_op_obq;
254         softs->num_op_aio_ibq = softs->num_op_raid_ibq;
255         softs->ibq_elem_size =  softs->pqi_dev_cap.max_iq_elem_len * 16;
256         softs->obq_elem_size = softs->pqi_dev_cap.max_oq_elem_len * 16;
257         if (softs->max_ib_iu_length_per_fw == 256 &&
258             softs->ob_spanning_supported) {
259                 /* older f/w that doesn't actually support spanning. */
260                 softs->max_ib_iu_length = softs->ibq_elem_size;
261         } else {
262                 /* max. inbound IU length is an multiple of our inbound element size. */
263                 softs->max_ib_iu_length =
264                         (softs->max_ib_iu_length_per_fw / softs->ibq_elem_size) *
265                          softs->ibq_elem_size;
266                                            
267         }
268         /* If Max. Outstanding IO came with Max. Spanning element count then, 
269                 needed elements per IO are multiplication of
270                 Max.Outstanding IO and  Max.Spanning element */
271         total_iq_elements = (softs->max_outstanding_io * 
272                 (softs->max_ib_iu_length / softs->ibq_elem_size));
273         
274         softs->num_elem_per_op_ibq = total_iq_elements / softs->num_op_raid_ibq;
275         softs->num_elem_per_op_ibq = MIN(softs->num_elem_per_op_ibq, 
276                 softs->pqi_dev_cap.max_iq_elements);
277         
278         softs->num_elem_per_op_obq = softs->max_outstanding_io / softs->num_op_obq; 
279         softs->num_elem_per_op_obq = MIN(softs->num_elem_per_op_obq,
280                 softs->pqi_dev_cap.max_oq_elements);
281
282         softs->max_sg_per_iu = ((softs->max_ib_iu_length - 
283                                 softs->ibq_elem_size) /
284                                 sizeof(sgt_t)) +
285                                 MAX_EMBEDDED_SG_IN_FIRST_IU;
286
287         DBG_INIT("softs->max_ib_iu_length: %d\n", softs->max_ib_iu_length);
288         DBG_INIT("softs->num_elem_per_op_ibq: %d\n", softs->num_elem_per_op_ibq);
289         DBG_INIT("softs->num_elem_per_op_obq: %d\n", softs->num_elem_per_op_obq);
290         DBG_INIT("softs->max_sg_per_iu: %d\n", softs->max_sg_per_iu);
291
292         DBG_FUNC("OUT\n");
293 }
294
295 /*
296  * Configure the operational queue parameters.
297  */
298 int pqisrc_configure_op_queues(pqisrc_softstate_t *softs)
299 {
300         int ret = PQI_STATUS_SUCCESS;
301         
302         /* Get the PQI capability, 
303                 REPORT PQI DEVICE CAPABILITY request */
304         ret = pqisrc_report_pqi_capability(softs);
305         if (ret) {
306                 DBG_ERR("Failed to send report pqi dev capability request : %d\n",
307                                 ret);
308                 goto err_out;
309         }
310
311         /* Reserve required no of slots for internal requests */
312         softs->max_io_for_scsi_ml = softs->max_outstanding_io - PQI_RESERVED_IO_SLOTS_CNT;
313
314         /* Decide the Op queue configuration */
315         pqisrc_decide_opq_config(softs);        
316         
317         DBG_FUNC("OUT\n");
318         return ret;
319                 
320 err_out:
321         DBG_FUNC("OUT failed\n");
322         return ret;
323 }
324
325 /*
326  * Validate the PQI mode of adapter.
327  */
328 int pqisrc_check_pqimode(pqisrc_softstate_t *softs)
329 {
330         int ret = PQI_STATUS_FAILURE;
331         int tmo = 0;
332         uint64_t signature = 0;
333
334         DBG_FUNC("IN\n");
335
336         /* Check the PQI device signature */
337         tmo = PQISRC_PQIMODE_READY_TIMEOUT;
338         do {
339                 signature = LE_64(PCI_MEM_GET64(softs, &softs->pqi_reg->signature, PQI_SIGNATURE));
340         
341                 if (memcmp(&signature, PQISRC_PQI_DEVICE_SIGNATURE,
342                                 sizeof(uint64_t)) == 0) {
343                         ret = PQI_STATUS_SUCCESS;
344                         break;
345                 }
346                 OS_SLEEP(PQISRC_MODE_READY_POLL_INTERVAL);
347         } while (tmo--);
348
349         PRINT_PQI_SIGNATURE(signature);
350
351         if (tmo <= 0) {
352                 DBG_ERR("PQI Signature is invalid\n");
353                 ret = PQI_STATUS_TIMEOUT;
354                 goto err_out;
355         }
356
357         tmo = PQISRC_PQIMODE_READY_TIMEOUT;
358         /* Check function and status code for the device */
359         COND_WAIT((PCI_MEM_GET64(softs, &softs->pqi_reg->admin_q_config,
360                 PQI_ADMINQ_CONFIG) == PQI_ADMIN_QUEUE_CONF_FUNC_STATUS_IDLE), tmo);
361         if (!tmo) {
362                 DBG_ERR("PQI device is not in IDLE state\n");
363                 ret = PQI_STATUS_TIMEOUT;
364                 goto err_out;
365         }
366
367
368         tmo = PQISRC_PQIMODE_READY_TIMEOUT;
369         /* Check the PQI device status register */
370         COND_WAIT(LE_32(PCI_MEM_GET32(softs, &softs->pqi_reg->pqi_dev_status, PQI_DEV_STATUS)) &
371                                 PQI_DEV_STATE_AT_INIT, tmo);
372         if (!tmo) {
373                 DBG_ERR("PQI Registers are not ready\n");
374                 ret = PQI_STATUS_TIMEOUT;
375                 goto err_out;
376         }
377
378         DBG_FUNC("OUT\n");
379         return ret;
380 err_out:
381         DBG_FUNC("OUT failed\n");
382         return ret;
383 }
384
385 /*
386  * Get the PQI configuration table parameters.
387  * Currently using for heart-beat counter scratch-pad register.
388  */
389 int pqisrc_process_config_table(pqisrc_softstate_t *softs)
390 {
391         int ret = PQI_STATUS_FAILURE;
392         uint32_t config_table_size;
393         uint32_t section_off;
394         uint8_t *config_table_abs_addr;
395         struct pqi_conf_table *conf_table;
396         struct pqi_conf_table_section_header *section_hdr;
397
398         config_table_size = softs->pqi_cap.conf_tab_sz;
399
400         if (config_table_size < sizeof(*conf_table) ||
401                 config_table_size > PQI_CONF_TABLE_MAX_LEN) {
402                 DBG_ERR("Invalid PQI conf table length of %u\n",
403                         config_table_size);
404                 return ret;
405         }
406
407         conf_table = os_mem_alloc(softs, config_table_size);
408         if (!conf_table) {
409                 DBG_ERR("Failed to allocate memory for PQI conf table\n");
410                 return ret;
411         }
412
413         config_table_abs_addr = (uint8_t *)(softs->pci_mem_base_vaddr +
414                                         softs->pqi_cap.conf_tab_off);
415
416         PCI_MEM_GET_BUF(softs, config_table_abs_addr,
417                         softs->pqi_cap.conf_tab_off,
418                         (uint8_t*)conf_table, config_table_size);
419
420
421         if (memcmp(conf_table->sign, PQI_CONF_TABLE_SIGNATURE,
422                         sizeof(conf_table->sign)) != 0) {
423                 DBG_ERR("Invalid PQI config signature\n");
424                 goto out;
425         }
426
427         section_off = LE_32(conf_table->first_section_off);
428
429         while (section_off) {
430
431                 if (section_off+ sizeof(*section_hdr) >= config_table_size) {
432                         DBG_ERR("PQI config table section offset (%u) beyond \
433                         end of config table (config table length: %u)\n",
434                                         section_off, config_table_size);
435                         break;
436                 }
437                 
438                 section_hdr = (struct pqi_conf_table_section_header *)((uint8_t *)conf_table + section_off);
439                 
440                 switch (LE_16(section_hdr->section_id)) {
441                 case PQI_CONF_TABLE_SECTION_GENERAL_INFO:
442                 case PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES:
443                 case PQI_CONF_TABLE_SECTION_FIRMWARE_ERRATA:
444                 case PQI_CONF_TABLE_SECTION_DEBUG:
445                 break;
446                 case PQI_CONF_TABLE_SECTION_HEARTBEAT:
447                 softs->heartbeat_counter_off = softs->pqi_cap.conf_tab_off +
448                                                 section_off +
449                                                 offsetof(struct pqi_conf_table_heartbeat,
450                                                 heartbeat_counter);
451                 softs->heartbeat_counter_abs_addr = (uint64_t *)(softs->pci_mem_base_vaddr +
452                                                         softs->heartbeat_counter_off);
453                 ret = PQI_STATUS_SUCCESS;
454                 break;
455                 default:
456                 DBG_INFO("unrecognized PQI config table section ID: 0x%x\n",
457                                         LE_16(section_hdr->section_id));
458                 break;
459                 }
460                 section_off = LE_16(section_hdr->next_section_off);
461         }
462 out:
463         os_mem_free(softs, (void *)conf_table,config_table_size);
464         return ret;
465 }
466
467 /* Wait for PQI reset completion for the adapter*/
468 int pqisrc_wait_for_pqi_reset_completion(pqisrc_softstate_t *softs)
469 {
470         int ret = PQI_STATUS_SUCCESS;
471         pqi_reset_reg_t reset_reg;
472         int pqi_reset_timeout = 0;
473         uint64_t val = 0;
474         uint32_t max_timeout = 0;
475
476         val = PCI_MEM_GET64(softs, &softs->pqi_reg->pqi_dev_adminq_cap, PQI_ADMINQ_CAP);
477
478         max_timeout = (val & 0xFFFF00000000) >> 32;
479
480         DBG_INIT("max_timeout for PQI reset completion in 100 msec units = %u\n", max_timeout);
481
482         while(1) {
483                 if (pqi_reset_timeout++ == max_timeout) {
484                         return PQI_STATUS_TIMEOUT; 
485                 }
486                 OS_SLEEP(PQI_RESET_POLL_INTERVAL);/* 100 msec */
487                 reset_reg.all_bits = PCI_MEM_GET32(softs,
488                         &softs->pqi_reg->dev_reset, PQI_DEV_RESET);
489                 if (reset_reg.bits.reset_action == PQI_RESET_ACTION_COMPLETED)
490                         break;
491         }
492
493         return ret;
494 }
495
496 /*
497  * Function used to perform PQI hard reset.
498  */
499 int pqi_reset(pqisrc_softstate_t *softs)
500 {
501         int ret = PQI_STATUS_SUCCESS;
502         uint32_t val = 0;
503         pqi_reset_reg_t pqi_reset_reg;
504
505         DBG_FUNC("IN\n");
506
507         if (true == softs->ctrl_in_pqi_mode) { 
508         
509                 if (softs->pqi_reset_quiesce_allowed) {
510                         val = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
511                                         LEGACY_SIS_IDBR);
512                         val |= SIS_PQI_RESET_QUIESCE;
513                         PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
514                                         LEGACY_SIS_IDBR, LE_32(val));
515                         ret = pqisrc_sis_wait_for_db_bit_to_clear(softs, SIS_PQI_RESET_QUIESCE);
516                         if (ret) {
517                                 DBG_ERR("failed with error %d during quiesce\n", ret);
518                                 return ret;
519                         }
520                 }
521
522                 pqi_reset_reg.all_bits = 0;
523                 pqi_reset_reg.bits.reset_type = PQI_RESET_TYPE_HARD_RESET;
524                 pqi_reset_reg.bits.reset_action = PQI_RESET_ACTION_RESET;
525
526                 PCI_MEM_PUT32(softs, &softs->pqi_reg->dev_reset, PQI_DEV_RESET,
527                         LE_32(pqi_reset_reg.all_bits));
528
529                 ret = pqisrc_wait_for_pqi_reset_completion(softs);
530                 if (ret) {
531                         DBG_ERR("PQI reset timed out: ret = %d!\n", ret);
532                         return ret;
533                 }
534         }
535         softs->ctrl_in_pqi_mode = false;
536         DBG_FUNC("OUT\n");
537         return ret;
538 }
539
540 /*
541  * Initialize the adapter with supported PQI configuration.
542  */
543 int pqisrc_pqi_init(pqisrc_softstate_t *softs)
544 {
545         int ret = PQI_STATUS_SUCCESS;
546
547         DBG_FUNC("IN\n");
548
549         /* Check the PQI signature */
550         ret = pqisrc_check_pqimode(softs);
551         if(ret) {
552                 DBG_ERR("failed to switch to pqi\n");
553                 goto err_out;
554         }
555
556         PQI_SAVE_CTRL_MODE(softs, CTRL_PQI_MODE);
557         softs->ctrl_in_pqi_mode = true;
558         
559         /* Get the No. of Online CPUs,NUMA/Processor config from OS */
560         ret = os_get_processor_config(softs);
561         if (ret) {
562                 DBG_ERR("Failed to get processor config from OS %d\n",
563                         ret);
564                 goto err_out;
565         }
566         
567         softs->intr_type = INTR_TYPE_NONE;      
568
569         /* Get the interrupt count, type, priority available from OS */
570         ret = os_get_intr_config(softs);
571         if (ret) {
572                 DBG_ERR("Failed to get interrupt config from OS %d\n",
573                         ret);
574                 goto err_out;
575         }
576
577         /*Enable/Set Legacy INTx Interrupt mask clear pqi register,
578          *if allocated interrupt is legacy type.
579          */
580         if (INTR_TYPE_FIXED == softs->intr_type) {
581                 pqisrc_configure_legacy_intx(softs, true);
582                 sis_enable_intx(softs);
583         }
584
585         /* Create Admin Queue pair*/            
586         ret = pqisrc_create_admin_queue(softs);
587         if(ret) {
588                 DBG_ERR("Failed to configure admin queue\n");
589                 goto err_admin_queue;
590         }
591
592         /* For creating event and IO operational queues we have to submit 
593            admin IU requests.So Allocate resources for submitting IUs */  
594              
595         /* Allocate the request container block (rcb) */
596         ret = pqisrc_allocate_rcb(softs);
597         if (ret == PQI_STATUS_FAILURE) {
598                 DBG_ERR("Failed to allocate rcb \n");
599                 goto err_rcb;
600         }
601
602         /* Allocate & initialize request id queue */
603         ret = pqisrc_init_taglist(softs,&softs->taglist,
604                                 softs->max_outstanding_io);
605         if (ret) {
606                 DBG_ERR("Failed to allocate memory for request id q : %d\n",
607                         ret);
608                 goto err_taglist;
609         }
610
611         ret = pqisrc_configure_op_queues(softs);
612         if (ret) {
613                         DBG_ERR("Failed to configure op queue\n");
614                         goto err_config_opq;
615         }
616
617         /* Create Operational queues */
618         ret = pqisrc_create_op_queues(softs);
619         if(ret) {
620                 DBG_ERR("Failed to create op queue\n");
621                 ret = PQI_STATUS_FAILURE;
622                 goto err_create_opq;
623         }
624
625         softs->ctrl_online = true;
626
627         DBG_FUNC("OUT\n");
628         return ret;
629
630 err_create_opq:
631 err_config_opq:
632         pqisrc_destroy_taglist(softs,&softs->taglist);
633 err_taglist:
634         pqisrc_free_rcb(softs, softs->max_outstanding_io + 1);          
635 err_rcb:
636         pqisrc_destroy_admin_queue(softs);
637 err_admin_queue:
638         os_free_intr_config(softs);
639 err_out:
640         DBG_FUNC("OUT failed\n");
641         return PQI_STATUS_FAILURE;
642 }
643
644 /* */
645 int pqisrc_force_sis(pqisrc_softstate_t *softs)
646 {
647         int ret = PQI_STATUS_SUCCESS;
648
649         if (SIS_IS_KERNEL_PANIC(softs)) {
650                 DBG_INIT("Controller FW is not runnning");
651                 return PQI_STATUS_FAILURE;
652         }
653
654         if (PQI_GET_CTRL_MODE(softs) == CTRL_SIS_MODE) {
655                 return ret;
656         }
657
658         if (SIS_IS_KERNEL_UP(softs)) {
659                 PQI_SAVE_CTRL_MODE(softs, CTRL_SIS_MODE);
660                 return ret;
661         }
662         /* Disable interrupts ? */
663         sis_disable_interrupt(softs);
664
665         /* reset pqi, this will delete queues */
666         ret = pqi_reset(softs);
667         if (ret) {
668                 return ret;
669         }       
670         /* Re enable SIS */
671         ret = pqisrc_reenable_sis(softs);
672         if (ret) {
673                 return ret;
674         }
675
676         PQI_SAVE_CTRL_MODE(softs, CTRL_SIS_MODE);
677
678         return ret;     
679 }
680
681 int pqisrc_wait_for_cmnd_complete(pqisrc_softstate_t *softs)
682 {
683         int ret = PQI_STATUS_SUCCESS;
684         int tmo = PQI_CMND_COMPLETE_TMO;
685         
686         COND_WAIT((softs->taglist.num_elem == softs->max_outstanding_io), tmo);
687         if (!tmo) {
688                 DBG_ERR("Pending commands %x!!!",softs->taglist.num_elem);
689                 ret = PQI_STATUS_TIMEOUT;
690         }
691         return ret;
692 }
693
694 void pqisrc_complete_internal_cmds(pqisrc_softstate_t *softs)
695 {
696         int tag = 0;
697         rcb_t *rcb;
698         
699         for (tag = 1; tag <= softs->max_outstanding_io; tag++) {
700                 rcb = &softs->rcb[tag];
701                 if(rcb->req_pending && is_internal_req(rcb)) {
702                         rcb->status = REQUEST_FAILED;
703                         rcb->req_pending = false;
704                 }
705         }
706 }
707
708 /*
709  * Uninitialize the resources used during PQI initialization.
710  */
711 void pqisrc_pqi_uninit(pqisrc_softstate_t *softs)
712 {
713         int i, ret;
714
715         DBG_FUNC("IN\n");
716         
717         /* Wait for any rescan to finish */
718         pqisrc_wait_for_rescan_complete(softs);
719
720         /* Wait for commands to complete */
721         ret = pqisrc_wait_for_cmnd_complete(softs);
722         
723         /* Complete all pending commands. */
724         if(ret != PQI_STATUS_SUCCESS) {
725                 pqisrc_complete_internal_cmds(softs);
726                 os_complete_outstanding_cmds_nodevice(softs);
727         }
728
729     if(softs->devlist_lockcreated==true){    
730         os_uninit_spinlock(&softs->devlist_lock);
731         softs->devlist_lockcreated = false;
732     }
733     
734         for (i = 0; i <  softs->num_op_raid_ibq; i++) {
735         /* OP RAID IB Q */
736         if(softs->op_raid_ib_q[i].lockcreated==true){
737                 OS_UNINIT_PQILOCK(&softs->op_raid_ib_q[i].lock);
738                 softs->op_raid_ib_q[i].lockcreated = false;
739         }
740         
741         /* OP AIO IB Q */
742         if(softs->op_aio_ib_q[i].lockcreated==true){
743                 OS_UNINIT_PQILOCK(&softs->op_aio_ib_q[i].lock);
744                 softs->op_aio_ib_q[i].lockcreated = false;
745         }
746         }
747
748         /* Free Op queues */
749         os_dma_mem_free(softs, &softs->op_ibq_dma_mem);
750         os_dma_mem_free(softs, &softs->op_obq_dma_mem);
751         os_dma_mem_free(softs, &softs->event_q_dma_mem);
752         
753         /* Free  rcb */
754         pqisrc_free_rcb(softs, softs->max_outstanding_io + 1);
755
756         /* Free request id lists */
757         pqisrc_destroy_taglist(softs,&softs->taglist);
758
759         if(softs->admin_ib_queue.lockcreated==true){
760                 OS_UNINIT_PQILOCK(&softs->admin_ib_queue.lock); 
761                 softs->admin_ib_queue.lockcreated = false;
762         }
763
764         /* Free Admin Queue */
765         os_dma_mem_free(softs, &softs->admin_queue_dma_mem);
766
767         /* Switch back to SIS mode */
768         if (pqisrc_force_sis(softs)) {
769                 DBG_ERR("Failed to switch back the adapter to SIS mode!\n");
770         }
771
772         DBG_FUNC("OUT\n");
773 }
774
775 /*
776  * Function to initialize the adapter settings.
777  */
778 int pqisrc_init(pqisrc_softstate_t *softs)
779 {
780         int ret = 0;
781         int i = 0, j = 0;
782
783         DBG_FUNC("IN\n");
784     
785         check_struct_sizes();
786     
787         /* Init the Sync interface */
788         ret = pqisrc_sis_init(softs);
789         if (ret) {
790                 DBG_ERR("SIS Init failed with error %d\n", ret);
791                 goto err_out;
792         }
793
794         ret = os_create_semaphore("scan_lock", 1, &softs->scan_lock);
795         if(ret != PQI_STATUS_SUCCESS){
796                 DBG_ERR(" Failed to initialize scan lock\n");
797                 goto err_scan_lock;
798         }
799
800         /* Init the PQI interface */
801         ret = pqisrc_pqi_init(softs);
802         if (ret) {
803                 DBG_ERR("PQI Init failed with error %d\n", ret);
804                 goto err_pqi;
805         }
806
807         /* Setup interrupt */
808         ret = os_setup_intr(softs);
809         if (ret) {
810                 DBG_ERR("Interrupt setup failed with error %d\n", ret);
811                 goto err_intr;
812         }
813
814         /* Report event configuration */
815         ret = pqisrc_report_event_config(softs);
816         if(ret){
817                 DBG_ERR(" Failed to configure Report events\n");
818                 goto err_event;
819         }
820          
821         /* Set event configuration*/
822         ret = pqisrc_set_event_config(softs);
823         if(ret){
824                 DBG_ERR(" Failed to configure Set events\n");
825                 goto err_event;
826         }
827
828         /* Check for For PQI spanning */
829         ret = pqisrc_get_ctrl_fw_version(softs);
830         if(ret){
831                 DBG_ERR(" Failed to get ctrl fw version\n");
832                 goto err_fw_version;
833         }
834
835         /* update driver version in to FW */
836         ret = pqisrc_write_driver_version_to_host_wellness(softs);
837         if (ret) {
838                 DBG_ERR(" Failed to update driver version in to FW");
839                 goto err_host_wellness;
840         }
841
842     
843         os_strlcpy(softs->devlist_lock_name, "devlist_lock", LOCKNAME_SIZE);
844         ret = os_init_spinlock(softs, &softs->devlist_lock, softs->devlist_lock_name);
845         if(ret){
846                 DBG_ERR(" Failed to initialize devlist_lock\n");
847                 softs->devlist_lockcreated=false;
848                 goto err_lock;
849         }
850         softs->devlist_lockcreated = true;
851         
852         OS_ATOMIC64_SET(softs, num_intrs, 0);
853         softs->prev_num_intrs = softs->num_intrs;
854
855
856         /* Get the PQI configuration table to read heart-beat counter*/
857         if (PQI_NEW_HEARTBEAT_MECHANISM(softs)) {
858                 ret = pqisrc_process_config_table(softs);
859                 if (ret) {
860                         DBG_ERR("Failed to process PQI configuration table %d\n", ret);
861                         goto err_config_tab;
862                 }
863         }
864
865         if (PQI_NEW_HEARTBEAT_MECHANISM(softs))
866                 softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs) - OS_FW_HEARTBEAT_TIMER_INTERVAL;
867         
868         /* Init device list */
869         for(i = 0; i < PQI_MAX_DEVICES; i++)
870                 for(j = 0; j < PQI_MAX_MULTILUN; j++)
871                         softs->device_list[i][j] = NULL;
872
873         pqisrc_init_targetid_pool(softs);
874
875         DBG_FUNC("OUT\n");
876         return ret;
877
878 err_config_tab:
879         if(softs->devlist_lockcreated==true){    
880                 os_uninit_spinlock(&softs->devlist_lock);
881                 softs->devlist_lockcreated = false;
882         }       
883 err_lock:
884 err_fw_version:
885 err_event:
886 err_host_wellness:
887         os_destroy_intr(softs);
888 err_intr:
889         pqisrc_pqi_uninit(softs);
890 err_pqi:
891         os_destroy_semaphore(&softs->scan_lock);
892 err_scan_lock:
893         pqisrc_sis_uninit(softs);
894 err_out:
895         DBG_FUNC("OUT failed\n");
896         return ret;
897 }
898
899 /*
900  * Write all data in the adapter's battery-backed cache to
901  * storage.
902  */
903 int pqisrc_flush_cache( pqisrc_softstate_t *softs,
904                         enum pqisrc_flush_cache_event_type event_type)
905 {
906         int rval = PQI_STATUS_SUCCESS;
907         pqisrc_raid_req_t request;
908         pqisrc_bmic_flush_cache_t *flush_buff = NULL;
909
910         DBG_FUNC("IN\n");
911
912         if (pqisrc_ctrl_offline(softs))
913                 return PQI_STATUS_FAILURE;
914
915         flush_buff = os_mem_alloc(softs, sizeof(pqisrc_bmic_flush_cache_t)); 
916         if (!flush_buff) {
917                 DBG_ERR("Failed to allocate memory for flush cache params\n");
918                 rval = PQI_STATUS_FAILURE;
919                 return rval;
920         }
921
922         flush_buff->halt_event = event_type;
923
924         memset(&request, 0, sizeof(request));
925
926         rval = pqisrc_build_send_raid_request(softs, &request, flush_buff,
927                         sizeof(*flush_buff), SA_CACHE_FLUSH, 0,
928                         (uint8_t *)RAID_CTLR_LUNID, NULL);
929         if (rval) {
930                 DBG_ERR("error in build send raid req ret=%d\n", rval);
931         }
932
933         if (flush_buff)
934                 os_mem_free(softs, (void *)flush_buff,
935                         sizeof(pqisrc_bmic_flush_cache_t));
936
937         DBG_FUNC("OUT\n");
938
939         return rval;
940 }
941
942 /*
943  * Uninitialize the adapter.
944  */
945 void pqisrc_uninit(pqisrc_softstate_t *softs)
946 {
947         DBG_FUNC("IN\n");
948         
949         pqisrc_pqi_uninit(softs);
950
951         pqisrc_sis_uninit(softs);
952
953         os_destroy_semaphore(&softs->scan_lock);
954         
955         os_destroy_intr(softs);
956
957         pqisrc_cleanup_devices(softs);
958
959         DBG_FUNC("OUT\n");
960 }