1 /*
   2  * Copyright (c) 2008-2015 Solarflare Communications Inc.
   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 are met:
   7  *
   8  * 1. Redistributions of source code must retain the above copyright notice,
   9  *    this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright notice,
  11  *    this list of conditions and the following disclaimer in the documentation
  12  *    and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  *
  26  * The views and conclusions contained in the software and documentation are
  27  * those of the authors and should not be interpreted as representing official
  28  * policies, either expressed or implied, of the FreeBSD Project.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/ddi.h>
  33 #include <sys/sunddi.h>
  34 #include <sys/stream.h>
  35 #include <sys/dlpi.h>
  36 
  37 #include "sfxge.h"
  38 
  39 void
  40 sfxge_sram_init(sfxge_t *sp)
  41 {
  42         sfxge_sram_t *ssp = &(sp->s_sram);
  43         dev_info_t *dip = sp->s_dip;
  44         char name[MAXNAMELEN];
  45 
  46         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_UNINITIALIZED);
  47 
  48         mutex_init(&(ssp->ss_lock), NULL, MUTEX_DRIVER, NULL);
  49 
  50         /*
  51          * Create a VMEM arena for the buffer table
  52          * Note that these are not in the DDI/DKI.
  53          * See "man rmalloc" for a possible alternative
  54          */
  55         (void) snprintf(name, MAXNAMELEN - 1, "%s%d_sram", ddi_driver_name(dip),
  56             ddi_get_instance(dip));
  57         ssp->ss_buf_tbl = vmem_create(name, (void *)1, EFX_BUF_TBL_SIZE, 1,
  58             NULL, NULL, NULL, 1, VM_SLEEP | VMC_IDENTIFIER);
  59 
  60         ssp->ss_state = SFXGE_SRAM_INITIALIZED;
  61 }
  62 
  63 int
  64 sfxge_sram_buf_tbl_alloc(sfxge_t *sp, size_t n, uint32_t *idp)
  65 {
  66         sfxge_sram_t *ssp = &(sp->s_sram);
  67         void *base;
  68         int rc;
  69 
  70         mutex_enter(&(ssp->ss_lock));
  71 
  72         ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
  73 
  74         if ((base = vmem_alloc(ssp->ss_buf_tbl, n, VM_NOSLEEP)) == NULL) {
  75                 rc = ENOSPC;
  76                 goto fail1;
  77         }
  78 
  79         *idp = (uint32_t)((uintptr_t)base - 1);
  80 
  81         mutex_exit(&(ssp->ss_lock));
  82 
  83         return (0);
  84 
  85 fail1:
  86         DTRACE_PROBE1(fail1, int, rc);
  87 
  88         mutex_exit(&(ssp->ss_lock));
  89 
  90         return (rc);
  91 }
  92 
  93 int
  94 sfxge_sram_start(sfxge_t *sp)
  95 {
  96         sfxge_sram_t *ssp = &(sp->s_sram);
  97 
  98         mutex_enter(&(ssp->ss_lock));
  99 
 100         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
 101         ASSERT3U(ssp->ss_count, ==, 0);
 102 
 103         ssp->ss_state = SFXGE_SRAM_STARTED;
 104 
 105         mutex_exit(&(ssp->ss_lock));
 106 
 107         return (0);
 108 }
 109 
 110 int
 111 sfxge_sram_buf_tbl_set(sfxge_t *sp, uint32_t id, efsys_mem_t *esmp,
 112     size_t n)
 113 {
 114         sfxge_sram_t *ssp = &(sp->s_sram);
 115         int rc;
 116 
 117         mutex_enter(&(ssp->ss_lock));
 118 
 119         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
 120 
 121         if ((rc = efx_sram_buf_tbl_set(sp->s_enp, id, esmp, n)) != 0)
 122                 goto fail1;
 123 
 124         ssp->ss_count += n;
 125 
 126         mutex_exit(&(ssp->ss_lock));
 127 
 128         return (0);
 129 
 130 fail1:
 131         DTRACE_PROBE1(fail1, int, rc);
 132 
 133         mutex_exit(&(ssp->ss_lock));
 134 
 135         return (rc);
 136 }
 137 
 138 void
 139 sfxge_sram_buf_tbl_clear(sfxge_t *sp, uint32_t id, size_t n)
 140 {
 141         sfxge_sram_t *ssp = &(sp->s_sram);
 142 
 143         mutex_enter(&(ssp->ss_lock));
 144 
 145         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
 146 
 147         ASSERT3U(ssp->ss_count, >=, n);
 148         ssp->ss_count -= n;
 149 
 150         efx_sram_buf_tbl_clear(sp->s_enp, id, n);
 151 
 152         mutex_exit(&(ssp->ss_lock));
 153 }
 154 
 155 void
 156 sfxge_sram_stop(sfxge_t *sp)
 157 {
 158         sfxge_sram_t *ssp = &(sp->s_sram);
 159 
 160         mutex_enter(&(ssp->ss_lock));
 161 
 162         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
 163         ASSERT3U(ssp->ss_count, ==, 0);
 164 
 165         ssp->ss_state = SFXGE_SRAM_INITIALIZED;
 166 
 167         mutex_exit(&(ssp->ss_lock));
 168 }
 169 
 170 void
 171 sfxge_sram_buf_tbl_free(sfxge_t *sp, uint32_t id, size_t n)
 172 {
 173         sfxge_sram_t *ssp = &(sp->s_sram);
 174         void *base;
 175 
 176         mutex_enter(&(ssp->ss_lock));
 177 
 178         ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
 179 
 180         base = (void *)((uintptr_t)id + 1);
 181         vmem_free(ssp->ss_buf_tbl, base, n);
 182 
 183         mutex_exit(&(ssp->ss_lock));
 184 }
 185 
 186 void
 187 sfxge_sram_fini(sfxge_t *sp)
 188 {
 189         sfxge_sram_t *ssp = &(sp->s_sram);
 190 
 191         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
 192 
 193         /* Destroy the VMEM arena */
 194         vmem_destroy(ssp->ss_buf_tbl);
 195         ssp->ss_buf_tbl = NULL;
 196 
 197         mutex_destroy(&(ssp->ss_lock));
 198 
 199         ssp->ss_state = SFXGE_SRAM_UNINITIALIZED;
 200 }