The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/smartpqi/smartpqi_init.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  */
   25 
   26 /* $FreeBSD$ */
   27 
   28 #include "smartpqi_includes.h"
   29 
   30 /* 5 mins timeout for quiesce */
   31 #define PQI_QUIESCE_TIMEOUT     300000
   32 
   33 /*
   34  * Request the adapter to get PQI capabilities supported.
   35  */
   36 static int
   37 pqisrc_report_pqi_capability(pqisrc_softstate_t *softs)
   38 {
   39         int ret = PQI_STATUS_SUCCESS;
   40         
   41         DBG_FUNC("IN\n");
   42 
   43         gen_adm_req_iu_t        admin_req;
   44         gen_adm_resp_iu_t       admin_resp;
   45         dma_mem_t               pqi_cap_dma_buf;
   46         pqi_dev_cap_t           *capability = NULL;
   47         pqi_iu_layer_desc_t     *iu_layer_desc = NULL;
   48 
   49         /* Allocate Non DMA memory */
   50         capability = os_mem_alloc(softs, sizeof(*capability));
   51         if (!capability) {
   52                 DBG_ERR("Failed to allocate memory for capability\n");
   53                 ret = PQI_STATUS_FAILURE;
   54                 goto err_out;
   55         }
   56 
   57         memset(&admin_req, 0, sizeof(admin_req));
   58         memset(&admin_resp, 0, sizeof(admin_resp));
   59 
   60         memset(&pqi_cap_dma_buf, 0, sizeof(struct dma_mem));
   61         pqi_cap_dma_buf.tag = "pqi_cap_buf";
   62         pqi_cap_dma_buf.size = REPORT_PQI_DEV_CAP_DATA_BUF_SIZE;
   63         pqi_cap_dma_buf.align = PQISRC_DEFAULT_DMA_ALIGN;
   64 
   65         ret = os_dma_mem_alloc(softs, &pqi_cap_dma_buf);
   66         if (ret) {
   67                 DBG_ERR("Failed to allocate capability DMA buffer : %d\n", ret);
   68                 goto err_dma_alloc;
   69         }
   70 
   71         admin_req.fn_code = PQI_FUNCTION_REPORT_DEV_CAP;
   72         admin_req.req_type.general_func.buf_size = pqi_cap_dma_buf.size;
   73         admin_req.req_type.general_func.sg_desc.length = pqi_cap_dma_buf.size;
   74         admin_req.req_type.general_func.sg_desc.addr = pqi_cap_dma_buf.dma_addr;
   75         admin_req.req_type.general_func.sg_desc.type =  SGL_DESCRIPTOR_CODE_DATA_BLOCK;
   76 
   77         ret = pqisrc_submit_admin_req(softs, &admin_req, &admin_resp);
   78         if( PQI_STATUS_SUCCESS == ret) {
   79                 memcpy(capability,
   80                         pqi_cap_dma_buf.virt_addr,
   81                         pqi_cap_dma_buf.size);
   82         } else {
   83                 DBG_ERR("Failed to send admin req report pqi device capability\n");
   84                 goto err_admin_req;
   85 
   86         }
   87 
   88         softs->pqi_dev_cap.max_iqs = capability->max_iqs;
   89         softs->pqi_dev_cap.max_iq_elements = capability->max_iq_elements;
   90         softs->pqi_dev_cap.max_iq_elem_len = capability->max_iq_elem_len;
   91         softs->pqi_dev_cap.min_iq_elem_len = capability->min_iq_elem_len;
   92         softs->pqi_dev_cap.max_oqs = capability->max_oqs;
   93         softs->pqi_dev_cap.max_oq_elements = capability->max_oq_elements;
   94         softs->pqi_dev_cap.max_oq_elem_len = capability->max_oq_elem_len;
   95         softs->pqi_dev_cap.intr_coales_time_granularity = capability->intr_coales_time_granularity;
   96 
   97         iu_layer_desc = &capability->iu_layer_desc[PQI_PROTOCOL_SOP];
   98         softs->max_ib_iu_length_per_fw = iu_layer_desc->max_ib_iu_len;
   99         softs->ib_spanning_supported = iu_layer_desc->ib_spanning_supported;
  100         softs->ob_spanning_supported = iu_layer_desc->ob_spanning_supported;
  101 
  102         DBG_INIT("softs->pqi_dev_cap.max_iqs: %d\n", softs->pqi_dev_cap.max_iqs);
  103         DBG_INIT("softs->pqi_dev_cap.max_iq_elements: %d\n", softs->pqi_dev_cap.max_iq_elements);
  104         DBG_INIT("softs->pqi_dev_cap.max_iq_elem_len: %d\n", softs->pqi_dev_cap.max_iq_elem_len);
  105         DBG_INIT("softs->pqi_dev_cap.min_iq_elem_len: %d\n", softs->pqi_dev_cap.min_iq_elem_len);
  106         DBG_INIT("softs->pqi_dev_cap.max_oqs: %d\n", softs->pqi_dev_cap.max_oqs);
  107         DBG_INIT("softs->pqi_dev_cap.max_oq_elements: %d\n", softs->pqi_dev_cap.max_oq_elements);
  108         DBG_INIT("softs->pqi_dev_cap.max_oq_elem_len: %d\n", softs->pqi_dev_cap.max_oq_elem_len);
  109         DBG_INIT("softs->pqi_dev_cap.intr_coales_time_granularity: %d\n", softs->pqi_dev_cap.intr_coales_time_granularity);
  110         DBG_INIT("softs->max_ib_iu_length_per_fw: %d\n", softs->max_ib_iu_length_per_fw);
  111         DBG_INIT("softs->ib_spanning_supported: %d\n", softs->ib_spanning_supported);
  112         DBG_INIT("softs->ob_spanning_supported: %d\n", softs->ob_spanning_supported);
  113 
  114 
  115         os_mem_free(softs, (void *)capability,
  116                     REPORT_PQI_DEV_CAP_DATA_BUF_SIZE);
  117         os_dma_mem_free(softs, &pqi_cap_dma_buf);
  118 
  119         DBG_FUNC("OUT\n");
  120         return ret;
  121 
  122 err_admin_req:
  123         os_dma_mem_free(softs, &pqi_cap_dma_buf);
  124 err_dma_alloc:
  125         if (capability)
  126                 os_mem_free(softs, (void *)capability,
  127                             REPORT_PQI_DEV_CAP_DATA_BUF_SIZE);
  128 err_out:
  129         DBG_FUNC("failed OUT\n");
  130         return PQI_STATUS_FAILURE;
  131 }
  132 
  133 /*
  134  * Function used to deallocate the used rcb.
  135  */
  136 void
  137 pqisrc_free_rcb(pqisrc_softstate_t *softs, int req_count)
  138 {
  139         uint32_t num_req;
  140         size_t size;
  141         int i;
  142 
  143         DBG_FUNC("IN\n");
  144         num_req = softs->max_outstanding_io + 1;
  145         size = num_req * sizeof(rcb_t);
  146         for (i = 1; i < req_count; i++)
  147                 os_dma_mem_free(softs, &softs->sg_dma_desc[i]);
  148         os_mem_free(softs, (void *)softs->rcb, size);
  149         softs->rcb = NULL;
  150         DBG_FUNC("OUT\n");
  151 }
  152 
  153 
  154 /*
  155  * Allocate memory for rcb and SG descriptors.
  156  */
  157 static int
  158 pqisrc_allocate_rcb(pqisrc_softstate_t *softs)
  159 {
  160         int ret = PQI_STATUS_SUCCESS;
  161         int i = 0;
  162         uint32_t num_req = 0;
  163         uint32_t sg_buf_size = 0;
  164         uint64_t alloc_size = 0;
  165         rcb_t *rcb = NULL;
  166         rcb_t *prcb = NULL;
  167         DBG_FUNC("IN\n");
  168 
  169         /* Set maximum outstanding requests */
  170         /* The valid tag values are from 1, 2, ..., softs->max_outstanding_io
  171          * The rcb will be accessed by using the tag as index
  172          * As 0 tag index is not used, we need to allocate one extra.
  173          */
  174         softs->max_outstanding_io = softs->pqi_cap.max_outstanding_io;
  175         num_req = softs->max_outstanding_io + 1;
  176         DBG_INIT("Max Outstanding IO reset to %d\n", num_req);
  177 
  178         alloc_size = num_req * sizeof(rcb_t);
  179 
  180         /* Allocate Non DMA memory */
  181         rcb = os_mem_alloc(softs, alloc_size);
  182         if (!rcb) {
  183                 DBG_ERR("Failed to allocate memory for rcb\n");
  184                 ret = PQI_STATUS_FAILURE;
  185                 goto err_out;
  186         }
  187         softs->rcb = rcb;
  188 
  189         /* Allocate sg dma memory for sg chain  */
  190         sg_buf_size = softs->pqi_cap.max_sg_elem *
  191                         sizeof(sgt_t);
  192 
  193         prcb = &softs->rcb[1];
  194         /* Initialize rcb */
  195         for(i=1; i < num_req; i++) {
  196                 char tag[15];
  197                 sprintf(tag, "sg_dma_buf%d", i);
  198                 softs->sg_dma_desc[i].tag = tag;
  199                 softs->sg_dma_desc[i].size = sg_buf_size;
  200                 softs->sg_dma_desc[i].align = PQISRC_DEFAULT_DMA_ALIGN;
  201 
  202                 ret = os_dma_mem_alloc(softs, &softs->sg_dma_desc[i]);
  203                 if (ret) {
  204                         DBG_ERR("Failed to Allocate sg desc %d\n", ret);
  205                         ret = PQI_STATUS_FAILURE;
  206                         goto error;
  207                 }
  208                 prcb->sg_chain_virt = (sgt_t *)(softs->sg_dma_desc[i].virt_addr);
  209                 prcb->sg_chain_dma = (dma_addr_t)(softs->sg_dma_desc[i].dma_addr);
  210                 prcb ++;
  211         }
  212 
  213         DBG_FUNC("OUT\n");
  214         return ret;
  215 error:
  216         pqisrc_free_rcb(softs, i);
  217 err_out:
  218         DBG_FUNC("failed OUT\n");
  219         return ret;
  220 }
  221 
  222 /*
  223  * Function used to decide the operational queue configuration params
  224  * - no of ibq/obq, shared/non-shared interrupt resource, IU spanning support
  225  */
  226 void
  227 pqisrc_decide_opq_config(pqisrc_softstate_t *softs)
  228 {
  229         uint16_t total_iq_elements;
  230 
  231         DBG_FUNC("IN\n");
  232 
  233         DBG_INIT("softs->intr_count : %d  softs->num_cpus_online : %d",
  234                 softs->intr_count, softs->num_cpus_online);
  235         
  236         if (softs->intr_count == 1 || softs->num_cpus_online == 1) {
  237                 /* Share the event and Operational queue. */
  238                 softs->num_op_obq = 1;
  239                 softs->share_opq_and_eventq = true;
  240         }
  241         else {
  242                 /* Note :  One OBQ (OBQ0) reserved for event queue */
  243                 softs->num_op_obq = MIN(softs->num_cpus_online,
  244                                         softs->intr_count) - 1;
  245                 softs->share_opq_and_eventq = false;
  246         }
  247         /* If the available interrupt count is more than one,
  248         we dont need to share the interrupt for IO and event queue */
  249         if (softs->intr_count > 1)
  250                 softs->share_opq_and_eventq = false;
  251 
  252         DBG_INIT("softs->num_op_obq : %d\n",softs->num_op_obq);
  253 
  254         softs->num_op_raid_ibq = softs->num_op_obq;
  255         softs->num_op_aio_ibq = softs->num_op_raid_ibq;
  256         softs->ibq_elem_size =  softs->pqi_dev_cap.max_iq_elem_len * 16;
  257         softs->obq_elem_size = softs->pqi_dev_cap.max_oq_elem_len * 16;
  258         if (softs->max_ib_iu_length_per_fw == 256 &&
  259             softs->ob_spanning_supported) {
  260                 /* older f/w that doesn't actually support spanning. */
  261                 softs->max_ib_iu_length = softs->ibq_elem_size;
  262         } else {
  263                 /* max. inbound IU length is an multiple of our inbound element size. */
  264                 softs->max_ib_iu_length =
  265                         (softs->max_ib_iu_length_per_fw / softs->ibq_elem_size) *
  266                          softs->ibq_elem_size;
  267 
  268         }
  269         /* If Max. Outstanding IO came with Max. Spanning element count then,
  270                 needed elements per IO are multiplication of
  271                 Max.Outstanding IO and  Max.Spanning element */
  272         total_iq_elements = (softs->max_outstanding_io *
  273                 (softs->max_ib_iu_length / softs->ibq_elem_size));
  274 
  275         softs->num_elem_per_op_ibq = total_iq_elements / softs->num_op_raid_ibq;
  276         softs->num_elem_per_op_ibq = MIN(softs->num_elem_per_op_ibq,
  277                 softs->pqi_dev_cap.max_iq_elements);
  278 
  279         softs->num_elem_per_op_obq = softs->max_outstanding_io / softs->num_op_obq;
  280         softs->num_elem_per_op_obq = MIN(softs->num_elem_per_op_obq,
  281                 softs->pqi_dev_cap.max_oq_elements);
  282 
  283         softs->max_sg_per_iu = ((softs->max_ib_iu_length -
  284                                 softs->ibq_elem_size) /
  285                                 sizeof(sgt_t)) +
  286                                 MAX_EMBEDDED_SG_IN_FIRST_IU;
  287 
  288         DBG_INIT("softs->max_ib_iu_length: %d\n", softs->max_ib_iu_length);
  289         DBG_INIT("softs->num_elem_per_op_ibq: %d\n", softs->num_elem_per_op_ibq);
  290         DBG_INIT("softs->num_elem_per_op_obq: %d\n", softs->num_elem_per_op_obq);
  291         DBG_INIT("softs->max_sg_per_iu: %d\n", softs->max_sg_per_iu);
  292 
  293         DBG_FUNC("OUT\n");
  294 }
  295 
  296 /*
  297  * Configure the operational queue parameters.
  298  */
  299 int
  300 pqisrc_configure_op_queues(pqisrc_softstate_t *softs)
  301 {
  302         int ret = PQI_STATUS_SUCCESS;
  303 
  304         /* Get the PQI capability,
  305                 REPORT PQI DEVICE CAPABILITY request */
  306         ret = pqisrc_report_pqi_capability(softs);
  307         if (ret) {
  308                 DBG_ERR("Failed to send report pqi dev capability request : %d\n",
  309                                 ret);
  310                 goto err_out;
  311         }
  312 
  313         /* Reserve required no of slots for internal requests */
  314         softs->max_io_for_scsi_ml = softs->max_outstanding_io - PQI_RESERVED_IO_SLOTS_CNT;
  315 
  316         /* Decide the Op queue configuration */
  317         pqisrc_decide_opq_config(softs);
  318 
  319         DBG_FUNC("OUT\n");
  320         return ret;
  321 
  322 err_out:
  323         DBG_FUNC("OUT failed\n");
  324         return ret;
  325 }
  326 
  327 /*
  328  * Validate the PQI mode of adapter.
  329  */
  330 int
  331 pqisrc_check_pqimode(pqisrc_softstate_t *softs)
  332 {
  333         int ret = PQI_STATUS_FAILURE;
  334         int tmo = 0;
  335         uint64_t signature = 0;
  336 
  337         DBG_FUNC("IN\n");
  338 
  339         /* Check the PQI device signature */
  340         tmo = PQISRC_PQIMODE_READY_TIMEOUT;
  341         do {
  342                 signature = LE_64(PCI_MEM_GET64(softs, &softs->pqi_reg->signature, PQI_SIGNATURE));
  343 
  344                 if (memcmp(&signature, PQISRC_PQI_DEVICE_SIGNATURE,
  345                                 sizeof(uint64_t)) == 0) {
  346                         ret = PQI_STATUS_SUCCESS;
  347                         break;
  348                 }
  349                 OS_SLEEP(PQISRC_MODE_READY_POLL_INTERVAL);
  350         } while (tmo--);
  351 
  352         PRINT_PQI_SIGNATURE(signature);
  353 
  354         if (tmo <= 0) {
  355                 DBG_ERR("PQI Signature is invalid\n");
  356                 ret = PQI_STATUS_TIMEOUT;
  357                 goto err_out;
  358         }
  359 
  360         tmo = PQISRC_PQIMODE_READY_TIMEOUT;
  361         /* Check function and status code for the device */
  362         COND_WAIT((PCI_MEM_GET64(softs, &softs->pqi_reg->admin_q_config,
  363                 PQI_ADMINQ_CONFIG) == PQI_ADMIN_QUEUE_CONF_FUNC_STATUS_IDLE), tmo);
  364         if (!tmo) {
  365                 DBG_ERR("PQI device is not in IDLE state\n");
  366                 ret = PQI_STATUS_TIMEOUT;
  367                 goto err_out;
  368         }
  369 
  370 
  371         tmo = PQISRC_PQIMODE_READY_TIMEOUT;
  372         /* Check the PQI device status register */
  373         COND_WAIT(LE_32(PCI_MEM_GET32(softs, &softs->pqi_reg->pqi_dev_status, PQI_DEV_STATUS)) &
  374                                 PQI_DEV_STATE_AT_INIT, tmo);
  375         if (!tmo) {
  376                 DBG_ERR("PQI Registers are not ready\n");
  377                 ret = PQI_STATUS_TIMEOUT;
  378                 goto err_out;
  379         }
  380 
  381         DBG_FUNC("OUT\n");
  382         return ret;
  383 err_out:
  384         DBG_FUNC("OUT failed\n");
  385         return ret;
  386 }
  387 
  388 /* PQI Feature processing */
  389 static int
  390 pqisrc_config_table_update(struct pqisrc_softstate *softs,
  391         uint16_t first_section, uint16_t last_section)
  392 {
  393         pqi_vendor_general_request_t request;
  394         int ret = PQI_STATUS_FAILURE;
  395 
  396         memset(&request, 0, sizeof(request));
  397 
  398         request.header.iu_type = PQI_REQUEST_IU_VENDOR_GENERAL;
  399         request.header.iu_length = sizeof(request) - PQI_REQUEST_HEADER_LENGTH;
  400         request.function_code = PQI_VENDOR_GENERAL_CONFIG_TABLE_UPDATE;
  401         request.data.config_table_update.first_section = first_section;
  402         request.data.config_table_update.last_section = last_section;
  403 
  404         ret = pqisrc_build_send_vendor_request(softs, &request, NULL);
  405 
  406         if (ret != PQI_STATUS_SUCCESS) {
  407                 DBG_ERR("Failed to submit vendor general request IU, Ret status: %d\n", ret);
  408                 return PQI_STATUS_FAILURE;
  409         }
  410 
  411         return PQI_STATUS_SUCCESS;
  412 }
  413 
  414 static inline
  415 boolean_t pqi_is_firmware_feature_supported(
  416         struct pqi_conf_table_firmware_features *firmware_feature_list,
  417         unsigned int bit_position)
  418 {
  419         unsigned int byte_index;
  420 
  421         byte_index = bit_position / BITS_PER_BYTE;
  422 
  423         if (byte_index >= firmware_feature_list->num_elements)
  424                 return false;
  425 
  426         return firmware_feature_list->features_supported[byte_index] &
  427                 (1 << (bit_position % BITS_PER_BYTE)) ? true : false;
  428 }
  429 
  430 static inline
  431 boolean_t pqi_is_firmware_feature_enabled(
  432         struct pqi_conf_table_firmware_features *firmware_feature_list,
  433         uint8_t *firmware_features_addr, unsigned int bit_position)
  434 {
  435         unsigned int byte_index;
  436         uint8_t *feature_enabled_addr;
  437 
  438         byte_index = (bit_position / BITS_PER_BYTE) +
  439                 (firmware_feature_list->num_elements * 2);
  440 
  441         feature_enabled_addr = firmware_features_addr +
  442                 offsetof(struct pqi_conf_table_firmware_features,
  443                         features_supported) + byte_index;
  444 
  445         return *feature_enabled_addr &
  446                 (1 << (bit_position % BITS_PER_BYTE)) ? true : false;
  447 }
  448 
  449 static inline void
  450 pqi_request_firmware_feature(
  451         struct pqi_conf_table_firmware_features *firmware_feature_list,
  452         unsigned int bit_position)
  453 {
  454         unsigned int byte_index;
  455 
  456         byte_index = (bit_position / BITS_PER_BYTE) +
  457                 firmware_feature_list->num_elements;
  458 
  459         firmware_feature_list->features_supported[byte_index] |=
  460                 (1 << (bit_position % BITS_PER_BYTE));
  461 }
  462 
  463 /* Update PQI config table firmware features section and inform the firmware */
  464 static int
  465 pqisrc_set_host_requested_firmware_feature(pqisrc_softstate_t *softs,
  466         struct pqi_conf_table_firmware_features *firmware_feature_list)
  467 {
  468         uint8_t *request_feature_addr;
  469         void *request_feature_abs_addr;
  470 
  471         request_feature_addr = firmware_feature_list->features_supported +
  472                 firmware_feature_list->num_elements;
  473         request_feature_abs_addr = softs->fw_features_section_abs_addr +
  474                 (request_feature_addr - (uint8_t*)firmware_feature_list);
  475 
  476         os_io_memcpy(request_feature_abs_addr, request_feature_addr,
  477                         firmware_feature_list->num_elements);
  478 
  479         return pqisrc_config_table_update(softs,
  480                 PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES,
  481                 PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES);
  482 }
  483 
  484 /* Check firmware has enabled the feature specified in the respective bit position. */
  485 inline boolean_t
  486 pqisrc_is_firmware_feature_enabled(pqisrc_softstate_t *softs,
  487                 struct pqi_conf_table_firmware_features *firmware_feature_list, uint16_t bit_position)
  488 {
  489         uint16_t byte_index;
  490         uint8_t *features_enabled_abs_addr;
  491 
  492         byte_index = (bit_position / BITS_PER_BYTE) +
  493                 (firmware_feature_list->num_elements * 2);
  494 
  495         features_enabled_abs_addr = softs->fw_features_section_abs_addr +
  496         offsetof(struct pqi_conf_table_firmware_features,features_supported) + byte_index;
  497 
  498         return *features_enabled_abs_addr &
  499                 (1 << (bit_position % BITS_PER_BYTE)) ? true : false;
  500 }
  501 
  502 static void
  503 pqi_firmware_feature_status(struct pqisrc_softstate     *softs,
  504         struct pqi_firmware_feature *firmware_feature)
  505 {
  506         switch(firmware_feature->feature_bit) {
  507         case PQI_FIRMWARE_FEATURE_OFA:
  508                 break;
  509         case PQI_FIRMWARE_FEATURE_TIMEOUT_IN_RAID_IU_SUPPORT:
  510                 softs->timeout_in_passthrough = true;
  511                 break;
  512         case PQI_FIRMWARE_FEATURE_TIMEOUT_IN_TMF_IU_SUPPORT:
  513                 softs->timeout_in_tmf = true;
  514                 break;
  515         default:
  516                 DBG_NOTE("Nothing to do \n");
  517         }
  518 }
  519 
  520 /* Firmware features supported by the driver */
  521 static struct
  522 pqi_firmware_feature pqi_firmware_features[] = {
  523         {
  524                 .feature_name = "Support timeout for pass-through commands",
  525                 .feature_bit = PQI_FIRMWARE_FEATURE_TIMEOUT_IN_RAID_IU_SUPPORT,
  526                 .feature_status = pqi_firmware_feature_status,
  527         },
  528         {
  529                 .feature_name = "Support timeout for LUN Reset TMF",
  530                 .feature_bit = PQI_FIRMWARE_FEATURE_TIMEOUT_IN_TMF_IU_SUPPORT,
  531                 .feature_status = pqi_firmware_feature_status,
  532         }
  533 };
  534 
  535 static void
  536 pqisrc_process_firmware_features(pqisrc_softstate_t *softs)
  537 {
  538         int rc;
  539         struct pqi_conf_table_firmware_features *firmware_feature_list;
  540         unsigned int i;
  541         unsigned int num_features_requested;
  542 
  543         firmware_feature_list = (struct pqi_conf_table_firmware_features*)
  544                 softs->fw_features_section_abs_addr;
  545 
  546         /* Check features and request those supported by firmware and driver.*/
  547         for (i = 0, num_features_requested = 0;
  548                 i < ARRAY_SIZE(pqi_firmware_features); i++) {
  549                 /* Firmware support it ? */
  550                 if (pqi_is_firmware_feature_supported(firmware_feature_list,
  551                                 pqi_firmware_features[i].feature_bit)) {
  552                         pqi_request_firmware_feature(firmware_feature_list,
  553                                 pqi_firmware_features[i].feature_bit);
  554                         pqi_firmware_features[i].supported = true;
  555                         num_features_requested++;
  556                         DBG_NOTE("%s supported by driver, requesting firmware to enable it\n",
  557                                         pqi_firmware_features[i].feature_name);
  558                 } else {
  559                         DBG_NOTE("%s supported by driver, but not by current firmware\n",
  560                                         pqi_firmware_features[i].feature_name);
  561                 }
  562         }
  563         if (num_features_requested == 0)
  564                 return;
  565 
  566         rc = pqisrc_set_host_requested_firmware_feature(softs, firmware_feature_list);
  567         if (rc) {
  568                 DBG_ERR("Failed to update pqi config table\n");
  569                 return;
  570         }
  571 
  572         for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) {
  573                 if (pqi_is_firmware_feature_enabled(firmware_feature_list,
  574                         softs->fw_features_section_abs_addr, pqi_firmware_features[i].feature_bit)) {
  575                         pqi_firmware_features[i].enabled = true;
  576                         DBG_NOTE("Firmware feature %s enabled \n",pqi_firmware_features[i].feature_name);
  577                         if(pqi_firmware_features[i].feature_status)
  578                                 pqi_firmware_features[i].feature_status(softs, &(pqi_firmware_features[i]));
  579                 }
  580         }
  581 }
  582 
  583 /*
  584  * Get the PQI configuration table parameters.
  585  * Currently using for heart-beat counter scratch-pad register.
  586  */
  587 int
  588 pqisrc_process_config_table(pqisrc_softstate_t *softs)
  589 {
  590         int ret = PQI_STATUS_FAILURE;
  591         uint32_t config_table_size;
  592         uint32_t section_off;
  593         uint8_t *config_table_abs_addr __unused;
  594         struct pqi_conf_table *conf_table;
  595         struct pqi_conf_table_section_header *section_hdr;
  596 
  597         config_table_size = softs->pqi_cap.conf_tab_sz;
  598 
  599         if (config_table_size < sizeof(*conf_table) ||
  600                 config_table_size > PQI_CONF_TABLE_MAX_LEN) {
  601                 DBG_ERR("Invalid PQI conf table length of %u\n",
  602                         config_table_size);
  603                 return ret;
  604         }
  605 
  606         conf_table = os_mem_alloc(softs, config_table_size);
  607         if (!conf_table) {
  608                 DBG_ERR("Failed to allocate memory for PQI conf table\n");
  609                 return ret;
  610         }
  611 
  612         if (config_table_size < sizeof(conf_table) ||
  613                 config_table_size > PQI_CONF_TABLE_MAX_LEN) {
  614                 DBG_ERR("Invalid PQI conf table length of %u\n",
  615                         config_table_size);
  616                 goto out;
  617         }
  618 
  619         config_table_abs_addr = (uint8_t *)(softs->pci_mem_base_vaddr +
  620                                         softs->pqi_cap.conf_tab_off);
  621 
  622         PCI_MEM_GET_BUF(softs, config_table_abs_addr,
  623                         softs->pqi_cap.conf_tab_off,
  624                         (uint8_t*)conf_table, config_table_size);
  625 
  626 
  627         if (memcmp(conf_table->sign, PQI_CONF_TABLE_SIGNATURE,
  628                         sizeof(conf_table->sign)) != 0) {
  629                 DBG_ERR("Invalid PQI config signature\n");
  630                 goto out;
  631         }
  632 
  633         section_off = LE_32(conf_table->first_section_off);
  634 
  635         while (section_off) {
  636 
  637                 if (section_off+ sizeof(*section_hdr) >= config_table_size) {
  638                         DBG_INFO("Reached end of PQI config table. Breaking off.\n");
  639                         break;
  640                 }
  641 
  642                 section_hdr = (struct pqi_conf_table_section_header *)((uint8_t *)conf_table + section_off);
  643 
  644                 switch (LE_16(section_hdr->section_id)) {
  645                 case PQI_CONF_TABLE_SECTION_GENERAL_INFO:
  646                 case PQI_CONF_TABLE_SECTION_FIRMWARE_ERRATA:
  647                 case PQI_CONF_TABLE_SECTION_DEBUG:
  648                         break;
  649                 case PQI_CONF_TABLE_SECTION_FIRMWARE_FEATURES:
  650                         softs->fw_features_section_off = softs->pqi_cap.conf_tab_off + section_off;
  651                         softs->fw_features_section_abs_addr = softs->pci_mem_base_vaddr + softs->fw_features_section_off;
  652                         pqisrc_process_firmware_features(softs);
  653                 break;
  654                 case PQI_CONF_TABLE_SECTION_HEARTBEAT:
  655                 softs->heartbeat_counter_off = softs->pqi_cap.conf_tab_off +
  656                                                 section_off +
  657                                                 offsetof(struct pqi_conf_table_heartbeat,
  658                                                 heartbeat_counter);
  659                 softs->heartbeat_counter_abs_addr = (uint64_t *)(softs->pci_mem_base_vaddr +
  660                                                         softs->heartbeat_counter_off);
  661                 ret = PQI_STATUS_SUCCESS;
  662                 break;
  663                 default:
  664                 DBG_INFO("unrecognized PQI config table section ID: 0x%x\n",
  665                                         LE_16(section_hdr->section_id));
  666                 break;
  667                 }
  668                 section_off = LE_16(section_hdr->next_section_off);
  669         }
  670 out:
  671         os_mem_free(softs, (void *)conf_table,config_table_size);
  672         return ret;
  673 }
  674 
  675 /* Wait for PQI reset completion for the adapter*/
  676 int
  677 pqisrc_wait_for_pqi_reset_completion(pqisrc_softstate_t *softs)
  678 {
  679         int ret = PQI_STATUS_SUCCESS;
  680         pqi_reset_reg_t reset_reg;
  681         int pqi_reset_timeout = 0;
  682         uint64_t val = 0;
  683         uint32_t max_timeout = 0;
  684 
  685         val = PCI_MEM_GET64(softs, &softs->pqi_reg->pqi_dev_adminq_cap, PQI_ADMINQ_CAP);
  686 
  687         max_timeout = (val & 0xFFFF00000000) >> 32;
  688 
  689         DBG_INIT("max_timeout for PQI reset completion in 100 msec units = %u\n", max_timeout);
  690 
  691         while(1) {
  692                 if (pqi_reset_timeout++ == max_timeout) {
  693                         return PQI_STATUS_TIMEOUT;
  694                 }
  695                 OS_SLEEP(PQI_RESET_POLL_INTERVAL);/* 100 msec */
  696                 reset_reg.all_bits = PCI_MEM_GET32(softs,
  697                         &softs->pqi_reg->dev_reset, PQI_DEV_RESET);
  698                 if (reset_reg.bits.reset_action == PQI_RESET_ACTION_COMPLETED)
  699                         break;
  700         }
  701 
  702         return ret;
  703 }
  704 
  705 /*
  706  * Function used to perform PQI hard reset.
  707  */
  708 int
  709 pqi_reset(pqisrc_softstate_t *softs)
  710 {
  711         int ret = PQI_STATUS_SUCCESS;
  712         uint32_t val = 0;
  713         pqi_reset_reg_t pqi_reset_reg;
  714 
  715         DBG_FUNC("IN\n");
  716 
  717         if (true == softs->ctrl_in_pqi_mode) {
  718 
  719                 if (softs->pqi_reset_quiesce_allowed) {
  720                         val = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db,
  721                                         LEGACY_SIS_IDBR);
  722                         val |= SIS_PQI_RESET_QUIESCE;
  723                         PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db,
  724                                         LEGACY_SIS_IDBR, LE_32(val));
  725                         ret = pqisrc_sis_wait_for_db_bit_to_clear(softs, SIS_PQI_RESET_QUIESCE);
  726                         if (ret) {
  727                                 DBG_ERR("failed with error %d during quiesce\n", ret);
  728                                 return ret;
  729                         }
  730                 }
  731 
  732                 pqi_reset_reg.all_bits = 0;
  733                 pqi_reset_reg.bits.reset_type = PQI_RESET_TYPE_HARD_RESET;
  734                 pqi_reset_reg.bits.reset_action = PQI_RESET_ACTION_RESET;
  735 
  736                 PCI_MEM_PUT32(softs, &softs->pqi_reg->dev_reset, PQI_DEV_RESET,
  737                         LE_32(pqi_reset_reg.all_bits));
  738 
  739                 ret = pqisrc_wait_for_pqi_reset_completion(softs);
  740                 if (ret) {
  741                         DBG_ERR("PQI reset timed out: ret = %d!\n", ret);
  742                         return ret;
  743                 }
  744         }
  745         softs->ctrl_in_pqi_mode = false;
  746         DBG_FUNC("OUT\n");
  747         return ret;
  748 }
  749 
  750 /*
  751  * Initialize the adapter with supported PQI configuration.
  752  */
  753 int
  754 pqisrc_pqi_init(pqisrc_softstate_t *softs)
  755 {
  756         int ret = PQI_STATUS_SUCCESS;
  757 
  758         DBG_FUNC("IN\n");
  759 
  760         /* Check the PQI signature */
  761         ret = pqisrc_check_pqimode(softs);
  762         if(ret) {
  763                 DBG_ERR("failed to switch to pqi\n");
  764                 goto err_out;
  765         }
  766 
  767         PQI_SAVE_CTRL_MODE(softs, CTRL_PQI_MODE);
  768         softs->ctrl_in_pqi_mode = true;
  769 
  770         /* Get the No. of Online CPUs,NUMA/Processor config from OS */
  771         ret = os_get_processor_config(softs);
  772         if (ret) {
  773                 DBG_ERR("Failed to get processor config from OS %d\n",
  774                         ret);
  775                 goto err_out;
  776         }
  777 
  778         softs->intr_type = INTR_TYPE_NONE;
  779 
  780         /* Get the interrupt count, type, priority available from OS */
  781         ret = os_get_intr_config(softs);
  782         if (ret) {
  783                 DBG_ERR("Failed to get interrupt config from OS %d\n",
  784                         ret);
  785                 goto err_out;
  786         }
  787 
  788         /*Enable/Set Legacy INTx Interrupt mask clear pqi register,
  789          *if allocated interrupt is legacy type.
  790          */
  791         if (INTR_TYPE_FIXED == softs->intr_type) {
  792                 pqisrc_configure_legacy_intx(softs, true);
  793                 sis_enable_intx(softs);
  794         }
  795 
  796         /* Create Admin Queue pair*/
  797         ret = pqisrc_create_admin_queue(softs);
  798         if(ret) {
  799                 DBG_ERR("Failed to configure admin queue\n");
  800                 goto err_admin_queue;
  801         }
  802 
  803         /* For creating event and IO operational queues we have to submit
  804            admin IU requests.So Allocate resources for submitting IUs */
  805 
  806         /* Allocate the request container block (rcb) */
  807         ret = pqisrc_allocate_rcb(softs);
  808         if (ret == PQI_STATUS_FAILURE) {
  809                 DBG_ERR("Failed to allocate rcb \n");
  810                 goto err_rcb;
  811         }
  812 
  813         /* Allocate & initialize request id queue */
  814         ret = pqisrc_init_taglist(softs,&softs->taglist,
  815                                 softs->max_outstanding_io);
  816         if (ret) {
  817                 DBG_ERR("Failed to allocate memory for request id q : %d\n",
  818                         ret);
  819                 goto err_taglist;
  820         }
  821 
  822         ret = pqisrc_configure_op_queues(softs);
  823         if (ret) {
  824                         DBG_ERR("Failed to configure op queue\n");
  825                         goto err_config_opq;
  826         }
  827 
  828         /* Create Operational queues */
  829         ret = pqisrc_create_op_queues(softs);
  830         if(ret) {
  831                 DBG_ERR("Failed to create op queue\n");
  832                 ret = PQI_STATUS_FAILURE;
  833                 goto err_create_opq;
  834         }
  835 
  836         softs->ctrl_online = true;
  837 
  838         DBG_FUNC("OUT\n");
  839         return ret;
  840 
  841 err_create_opq:
  842 err_config_opq:
  843         pqisrc_destroy_taglist(softs,&softs->taglist);
  844 err_taglist:
  845         pqisrc_free_rcb(softs, softs->max_outstanding_io + 1);
  846 err_rcb:
  847         pqisrc_destroy_admin_queue(softs);
  848 err_admin_queue:
  849         os_free_intr_config(softs);
  850 err_out:
  851         DBG_FUNC("OUT failed\n");
  852         return PQI_STATUS_FAILURE;
  853 }
  854 
  855 int
  856 pqisrc_force_sis(pqisrc_softstate_t *softs)
  857 {
  858         int ret = PQI_STATUS_SUCCESS;
  859 
  860         if (SIS_IS_KERNEL_PANIC(softs)) {
  861                 DBG_INIT("Controller FW is not running");
  862                 return PQI_STATUS_FAILURE;
  863         }
  864 
  865         if (PQI_GET_CTRL_MODE(softs) == CTRL_SIS_MODE) {
  866                 return ret;
  867         }
  868 
  869         if (SIS_IS_KERNEL_UP(softs)) {
  870                 PQI_SAVE_CTRL_MODE(softs, CTRL_SIS_MODE);
  871                 return ret;
  872         }
  873         /* Disable interrupts ? */
  874         sis_disable_interrupt(softs);
  875 
  876         /* reset pqi, this will delete queues */
  877         ret = pqi_reset(softs);
  878         if (ret) {
  879                 return ret;
  880         }
  881         /* Re enable SIS */
  882         ret = pqisrc_reenable_sis(softs);
  883         if (ret) {
  884                 return ret;
  885         }
  886 
  887         PQI_SAVE_CTRL_MODE(softs, CTRL_SIS_MODE);
  888 
  889         return ret;
  890 }
  891 
  892 static int
  893 pqisrc_wait_for_cmnd_complete(pqisrc_softstate_t *softs)
  894 {
  895         int count = 0;
  896         int ret = PQI_STATUS_SUCCESS;
  897 
  898         DBG_NOTE("softs->taglist.num_elem : %d",softs->taglist.num_elem);
  899 
  900         if (softs->taglist.num_elem == softs->max_outstanding_io)
  901                 return ret;
  902         else {
  903                 DBG_WARN("%d commands pending\n",
  904                 softs->max_outstanding_io - softs->taglist.num_elem);
  905 
  906                 while(1) {
  907 
  908                         /* Since heartbeat timer stopped ,check for firmware status*/
  909                         if (SIS_IS_KERNEL_PANIC(softs)) {
  910                                 DBG_ERR("Controller FW is not running\n");
  911                                 return PQI_STATUS_FAILURE;
  912                         }
  913 
  914                         if (softs->taglist.num_elem != softs->max_outstanding_io) {
  915                                 /* Sleep for 1 msec */
  916                                 OS_SLEEP(1000);
  917                                 count++;
  918                                 if(count % 1000 == 0) {
  919                                         DBG_WARN("Waited for %d seconds", count/1000);
  920                                 }
  921                                 if (count >= PQI_QUIESCE_TIMEOUT) {
  922                                         return PQI_STATUS_FAILURE;
  923                                 }
  924                                 continue;
  925                         }
  926                         break;
  927                 }
  928         }
  929         return ret;
  930 }
  931 
  932 static void
  933 pqisrc_complete_internal_cmds(pqisrc_softstate_t *softs)
  934 {
  935 
  936         int tag = 0;
  937         rcb_t *rcb;
  938 
  939         for (tag = 1; tag <= softs->max_outstanding_io; tag++) {
  940                 rcb = &softs->rcb[tag];
  941                 if(rcb->req_pending && is_internal_req(rcb)) {
  942                         rcb->status = REQUEST_FAILED;
  943                         rcb->req_pending = false;
  944                 }
  945         }
  946 }
  947 
  948 
  949 /*
  950  * Uninitialize the resources used during PQI initialization.
  951  */
  952 void
  953 pqisrc_pqi_uninit(pqisrc_softstate_t *softs)
  954 {
  955         int i, ret;
  956 
  957         DBG_FUNC("IN\n");
  958 
  959         /* Wait for any rescan to finish */
  960         pqisrc_wait_for_rescan_complete(softs);
  961 
  962         /* Wait for commands to complete */
  963         ret = pqisrc_wait_for_cmnd_complete(softs);
  964 
  965         /* disable and free the interrupt resources */
  966         os_destroy_intr(softs);
  967 
  968         /* Complete all pending commands. */
  969         if(ret != PQI_STATUS_SUCCESS) {
  970                 pqisrc_complete_internal_cmds(softs);
  971                 os_complete_outstanding_cmds_nodevice(softs);
  972         }
  973 
  974         if(softs->devlist_lockcreated==true){
  975                 os_uninit_spinlock(&softs->devlist_lock);
  976                 softs->devlist_lockcreated = false;
  977         }
  978 
  979         for (i = 0; i <  softs->num_op_raid_ibq; i++) {
  980                 /* OP RAID IB Q */
  981                 if(softs->op_raid_ib_q[i].lockcreated==true){
  982                         OS_UNINIT_PQILOCK(&softs->op_raid_ib_q[i].lock);
  983                         softs->op_raid_ib_q[i].lockcreated = false;
  984                 }
  985                 /* OP AIO IB Q */
  986                 if(softs->op_aio_ib_q[i].lockcreated==true){
  987                         OS_UNINIT_PQILOCK(&softs->op_aio_ib_q[i].lock);
  988                         softs->op_aio_ib_q[i].lockcreated = false;
  989                 }
  990         }
  991 
  992         /* Free Op queues */
  993         os_dma_mem_free(softs, &softs->op_ibq_dma_mem);
  994         os_dma_mem_free(softs, &softs->op_obq_dma_mem);
  995         os_dma_mem_free(softs, &softs->event_q_dma_mem);
  996 
  997 
  998 
  999         /* Free  rcb */
 1000         pqisrc_free_rcb(softs, softs->max_outstanding_io + 1);
 1001 
 1002         /* Free request id lists */
 1003         pqisrc_destroy_taglist(softs,&softs->taglist);
 1004 
 1005         if(softs->admin_ib_queue.lockcreated==true) {
 1006                 OS_UNINIT_PQILOCK(&softs->admin_ib_queue.lock);
 1007                 softs->admin_ib_queue.lockcreated = false;
 1008         }
 1009 
 1010         /* Free Admin Queue */
 1011         os_dma_mem_free(softs, &softs->admin_queue_dma_mem);
 1012 
 1013         /* Switch back to SIS mode */
 1014         if (pqisrc_force_sis(softs)) {
 1015                 DBG_ERR("Failed to switch back the adapter to SIS mode!\n");
 1016         }
 1017 
 1018         DBG_FUNC("OUT\n");
 1019 }
 1020 
 1021 /*
 1022  * Function to initialize the adapter settings.
 1023  */
 1024 int
 1025 pqisrc_init(pqisrc_softstate_t *softs)
 1026 {
 1027         int ret = 0;
 1028         int i = 0, j = 0;
 1029 
 1030         DBG_FUNC("IN\n");
 1031 
 1032         check_struct_sizes();
 1033 
 1034         /* Init the Sync interface */
 1035         ret = pqisrc_sis_init(softs);
 1036         if (ret) {
 1037                 DBG_ERR("SIS Init failed with error %d\n", ret);
 1038                 goto err_out;
 1039         }
 1040 
 1041         ret = os_create_semaphore("scan_lock", 1, &softs->scan_lock);
 1042         if(ret != PQI_STATUS_SUCCESS){
 1043                 DBG_ERR(" Failed to initialize scan lock\n");
 1044                 goto err_scan_lock;
 1045         }
 1046 
 1047         /* Init the PQI interface */
 1048         ret = pqisrc_pqi_init(softs);
 1049         if (ret) {
 1050                 DBG_ERR("PQI Init failed with error %d\n", ret);
 1051                 goto err_pqi;
 1052         }
 1053 
 1054         /* Setup interrupt */
 1055         ret = os_setup_intr(softs);
 1056         if (ret) {
 1057                 DBG_ERR("Interrupt setup failed with error %d\n", ret);
 1058                 goto err_intr;
 1059         }
 1060 
 1061         /* Report event configuration */
 1062         ret = pqisrc_report_event_config(softs);
 1063         if(ret){
 1064                 DBG_ERR(" Failed to configure Report events\n");
 1065                 goto err_event;
 1066         }
 1067 
 1068         /* Set event configuration*/
 1069         ret = pqisrc_set_event_config(softs);
 1070         if(ret){
 1071                 DBG_ERR(" Failed to configure Set events\n");
 1072                 goto err_event;
 1073         }
 1074 
 1075         /* Check for For PQI spanning */
 1076         ret = pqisrc_get_ctrl_fw_version(softs);
 1077         if(ret){
 1078                 DBG_ERR(" Failed to get ctrl fw version\n");
 1079                 goto err_fw_version;
 1080         }
 1081 
 1082         /* update driver version in to FW */
 1083         ret = pqisrc_write_driver_version_to_host_wellness(softs);
 1084         if (ret) {
 1085                 DBG_ERR(" Failed to update driver version in to FW");
 1086                 goto err_host_wellness;
 1087         }
 1088 
 1089 
 1090         os_strlcpy(softs->devlist_lock_name, "devlist_lock", LOCKNAME_SIZE);
 1091         ret = os_init_spinlock(softs, &softs->devlist_lock, softs->devlist_lock_name);
 1092         if(ret){
 1093                 DBG_ERR(" Failed to initialize devlist_lock\n");
 1094                 softs->devlist_lockcreated=false;
 1095                 goto err_lock;
 1096         }
 1097         softs->devlist_lockcreated = true;
 1098 
 1099         /* Get the PQI configuration table to read heart-beat counter*/
 1100         ret = pqisrc_process_config_table(softs);
 1101         if (ret) {
 1102                 DBG_ERR("Failed to process PQI configuration table %d\n", ret);
 1103                 goto err_config_tab;
 1104         }
 1105 
 1106         softs->prev_heartbeat_count = CTRLR_HEARTBEAT_CNT(softs) - OS_FW_HEARTBEAT_TIMER_INTERVAL;
 1107 
 1108         /* Init device list */
 1109         for(i = 0; i < PQI_MAX_DEVICES; i++)
 1110                 for(j = 0; j < PQI_MAX_MULTILUN; j++)
 1111                         softs->device_list[i][j] = NULL;
 1112 
 1113         pqisrc_init_targetid_pool(softs);
 1114 
 1115         DBG_FUNC("OUT\n");
 1116         return ret;
 1117 
 1118 err_config_tab:
 1119         if(softs->devlist_lockcreated==true){
 1120                 os_uninit_spinlock(&softs->devlist_lock);
 1121                 softs->devlist_lockcreated = false;
 1122         }
 1123 err_lock:
 1124 err_fw_version:
 1125 err_event:
 1126 err_host_wellness:
 1127 err_intr:
 1128         pqisrc_pqi_uninit(softs);
 1129 err_pqi:
 1130         os_destroy_semaphore(&softs->scan_lock);
 1131 err_scan_lock:
 1132         pqisrc_sis_uninit(softs);
 1133 err_out:
 1134         DBG_FUNC("OUT failed\n");
 1135         return ret;
 1136 }
 1137 
 1138 /*
 1139  * Write all data in the adapter's battery-backed cache to
 1140  * storage.
 1141  */
 1142 int
 1143 pqisrc_flush_cache( pqisrc_softstate_t *softs,
 1144                         enum pqisrc_flush_cache_event_type event_type)
 1145 {
 1146         int rval = PQI_STATUS_SUCCESS;
 1147         pqisrc_raid_req_t request;
 1148         pqisrc_bmic_flush_cache_t *flush_buff = NULL;
 1149 
 1150         DBG_FUNC("IN\n");
 1151 
 1152         if (pqisrc_ctrl_offline(softs))
 1153                 return PQI_STATUS_FAILURE;
 1154 
 1155         flush_buff = os_mem_alloc(softs, sizeof(pqisrc_bmic_flush_cache_t));
 1156         if (!flush_buff) {
 1157                 DBG_ERR("Failed to allocate memory for flush cache params\n");
 1158                 rval = PQI_STATUS_FAILURE;
 1159                 return rval;
 1160         }
 1161 
 1162         flush_buff->halt_event = event_type;
 1163 
 1164         memset(&request, 0, sizeof(request));
 1165 
 1166         rval = pqisrc_build_send_raid_request(softs, &request, flush_buff,
 1167                         sizeof(*flush_buff), SA_CACHE_FLUSH, 0,
 1168                         (uint8_t *)RAID_CTLR_LUNID, NULL);
 1169         if (rval) {
 1170                 DBG_ERR("error in build send raid req ret=%d\n", rval);
 1171         }
 1172 
 1173         if (flush_buff)
 1174                 os_mem_free(softs, (void *)flush_buff,
 1175                         sizeof(pqisrc_bmic_flush_cache_t));
 1176 
 1177         DBG_FUNC("OUT\n");
 1178 
 1179         return rval;
 1180 }
 1181 
 1182 /*
 1183  * Uninitialize the adapter.
 1184  */
 1185 void
 1186 pqisrc_uninit(pqisrc_softstate_t *softs)
 1187 {
 1188         DBG_FUNC("IN\n");
 1189 
 1190         pqisrc_pqi_uninit(softs);
 1191 
 1192         pqisrc_sis_uninit(softs);
 1193 
 1194         os_destroy_semaphore(&softs->scan_lock);
 1195 
 1196         pqisrc_cleanup_devices(softs);
 1197 
 1198         DBG_FUNC("OUT\n");
 1199 }

Cache object: 12765600e0dea5db2e08c734bc390c43


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.