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/liquidio/base/lio_response_manager.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  *   BSD LICENSE
    3  *
    4  *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
    5  *   All rights reserved.
    6  *
    7  *   Redistribution and use in source and binary forms, with or without
    8  *   modification, are permitted provided that the following conditions
    9  *   are met:
   10  *
   11  *     * Redistributions of source code must retain the above copyright
   12  *       notice, this list of conditions and the following disclaimer.
   13  *     * Redistributions in binary form must reproduce the above copyright
   14  *       notice, this list of conditions and the following disclaimer in
   15  *       the documentation and/or other materials provided with the
   16  *       distribution.
   17  *     * Neither the name of Cavium, Inc. nor the names of its
   18  *       contributors may be used to endorse or promote products derived
   19  *       from this software without specific prior written permission.
   20  *
   21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   25  *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 /*$FreeBSD$*/
   34 
   35 #include "lio_bsd.h"
   36 #include "lio_common.h"
   37 #include "lio_droq.h"
   38 #include "lio_iq.h"
   39 #include "lio_response_manager.h"
   40 #include "lio_device.h"
   41 #include "lio_main.h"
   42 
   43 static void     lio_poll_req_completion(void *arg, int pending);
   44 
   45 int
   46 lio_setup_response_list(struct octeon_device *oct)
   47 {
   48         struct lio_tq   *ctq;
   49         int             i, ret = 0;
   50 
   51         for (i = 0; i < LIO_MAX_RESPONSE_LISTS; i++) {
   52                 STAILQ_INIT(&oct->response_list[i].head);
   53                 mtx_init(&oct->response_list[i].lock, "response_list_lock",
   54                          NULL, MTX_DEF);
   55                 atomic_store_rel_int(&oct->response_list[i].pending_req_count,
   56                                      0);
   57         }
   58         mtx_init(&oct->cmd_resp_wqlock, "cmd_resp_wqlock", NULL, MTX_DEF);
   59 
   60         ctq = &oct->dma_comp_tq;
   61         ctq->tq = taskqueue_create("lio_dma_comp", M_WAITOK,
   62                                    taskqueue_thread_enqueue, &ctq->tq);
   63         if (ctq->tq == NULL) {
   64                 lio_dev_err(oct, "failed to create wq thread\n");
   65                 return (-ENOMEM);
   66         }
   67 
   68         TIMEOUT_TASK_INIT(ctq->tq, &ctq->work, 0, lio_poll_req_completion,
   69                           (void *)ctq);
   70         ctq->ctxptr = oct;
   71 
   72         oct->cmd_resp_state = LIO_DRV_ONLINE;
   73         taskqueue_start_threads(&ctq->tq, 1, PI_NET, "lio%d_dma_comp",
   74                                 oct->octeon_id);
   75         taskqueue_enqueue_timeout(ctq->tq, &ctq->work, lio_ms_to_ticks(50));
   76 
   77         return (ret);
   78 }
   79 
   80 void
   81 lio_delete_response_list(struct octeon_device *oct)
   82 {
   83 
   84         if (oct->dma_comp_tq.tq != NULL) {
   85                 while (taskqueue_cancel_timeout(oct->dma_comp_tq.tq,
   86                                                 &oct->dma_comp_tq.work, NULL))
   87                         taskqueue_drain_timeout(oct->dma_comp_tq.tq,
   88                                                 &oct->dma_comp_tq.work);
   89                 taskqueue_free(oct->dma_comp_tq.tq);
   90                 oct->dma_comp_tq.tq = NULL;
   91         }
   92 }
   93 
   94 int
   95 lio_process_ordered_list(struct octeon_device *octeon_dev,
   96                          uint32_t force_quit)
   97 {
   98         struct lio_response_list        *ordered_sc_list;
   99         struct lio_soft_command         *sc;
  100         uint64_t                        status64;
  101         uint32_t                        status;
  102         int                             request_complete = 0;
  103         int                             resp_to_process;
  104 
  105         resp_to_process = LIO_MAX_ORD_REQS_TO_PROCESS;
  106 
  107         ordered_sc_list = &octeon_dev->response_list[LIO_ORDERED_SC_LIST];
  108 
  109         do {
  110                 mtx_lock(&ordered_sc_list->lock);
  111 
  112                 if (STAILQ_EMPTY(&ordered_sc_list->head)) {
  113                         /*
  114                          * ordered_sc_list is empty; there is nothing to
  115                          * process
  116                          */
  117                         mtx_unlock(&ordered_sc_list->lock);
  118                         return (1);
  119                 }
  120 
  121                 sc = LIO_STAILQ_FIRST_ENTRY(&ordered_sc_list->head,
  122                                             struct lio_soft_command, node);
  123 
  124                 status = LIO_REQUEST_PENDING;
  125 
  126                 /*
  127                  * check if octeon has finished DMA'ing a response to where
  128                  * rptr is pointing to
  129                  */
  130                 status64 = *sc->status_word;
  131 
  132                 if (status64 != COMPLETION_WORD_INIT) {
  133                         /*
  134                          * This logic ensures that all 64b have been written.
  135                          * 1. check byte 0 for non-FF
  136                          * 2. if non-FF, then swap result from BE to host order
  137                          * 3. check byte 7 (swapped to 0) for non-FF
  138                          * 4. if non-FF, use the low 32-bit status code
  139                          * 5. if either byte 0 or byte 7 is FF, don't use status
  140                          */
  141                         if ((status64 & 0xff) != 0xff) {
  142                                 lio_swap_8B_data(&status64, 1);
  143                                 if (((status64 & 0xff) != 0xff)) {
  144                                         /* retrieve 16-bit firmware status */
  145                                         status = (uint32_t)(status64 &
  146                                                             0xffffULL);
  147                                         if (status) {
  148                                                 status = LIO_FW_STATUS_CODE(
  149                                                                         status);
  150                                         } else {
  151                                                 /* i.e. no error */
  152                                                 status = LIO_REQUEST_DONE;
  153                                         }
  154                                 }
  155                         }
  156                 } else if (force_quit || (sc->timeout &&
  157                            lio_check_timeout(ticks, sc->timeout))) {
  158                         lio_dev_err(octeon_dev, "%s: cmd failed, timeout (%u, %u)\n",
  159                                     __func__, ticks, sc->timeout);
  160                         status = LIO_REQUEST_TIMEOUT;
  161                 }
  162 
  163                 if (status != LIO_REQUEST_PENDING) {
  164                         /* we have received a response or we have timed out */
  165                         /* remove node from linked list */
  166                         STAILQ_REMOVE(&octeon_dev->response_list
  167                                       [LIO_ORDERED_SC_LIST].head,
  168                                       &sc->node, lio_stailq_node, entries);
  169                         atomic_subtract_int(&octeon_dev->response_list
  170                                             [LIO_ORDERED_SC_LIST].
  171                                             pending_req_count, 1);
  172                         mtx_unlock(&ordered_sc_list->lock);
  173 
  174                         if (sc->callback != NULL)
  175                                 sc->callback(octeon_dev, status,
  176                                              sc->callback_arg);
  177 
  178                         request_complete++;
  179 
  180                 } else {
  181                         /* no response yet */
  182                         request_complete = 0;
  183                         mtx_unlock(&ordered_sc_list->lock);
  184                 }
  185 
  186                 /*
  187                  * If we hit the Max Ordered requests to process every loop,
  188                  * we quit and let this function be invoked the next time
  189                  * the poll thread runs to process the remaining requests.
  190                  * This function can take up the entire CPU if there is no
  191                  * upper limit to the requests processed.
  192                  */
  193                 if (request_complete >= resp_to_process)
  194                         break;
  195         } while (request_complete);
  196 
  197         return (0);
  198 }
  199 
  200 static void
  201 lio_poll_req_completion(void *arg, int pending)
  202 {
  203         struct lio_tq           *ctq = (struct lio_tq *)arg;
  204         struct octeon_device    *oct = (struct octeon_device *)ctq->ctxptr;
  205 
  206         lio_process_ordered_list(oct, 0);
  207         taskqueue_enqueue_timeout(ctq->tq, &ctq->work, lio_ms_to_ticks(50));
  208 }

Cache object: fa9ede036a518119eda89026c1df5a4f


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