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/sysmacros.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/cyclic.h> 32 33 #include "sfxge.h" 34 35 #include "efx.h" 36 37 /* Monitor DMA attributes */ 38 static ddi_device_acc_attr_t sfxge_mon_devacc = { 39 40 DDI_DEVICE_ATTR_V0, /* devacc_attr_version */ 41 DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */ 42 DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ 43 }; 44 45 static ddi_dma_attr_t sfxge_mon_dma_attr = { 46 DMA_ATTR_V0, /* dma_attr_version */ 47 0, /* dma_attr_addr_lo */ 48 0xffffffffffffffffull, /* dma_attr_addr_hi */ 49 0xffffffffffffffffull, /* dma_attr_count_max */ 50 0x1000, /* dma_attr_align */ 51 0xffffffff, /* dma_attr_burstsizes */ 52 1, /* dma_attr_minxfer */ 53 0xffffffffffffffffull, /* dma_attr_maxxfer */ 54 0xffffffffffffffffull, /* dma_attr_seg */ 55 1, /* dma_attr_sgllen */ 56 1, /* dma_attr_granular */ 57 0 /* dma_attr_flags */ 58 }; 59 60 61 static int 62 sfxge_mon_kstat_update(kstat_t *ksp, int rw) 63 { 64 sfxge_t *sp = ksp->ks_private; 65 sfxge_mon_t *smp = &(sp->s_mon); 66 efsys_mem_t *esmp = &(smp->sm_mem); 67 efx_nic_t *enp = sp->s_enp; 68 kstat_named_t *knp; 69 int rc, sn; 70 71 if (rw != KSTAT_READ) { 72 rc = EACCES; 73 goto fail1; 74 } 75 76 ASSERT(mutex_owned(&(smp->sm_lock))); 77 78 if (smp->sm_state != SFXGE_MON_STARTED) 79 goto done; 80 81 /* Synchronize the DMA memory for reading */ 82 (void) ddi_dma_sync(smp->sm_mem.esm_dma_handle, 83 0, 84 EFX_MON_STATS_SIZE, 85 DDI_DMA_SYNC_FORKERNEL); 86 87 if ((rc = efx_mon_stats_update(enp, esmp, smp->sm_statbuf)) != 0) 88 goto fail2; 89 90 knp = smp->sm_stat; 91 for (sn = 0; sn < EFX_MON_NSTATS; sn++) { 92 knp->value.ui64 = smp->sm_statbuf[sn].emsv_value; 93 knp++; 94 } 95 96 knp->value.ui32 = sp->s_num_restarts; 97 knp++; 98 knp->value.ui32 = sp->s_num_restarts_hw_err; 99 knp++; 100 101 done: 102 return (0); 103 104 fail2: 105 DTRACE_PROBE(fail2); 106 fail1: 107 DTRACE_PROBE1(fail1, int, rc); 108 109 return (rc); 110 } 111 112 static int 113 sfxge_mon_kstat_init(sfxge_t *sp) 114 { 115 sfxge_mon_t *smp = &(sp->s_mon); 116 dev_info_t *dip = sp->s_dip; 117 efx_nic_t *enp = sp->s_enp; 118 kstat_t *ksp; 119 kstat_named_t *knp; 120 char name[MAXNAMELEN]; 121 unsigned int id; 122 int rc; 123 124 if ((smp->sm_statbuf = kmem_zalloc(sizeof (uint32_t) * EFX_MON_NSTATS, 125 KM_NOSLEEP)) == NULL) { 126 rc = ENOMEM; 127 goto fail1; 128 } 129 130 (void) snprintf(name, MAXNAMELEN - 1, "%s_%s", ddi_driver_name(dip), 131 efx_mon_name(enp)); 132 133 /* Create the set */ 134 if ((ksp = kstat_create((char *)ddi_driver_name(dip), 135 ddi_get_instance(dip), name, "mon", KSTAT_TYPE_NAMED, 136 EFX_MON_NSTATS+2, 0)) == NULL) { 137 rc = ENOMEM; 138 goto fail2; 139 } 140 141 smp->sm_ksp = ksp; 142 143 ksp->ks_update = sfxge_mon_kstat_update; 144 ksp->ks_private = sp; 145 ksp->ks_lock = &(smp->sm_lock); 146 147 /* Initialise the named stats */ 148 smp->sm_stat = knp = ksp->ks_data; 149 for (id = 0; id < EFX_MON_NSTATS; id++) { 150 kstat_named_init(knp, (char *)efx_mon_stat_name(enp, id), 151 KSTAT_DATA_UINT64); 152 knp++; 153 } 154 kstat_named_init(knp, "num_restarts", KSTAT_DATA_UINT32); 155 knp++; 156 kstat_named_init(knp, "num_restarts_hw_err", KSTAT_DATA_UINT32); 157 knp++; 158 159 kstat_install(ksp); 160 161 return (0); 162 163 fail2: 164 DTRACE_PROBE(fail2); 165 kmem_free(smp->sm_statbuf, sizeof (uint32_t) * EFX_MON_NSTATS); 166 fail1: 167 DTRACE_PROBE1(fail1, int, rc); 168 169 return (rc); 170 } 171 172 static void 173 sfxge_mon_kstat_fini(sfxge_t *sp) 174 { 175 sfxge_mon_t *smp = &(sp->s_mon); 176 177 /* Destroy the set */ 178 kstat_delete(smp->sm_ksp); 179 smp->sm_ksp = NULL; 180 smp->sm_stat = NULL; 181 182 kmem_free(smp->sm_statbuf, sizeof (uint32_t) * EFX_MON_NSTATS); 183 } 184 185 int 186 sfxge_mon_init(sfxge_t *sp) 187 { 188 sfxge_mon_t *smp = &(sp->s_mon); 189 efx_nic_t *enp = sp->s_enp; 190 efsys_mem_t *esmp = &(smp->sm_mem); 191 sfxge_dma_buffer_attr_t dma_attr; 192 const efx_nic_cfg_t *encp; 193 int rc; 194 195 SFXGE_OBJ_CHECK(smp, sfxge_mon_t); 196 197 ASSERT3U(smp->sm_state, ==, SFXGE_MON_UNINITIALIZED); 198 199 smp->sm_sp = sp; 200 201 mutex_init(&(smp->sm_lock), NULL, MUTEX_DRIVER, NULL); 202 203 dma_attr.sdba_dip = sp->s_dip; 204 dma_attr.sdba_dattrp = &sfxge_mon_dma_attr; 205 dma_attr.sdba_callback = DDI_DMA_SLEEP; 206 dma_attr.sdba_length = EFX_MON_STATS_SIZE; 207 dma_attr.sdba_memflags = DDI_DMA_CONSISTENT; 208 dma_attr.sdba_devaccp = &sfxge_mon_devacc; 209 dma_attr.sdba_bindflags = DDI_DMA_READ | DDI_DMA_CONSISTENT; 210 dma_attr.sdba_maxcookies = 1; 211 dma_attr.sdba_zeroinit = B_TRUE; 212 213 if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0) 214 goto fail1; 215 216 encp = efx_nic_cfg_get(enp); 217 smp->sm_type = encp->enc_mon_type; 218 219 DTRACE_PROBE1(mon, efx_mon_type_t, smp->sm_type); 220 221 smp->sm_state = SFXGE_MON_INITIALIZED; 222 223 /* Initialize the statistics */ 224 if ((rc = sfxge_mon_kstat_init(sp)) != 0) 225 goto fail2; 226 227 return (0); 228 229 fail2: 230 DTRACE_PROBE(fail2); 231 232 /* Tear down DMA setup */ 233 sfxge_dma_buffer_destroy(esmp); 234 235 fail1: 236 DTRACE_PROBE1(fail1, int, rc); 237 mutex_destroy(&(smp->sm_lock)); 238 239 smp->sm_sp = NULL; 240 241 SFXGE_OBJ_CHECK(smp, sfxge_mac_t); 242 243 return (rc); 244 } 245 246 int 247 sfxge_mon_start(sfxge_t *sp) 248 { 249 sfxge_mon_t *smp = &(sp->s_mon); 250 int rc; 251 252 mutex_enter(&(smp->sm_lock)); 253 ASSERT3U(smp->sm_state, ==, SFXGE_MON_INITIALIZED); 254 255 /* Initialize the MON module */ 256 if ((rc = efx_mon_init(sp->s_enp)) != 0) 257 goto fail1; 258 259 smp->sm_state = SFXGE_MON_STARTED; 260 261 mutex_exit(&(smp->sm_lock)); 262 263 return (0); 264 265 fail1: 266 DTRACE_PROBE1(fail1, int, rc); 267 268 mutex_exit(&(smp->sm_lock)); 269 270 return (rc); 271 } 272 273 void 274 sfxge_mon_stop(sfxge_t *sp) 275 { 276 sfxge_mon_t *smp = &(sp->s_mon); 277 278 mutex_enter(&(smp->sm_lock)); 279 280 ASSERT3U(smp->sm_state, ==, SFXGE_MON_STARTED); 281 smp->sm_state = SFXGE_MON_INITIALIZED; 282 283 /* Tear down the MON module */ 284 efx_mon_fini(sp->s_enp); 285 286 mutex_exit(&(smp->sm_lock)); 287 } 288 289 void 290 sfxge_mon_fini(sfxge_t *sp) 291 { 292 sfxge_mon_t *smp = &(sp->s_mon); 293 efsys_mem_t *esmp = &(smp->sm_mem); 294 295 ASSERT3U(smp->sm_state, ==, SFXGE_MON_INITIALIZED); 296 297 /* Tear down the statistics */ 298 sfxge_mon_kstat_fini(sp); 299 300 smp->sm_state = SFXGE_MON_UNINITIALIZED; 301 mutex_destroy(&(smp->sm_lock)); 302 303 smp->sm_sp = NULL; 304 smp->sm_type = EFX_MON_INVALID; 305 306 /* Tear down DMA setup */ 307 sfxge_dma_buffer_destroy(esmp); 308 309 SFXGE_OBJ_CHECK(smp, sfxge_mon_t); 310 }