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 }