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_event.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 /*
   31  * Function to rescan the devices connected to adapter.
   32  */
   33 int
   34 pqisrc_rescan_devices(pqisrc_softstate_t *softs)
   35 {
   36         int ret;
   37 
   38         DBG_FUNC("IN\n");
   39 
   40         os_sema_lock(&softs->scan_lock);
   41 
   42         ret = pqisrc_scan_devices(softs);
   43 
   44         os_sema_unlock(&softs->scan_lock);
   45 
   46         DBG_FUNC("OUT\n");
   47 
   48         return ret;
   49 }
   50 
   51 void
   52 pqisrc_wait_for_rescan_complete(pqisrc_softstate_t *softs)
   53 {
   54         os_sema_lock(&softs->scan_lock);
   55         os_sema_unlock(&softs->scan_lock);
   56 }
   57 
   58 /*
   59  * Subroutine to acknowledge the events processed by the driver to the adapter.
   60  */
   61 static void
   62 pqisrc_acknowledge_event(pqisrc_softstate_t *softs,
   63         struct pqi_event *event)
   64 {
   65 
   66         pqi_event_acknowledge_request_t request;
   67         ib_queue_t *ib_q = &softs->op_raid_ib_q[0];
   68         int tmo = PQISRC_EVENT_ACK_RESP_TIMEOUT;
   69         memset(&request,0,sizeof(request));
   70 
   71         DBG_FUNC("IN\n");
   72 
   73         request.header.iu_type = PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT;
   74         request.header.iu_length = (sizeof(pqi_event_acknowledge_request_t) -
   75                                                                 PQI_REQUEST_HEADER_LENGTH);
   76         request.event_type = event->event_type;
   77         request.event_id   = event->event_id;
   78         request.additional_event_id = event->additional_event_id;
   79 
   80         /* Submit Event Acknowledge */
   81 
   82         pqisrc_submit_cmnd(softs, ib_q, &request);
   83 
   84         /*
   85          * We have to special-case this type of request because the firmware
   86          * does not generate an interrupt when this type of request completes.
   87          * Therefore, we have to poll until we see that the firmware has
   88          * consumed the request before we move on.
   89          */
   90 
   91         COND_WAIT(((ib_q->pi_local) == *(ib_q->ci_virt_addr)), tmo);
   92                 if (tmo <= 0) {
   93                         DBG_ERR("wait for event acknowledge timed out\n");
   94                         DBG_ERR("tmo : %d\n",tmo);
   95                 }
   96 
   97         DBG_FUNC(" OUT\n");
   98 }
   99 
  100 /*
  101  * Acknowledge processed events to the adapter.
  102  */
  103 void
  104 pqisrc_ack_all_events(void *arg1)
  105 {
  106         int i;
  107         struct pqi_event *pending_event;
  108         pqisrc_softstate_t *softs = (pqisrc_softstate_t*)arg1;
  109 
  110         DBG_FUNC(" IN\n");
  111 
  112 
  113         pending_event = &softs->pending_events[0];
  114         for (i=0; i < PQI_NUM_SUPPORTED_EVENTS; i++) {
  115                 if (pending_event->pending == true) {
  116                         pending_event->pending = false;
  117                         pqisrc_acknowledge_event(softs, pending_event);
  118                 }
  119                 pending_event++;
  120         }
  121 
  122         /* Rescan devices except for heartbeat event */
  123         if ((pqisrc_rescan_devices(softs)) != PQI_STATUS_SUCCESS) {
  124                         DBG_ERR(" Failed to Re-Scan devices\n ");
  125         }
  126         DBG_FUNC(" OUT\n");
  127 
  128 }
  129 
  130 /*
  131  * Get event index from event type to validate the type of event.
  132  */
  133 static int
  134 pqisrc_event_type_to_event_index(unsigned event_type)
  135 {
  136         int index;
  137 
  138         switch (event_type) {
  139         case PQI_EVENT_TYPE_HOTPLUG:
  140                 index = PQI_EVENT_HOTPLUG;
  141                 break;
  142         case PQI_EVENT_TYPE_HARDWARE:
  143                 index = PQI_EVENT_HARDWARE;
  144                 break;
  145         case PQI_EVENT_TYPE_PHYSICAL_DEVICE:
  146                 index = PQI_EVENT_PHYSICAL_DEVICE;
  147                 break;
  148         case PQI_EVENT_TYPE_LOGICAL_DEVICE:
  149                 index = PQI_EVENT_LOGICAL_DEVICE;
  150                 break;
  151         case PQI_EVENT_TYPE_AIO_STATE_CHANGE:
  152                 index = PQI_EVENT_AIO_STATE_CHANGE;
  153                 break;
  154         case PQI_EVENT_TYPE_AIO_CONFIG_CHANGE:
  155                 index = PQI_EVENT_AIO_CONFIG_CHANGE;
  156                 break;
  157         default:
  158                 index = -1;
  159                 break;
  160         }
  161 
  162         return index;
  163 }
  164 
  165 /*
  166  * Function used to process the events supported by the adapter.
  167  */
  168 int
  169 pqisrc_process_event_intr_src(pqisrc_softstate_t *softs,int obq_id)
  170 {
  171         uint32_t obq_pi,obq_ci;
  172         pqi_event_response_t response;
  173         ob_queue_t *event_q;
  174         struct pqi_event *pending_event;
  175         boolean_t  need_delayed_work = false;
  176 
  177         DBG_FUNC(" IN\n");
  178 
  179         event_q = &softs->event_q;
  180         obq_ci = event_q->ci_local;
  181         obq_pi = *(event_q->pi_virt_addr);
  182         DBG_INFO("Initial Event_q ci : %d Event_q pi : %d\n", obq_ci, obq_pi);
  183 
  184         while(1) {
  185                 int event_index;
  186                 DBG_INFO("queue_id : %d ci : %d pi : %d\n",obq_id, obq_ci, obq_pi);
  187                 if (obq_pi == obq_ci)
  188                         break;
  189 
  190                 need_delayed_work = true;
  191 
  192                 /* Copy the response */
  193                 memcpy(&response, event_q->array_virt_addr + (obq_ci * event_q->elem_size),
  194                                         sizeof(pqi_event_response_t));
  195                 DBG_INFO("response.header.iu_type : 0x%x \n", response.header.iu_type);
  196                 DBG_INFO("response.event_type : 0x%x \n", response.event_type);
  197 
  198                 event_index = pqisrc_event_type_to_event_index(response.event_type);
  199 
  200                 if (event_index >= 0) {
  201                         if(response.request_acknowledge) {
  202                                 pending_event = &softs->pending_events[event_index];
  203                                 pending_event->pending = true;
  204                                 pending_event->event_type = response.event_type;
  205                                 pending_event->event_id = response.event_id;
  206                                 pending_event->additional_event_id = response.additional_event_id;
  207                         }
  208                 }
  209 
  210         obq_ci = (obq_ci + 1) % event_q->num_elem;
  211         }
  212     /* Update CI */
  213         event_q->ci_local = obq_ci;
  214         PCI_MEM_PUT32(softs, event_q->ci_register_abs,
  215         event_q->ci_register_offset, event_q->ci_local);
  216 
  217         /*Adding events to the task queue for acknowledging*/
  218         if (need_delayed_work == true) {
  219                 os_eventtaskqueue_enqueue(softs);
  220         }
  221 
  222         DBG_FUNC("OUT");
  223         return PQI_STATUS_SUCCESS;
  224 
  225 
  226 }
  227 
  228 /*
  229  * Function used to send a general management request to adapter.
  230  */
  231 int
  232 pqisrc_submit_management_req(pqisrc_softstate_t *softs,
  233                                       pqi_event_config_request_t *request)
  234 {
  235         int ret = PQI_STATUS_SUCCESS;
  236         ib_queue_t *op_ib_q = &softs->op_raid_ib_q[0];
  237         rcb_t *rcb = NULL;
  238 
  239         DBG_FUNC(" IN\n");
  240 
  241         /* Get the tag */
  242         request->request_id = pqisrc_get_tag(&softs->taglist);
  243         if (INVALID_ELEM == request->request_id) {
  244                 DBG_ERR("Tag not available\n");
  245                 ret = PQI_STATUS_FAILURE;
  246                 goto err_out;
  247         }
  248 
  249         rcb = &softs->rcb[request->request_id];
  250         rcb->req_pending = true;
  251         rcb->tag = request->request_id;
  252         /* Submit command on operational raid ib queue */
  253         ret = pqisrc_submit_cmnd(softs, op_ib_q, request);
  254         if (ret != PQI_STATUS_SUCCESS) {
  255                 DBG_ERR("  Unable to submit command\n");
  256                 goto err_cmd;
  257         }
  258 
  259         ret = pqisrc_wait_on_condition(softs, rcb, PQISRC_CMD_TIMEOUT);
  260         if (ret != PQI_STATUS_SUCCESS) {
  261                 DBG_ERR("Management request timed out !!\n");
  262                 goto err_cmd;
  263         }
  264 
  265         os_reset_rcb(rcb);
  266         pqisrc_put_tag(&softs->taglist,request->request_id);
  267         DBG_FUNC("OUT\n");
  268         return ret;
  269 
  270 err_cmd:
  271         os_reset_rcb(rcb);
  272         pqisrc_put_tag(&softs->taglist,request->request_id);
  273 err_out:
  274         DBG_FUNC(" failed OUT : %d\n", ret);
  275         return ret;
  276 }
  277 
  278 /*
  279  * Build and send the general management request.
  280  */
  281 static int
  282 pqi_event_configure(pqisrc_softstate_t *softs ,
  283                               pqi_event_config_request_t *request,
  284                               dma_mem_t *buff)
  285 {
  286         int ret = PQI_STATUS_SUCCESS;
  287 
  288         DBG_FUNC(" IN\n");
  289 
  290         request->header.comp_feature = 0x00;
  291         request->header.iu_length = sizeof(pqi_event_config_request_t) -
  292                     PQI_REQUEST_HEADER_LENGTH; /* excluding IU header length */
  293 
  294         /*Op OQ id where response to be delivered */
  295         request->response_queue_id = softs->op_ob_q[0].q_id;
  296         request->buffer_length     = buff->size;
  297         request->sg_desc.addr      = buff->dma_addr;
  298         request->sg_desc.length    = buff->size;
  299         request->sg_desc.zero      = 0;
  300         request->sg_desc.type      = SGL_DESCRIPTOR_CODE_LAST_ALTERNATIVE_SGL_SEGMENT;
  301 
  302         /* submit management req IU*/
  303         ret = pqisrc_submit_management_req(softs,request);
  304         if(ret)
  305                 goto err_out;
  306 
  307 
  308         DBG_FUNC(" OUT\n");
  309         return ret;
  310 
  311 err_out:
  312         DBG_FUNC("Failed OUT\n");
  313         return ret;
  314 }
  315 
  316 /*
  317  * Prepare REPORT EVENT CONFIGURATION IU to request that
  318  * event configuration information be reported.
  319  */
  320 int
  321 pqisrc_report_event_config(pqisrc_softstate_t *softs)
  322 {
  323 
  324         int ret,i ;
  325         pqi_event_config_request_t request;
  326         pqi_event_config_t  *event_config_p ;
  327         dma_mem_t  buf_report_event ;
  328         /*bytes to be allocaed for report event config data-in buffer */
  329         uint32_t alloc_size = sizeof(pqi_event_config_t) ;
  330         memset(&request, 0 , sizeof(request));
  331 
  332         DBG_FUNC(" IN\n");
  333 
  334         memset(&buf_report_event, 0, sizeof(struct dma_mem));
  335         buf_report_event.tag    = "pqi_report_event_buf" ;
  336         buf_report_event.size   = alloc_size;
  337         buf_report_event.align  = PQISRC_DEFAULT_DMA_ALIGN;
  338 
  339         /* allocate memory */
  340         ret = os_dma_mem_alloc(softs, &buf_report_event);
  341         if (ret) {
  342                 DBG_ERR("Failed to Allocate report event config buffer : %d\n", ret);
  343                 goto err_out;
  344         }
  345         DBG_INFO("buf_report_event.dma_addr     = %p \n",(void*)buf_report_event.dma_addr);
  346         DBG_INFO("buf_report_event.virt_addr    = %p \n",(void*)buf_report_event.virt_addr);
  347 
  348         request.header.iu_type = PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG;
  349 
  350         /* Event configuration */
  351         ret=pqi_event_configure(softs,&request,&buf_report_event);
  352         if(ret)
  353                 goto free_mem;
  354 
  355 
  356         event_config_p = (pqi_event_config_t*)buf_report_event.virt_addr;
  357         softs->event_config.num_event_descriptors = MIN(event_config_p->num_event_descriptors,
  358                                                             PQI_MAX_EVENT_DESCRIPTORS) ;
  359 
  360         for (i=0; i < softs->event_config.num_event_descriptors ;i++){
  361                 softs->event_config.descriptors[i].event_type =
  362                                         event_config_p->descriptors[i].event_type;
  363         }
  364         /* free the allocated memory*/
  365         os_dma_mem_free(softs, &buf_report_event);
  366 
  367         DBG_FUNC(" OUT\n");
  368         return ret;
  369 
  370 free_mem:
  371         os_dma_mem_free(softs, &buf_report_event);
  372 err_out:
  373         DBG_FUNC("Failed OUT\n");
  374         return PQI_STATUS_FAILURE;
  375 }
  376 
  377 /*
  378  * Prepare SET EVENT CONFIGURATION IU to request that
  379  * event configuration parameters be set.
  380  */
  381 int
  382 pqisrc_set_event_config(pqisrc_softstate_t *softs)
  383 {
  384 
  385         int ret,i;
  386         pqi_event_config_request_t request;
  387         pqi_event_config_t *event_config_p;
  388         dma_mem_t buf_set_event;
  389         /*bytes to be allocaed for set event config data-out buffer */
  390         uint32_t alloc_size = sizeof(pqi_event_config_t);
  391         memset(&request, 0 , sizeof(request));
  392 
  393         DBG_FUNC(" IN\n");
  394 
  395         memset(&buf_set_event, 0, sizeof(struct dma_mem));
  396         buf_set_event.tag       = "pqi_set_event_buf";
  397         buf_set_event.size      = alloc_size;
  398         buf_set_event.align     = PQISRC_DEFAULT_DMA_ALIGN;
  399 
  400         /* allocate memory */
  401         ret = os_dma_mem_alloc(softs, &buf_set_event);
  402         if (ret) {
  403                 DBG_ERR("Failed to Allocate set event config buffer : %d\n", ret);
  404                 goto err_out;
  405         }
  406 
  407         DBG_INFO("buf_set_event.dma_addr        = %p\n",(void*)buf_set_event.dma_addr);
  408         DBG_INFO("buf_set_event.virt_addr       = %p\n",(void*)buf_set_event.virt_addr);
  409 
  410         request.header.iu_type = PQI_REQUEST_IU_SET_EVENT_CONFIG;
  411         request.iu_specific.global_event_oq_id = softs->event_q.q_id;
  412 
  413         /*pointer to data-out buffer*/
  414 
  415         event_config_p = (pqi_event_config_t *)buf_set_event.virt_addr;
  416 
  417         event_config_p->num_event_descriptors = softs->event_config.num_event_descriptors;
  418 
  419 
  420         for (i=0; i < softs->event_config.num_event_descriptors ; i++){
  421                 event_config_p->descriptors[i].event_type =
  422                                         softs->event_config.descriptors[i].event_type;
  423                 if( pqisrc_event_type_to_event_index(event_config_p->descriptors[i].event_type) != -1)
  424                         event_config_p->descriptors[i].oq_id = softs->event_q.q_id;
  425                 else
  426                         event_config_p->descriptors[i].oq_id = 0; /* Not supported this event. */
  427 
  428 
  429         }
  430         /* Event configuration */
  431         ret = pqi_event_configure(softs,&request,&buf_set_event);
  432                 if(ret)
  433                         goto free_mem;
  434 
  435         os_dma_mem_free(softs, &buf_set_event);
  436 
  437         DBG_FUNC(" OUT\n");
  438         return ret;
  439 
  440 free_mem:
  441         os_dma_mem_free(softs, &buf_set_event);
  442 err_out:
  443         DBG_FUNC("Failed OUT\n");
  444         return PQI_STATUS_FAILURE;
  445 
  446 }

Cache object: 0d1f8cc8db3f7332dab01616a4687300


[ 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.