1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008-2013 Solarflare Communications Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/ddi.h>
  29 #include <sys/sunddi.h>
  30 #include <sys/stream.h>
  31 #include <sys/dlpi.h>
  32 
  33 #include "sfxge.h"
  34 
  35 void
  36 sfxge_sram_init(sfxge_t *sp)
  37 {
  38         sfxge_sram_t *ssp = &(sp->s_sram);
  39         dev_info_t *dip = sp->s_dip;
  40         char name[MAXNAMELEN];
  41 
  42         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_UNINITIALIZED);
  43 
  44         mutex_init(&(ssp->ss_lock), NULL, MUTEX_DRIVER, NULL);
  45 
  46         /*
  47          * Create a VMEM arena for the buffer table
  48          * Note that these are not in the DDI/DKI.
  49          * See "man rmalloc" for a possible alternative
  50          */
  51         (void) snprintf(name, MAXNAMELEN - 1, "%s%d_sram", ddi_driver_name(dip),
  52             ddi_get_instance(dip));
  53         ssp->ss_buf_tbl = vmem_create(name, (void *)1, EFX_BUF_TBL_SIZE, 1,
  54             NULL, NULL, NULL, 1, VM_SLEEP | VMC_IDENTIFIER);
  55 
  56         ssp->ss_state = SFXGE_SRAM_INITIALIZED;
  57 }
  58 
  59 int
  60 sfxge_sram_buf_tbl_alloc(sfxge_t *sp, size_t n, uint32_t *idp)
  61 {
  62         sfxge_sram_t *ssp = &(sp->s_sram);
  63         void *base;
  64         int rc;
  65 
  66         mutex_enter(&(ssp->ss_lock));
  67 
  68         ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
  69 
  70         if ((base = vmem_alloc(ssp->ss_buf_tbl, n, VM_NOSLEEP)) == NULL) {
  71                 rc = ENOSPC;
  72                 goto fail1;
  73         }
  74 
  75         *idp = (uint32_t)((uintptr_t)base - 1);
  76 
  77         mutex_exit(&(ssp->ss_lock));
  78 
  79         return (0);
  80 
  81 fail1:
  82         DTRACE_PROBE1(fail1, int, rc);
  83 
  84         mutex_exit(&(ssp->ss_lock));
  85 
  86         return (rc);
  87 }
  88 
  89 int
  90 sfxge_sram_start(sfxge_t *sp)
  91 {
  92         sfxge_sram_t *ssp = &(sp->s_sram);
  93 
  94         mutex_enter(&(ssp->ss_lock));
  95 
  96         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
  97         ASSERT3U(ssp->ss_count, ==, 0);
  98 
  99         ssp->ss_state = SFXGE_SRAM_STARTED;
 100 
 101         mutex_exit(&(ssp->ss_lock));
 102 
 103         return (0);
 104 }
 105 
 106 int
 107 sfxge_sram_buf_tbl_set(sfxge_t *sp, uint32_t id, efsys_mem_t *esmp,
 108     size_t n)
 109 {
 110         sfxge_sram_t *ssp = &(sp->s_sram);
 111         int rc;
 112 
 113         mutex_enter(&(ssp->ss_lock));
 114 
 115         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
 116 
 117         if ((rc = efx_sram_buf_tbl_set(sp->s_enp, id, esmp, n)) != 0)
 118                 goto fail1;
 119 
 120         ssp->ss_count += n;
 121 
 122         mutex_exit(&(ssp->ss_lock));
 123 
 124         return (0);
 125 
 126 fail1:
 127         DTRACE_PROBE1(fail1, int, rc);
 128 
 129         mutex_exit(&(ssp->ss_lock));
 130 
 131         return (rc);
 132 }
 133 
 134 void
 135 sfxge_sram_buf_tbl_clear(sfxge_t *sp, uint32_t id, size_t n)
 136 {
 137         sfxge_sram_t *ssp = &(sp->s_sram);
 138 
 139         mutex_enter(&(ssp->ss_lock));
 140 
 141         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
 142 
 143         ASSERT3U(ssp->ss_count, >=, n);
 144         ssp->ss_count -= n;
 145 
 146         efx_sram_buf_tbl_clear(sp->s_enp, id, n);
 147 
 148         mutex_exit(&(ssp->ss_lock));
 149 }
 150 
 151 void
 152 sfxge_sram_stop(sfxge_t *sp)
 153 {
 154         sfxge_sram_t *ssp = &(sp->s_sram);
 155 
 156         mutex_enter(&(ssp->ss_lock));
 157 
 158         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
 159         ASSERT3U(ssp->ss_count, ==, 0);
 160 
 161         ssp->ss_state = SFXGE_SRAM_INITIALIZED;
 162 
 163         mutex_exit(&(ssp->ss_lock));
 164 }
 165 
 166 void
 167 sfxge_sram_buf_tbl_free(sfxge_t *sp, uint32_t id, size_t n)
 168 {
 169         sfxge_sram_t *ssp = &(sp->s_sram);
 170         void *base;
 171 
 172         mutex_enter(&(ssp->ss_lock));
 173 
 174         ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
 175 
 176         base = (void *)((uintptr_t)id + 1);
 177         vmem_free(ssp->ss_buf_tbl, base, n);
 178 
 179         mutex_exit(&(ssp->ss_lock));
 180 }
 181 
 182 static int
 183 sfxge_sram_test(sfxge_t *sp, efx_pattern_type_t type)
 184 {
 185         sfxge_sram_t *ssp = &(sp->s_sram);
 186         int rc;
 187 
 188         if (ssp->ss_state != SFXGE_SRAM_INITIALIZED) {
 189                 rc = EFAULT;
 190                 goto fail1;
 191         }
 192 
 193         if (type >= EFX_PATTERN_NTYPES) {
 194                 rc = EINVAL;
 195                 goto fail2;
 196         }
 197 
 198         mutex_enter(&(ssp->ss_lock));
 199 
 200         if ((rc = efx_sram_test(sp->s_enp, type)) != 0)
 201                 goto fail3;
 202 
 203         mutex_exit(&(ssp->ss_lock));
 204 
 205         return (0);
 206 
 207 fail3:
 208         DTRACE_PROBE(fail3);
 209         mutex_exit(&(ssp->ss_lock));
 210 fail2:
 211         DTRACE_PROBE(fail2);
 212 fail1:
 213         DTRACE_PROBE1(fail1, int, rc);
 214 
 215         return (rc);
 216 }
 217 
 218 int
 219 sfxge_sram_ioctl(sfxge_t *sp, sfxge_sram_ioc_t *ssip)
 220 {
 221         int rc;
 222 
 223         switch (ssip->ssi_op) {
 224         case SFXGE_SRAM_OP_TEST: {
 225                 efx_pattern_type_t type = ssip->ssi_data;
 226 
 227                 if ((rc = sfxge_sram_test(sp, type)) != 0)
 228                         goto fail1;
 229 
 230                 break;
 231         }
 232         default:
 233                 rc = ENOTSUP;
 234                 goto fail1;
 235         }
 236 
 237         return (0);
 238 
 239 fail1:
 240         DTRACE_PROBE1(fail1, int, rc);
 241 
 242         return (rc);
 243 }
 244 
 245 void
 246 sfxge_sram_fini(sfxge_t *sp)
 247 {
 248         sfxge_sram_t *ssp = &(sp->s_sram);
 249 
 250         ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
 251 
 252         /* Destroy the VMEM arena */
 253         vmem_destroy(ssp->ss_buf_tbl);
 254         ssp->ss_buf_tbl = NULL;
 255 
 256         mutex_destroy(&(ssp->ss_lock));
 257 
 258         ssp->ss_state = SFXGE_SRAM_UNINITIALIZED;
 259 }