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/sysmacros.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/cyclic.h> 36 37 #include "sfxge.h" 38 #include "efx.h" 39 40 /* 41 * All efx_phy_*() must be after efx_port_init() 42 * 43 * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED 44 * to serialise against sfxge_restart() 45 * 46 * Note that there is no seperate PHY lock 47 * Everything is driven from MAC code and the MAC lock is used 48 */ 49 50 /* PHY DMA attributes */ 51 static ddi_device_acc_attr_t sfxge_phy_devacc = { 52 53 DDI_DEVICE_ATTR_V0, /* devacc_attr_version */ 54 DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */ 55 DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ 56 }; 57 58 static ddi_dma_attr_t sfxge_phy_dma_attr = { 59 DMA_ATTR_V0, /* dma_attr_version */ 60 0, /* dma_attr_addr_lo */ 61 0xffffffffffffffffull, /* dma_attr_addr_hi */ 62 0xffffffffffffffffull, /* dma_attr_count_max */ 63 0x1000, /* dma_attr_align */ 64 0xffffffff, /* dma_attr_burstsizes */ 65 1, /* dma_attr_minxfer */ 66 0xffffffffffffffffull, /* dma_attr_maxxfer */ 67 0xffffffffffffffffull, /* dma_attr_seg */ 68 1, /* dma_attr_sgllen */ 69 1, /* dma_attr_granular */ 70 0 /* dma_attr_flags */ 71 }; 72 73 74 static int 75 sfxge_phy_kstat_update(kstat_t *ksp, int rw) 76 { 77 sfxge_t *sp = ksp->ks_private; 78 sfxge_mac_t *smp = &(sp->s_mac); 79 sfxge_phy_t *spp = &(smp->sm_phy); 80 efx_nic_t *enp = sp->s_enp; 81 kstat_named_t *knp; 82 const efx_nic_cfg_t *encp; 83 int rc, sn; 84 85 if (rw != KSTAT_READ) { 86 rc = EACCES; 87 goto fail1; 88 } 89 90 ASSERT(mutex_owned(&(smp->sm_lock))); 91 92 if (smp->sm_state != SFXGE_MAC_STARTED) 93 goto done; 94 95 /* Synchronize the DMA memory for reading */ 96 (void) ddi_dma_sync(spp->sp_mem.esm_dma_handle, 97 0, EFX_PHY_STATS_SIZE, DDI_DMA_SYNC_FORKERNEL); 98 99 if ((rc = efx_phy_stats_update(enp, &spp->sp_mem, spp->sp_statbuf)) 100 != 0) 101 goto fail2; 102 103 knp = spp->sp_stat; 104 for (sn = 0; sn < EFX_PHY_NSTATS; sn++) { 105 knp->value.ui64 = spp->sp_statbuf[sn]; 106 knp++; 107 } 108 109 encp = efx_nic_cfg_get(enp); 110 knp->value.ui64 = encp->enc_port; 111 112 done: 113 return (0); 114 115 fail2: 116 DTRACE_PROBE(fail2); 117 fail1: 118 DTRACE_PROBE1(fail1, int, rc); 119 120 return (rc); 121 } 122 123 int 124 sfxge_phy_kstat_init(sfxge_t *sp) 125 { 126 dev_info_t *dip = sp->s_dip; 127 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 128 efx_nic_t *enp = sp->s_enp; 129 kstat_t *ksp; 130 kstat_named_t *knp; 131 const efx_nic_cfg_t *encp; 132 unsigned int id; 133 char name[MAXNAMELEN]; 134 int rc; 135 136 if ((spp->sp_statbuf = kmem_zalloc(sizeof (uint32_t) * EFX_PHY_NSTATS, 137 KM_NOSLEEP)) == NULL) { 138 rc = ENOMEM; 139 goto fail1; 140 } 141 142 encp = efx_nic_cfg_get(enp); 143 144 (void) snprintf(name, MAXNAMELEN - 1, "%s_%s", ddi_driver_name(dip), 145 encp->enc_phy_name); 146 147 /* Create the set */ 148 if ((ksp = kstat_create((char *)ddi_driver_name(dip), 149 ddi_get_instance(dip), name, "phy", KSTAT_TYPE_NAMED, 150 EFX_PHY_NSTATS + 1, 0)) == NULL) { 151 rc = ENOMEM; 152 goto fail2; 153 } 154 155 spp->sp_ksp = ksp; 156 157 ksp->ks_update = sfxge_phy_kstat_update; 158 ksp->ks_private = sp; 159 ksp->ks_lock = &(sp->s_mac.sm_lock); 160 161 /* Initialise the named stats */ 162 spp->sp_stat = knp = ksp->ks_data; 163 for (id = 0; id < EFX_PHY_NSTATS; id++) { 164 kstat_named_init(knp, (char *)efx_phy_stat_name(enp, id), 165 KSTAT_DATA_UINT64); 166 knp++; 167 } 168 169 kstat_named_init(knp, "port", KSTAT_DATA_UINT64); 170 kstat_install(ksp); 171 172 return (0); 173 174 fail2: 175 DTRACE_PROBE(fail2) 176 kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS); 177 178 fail1: 179 DTRACE_PROBE1(fail1, int, rc); 180 181 return (rc); 182 } 183 184 void 185 sfxge_phy_kstat_fini(sfxge_t *sp) 186 { 187 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 188 189 /* Destroy the set */ 190 kstat_delete(spp->sp_ksp); 191 spp->sp_ksp = NULL; 192 spp->sp_stat = NULL; 193 194 kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS); 195 } 196 197 198 int 199 sfxge_phy_init(sfxge_t *sp) 200 { 201 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 202 efsys_mem_t *esmp = &(spp->sp_mem); 203 sfxge_dma_buffer_attr_t dma_attr; 204 int rc; 205 206 dma_attr.sdba_dip = sp->s_dip; 207 dma_attr.sdba_dattrp = &sfxge_phy_dma_attr; 208 dma_attr.sdba_callback = DDI_DMA_SLEEP; 209 dma_attr.sdba_length = EFX_PHY_STATS_SIZE; 210 dma_attr.sdba_memflags = DDI_DMA_CONSISTENT; 211 dma_attr.sdba_devaccp = &sfxge_phy_devacc; 212 dma_attr.sdba_bindflags = DDI_DMA_READ | DDI_DMA_CONSISTENT; 213 dma_attr.sdba_maxcookies = 1; 214 dma_attr.sdba_zeroinit = B_TRUE; 215 216 if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0) 217 goto fail1; 218 219 return (0); 220 221 fail1: 222 DTRACE_PROBE1(fail1, int, rc); 223 SFXGE_OBJ_CHECK(spp, sfxge_phy_t); 224 225 return (rc); 226 } 227 228 uint8_t 229 sfxge_phy_lp_cap_test(sfxge_t *sp, uint32_t field) 230 { 231 sfxge_mac_t *smp = &(sp->s_mac); 232 uint32_t cap = 0; 233 234 mutex_enter(&(smp->sm_lock)); 235 236 if (smp->sm_state != SFXGE_MAC_STARTED) 237 goto done; 238 239 efx_phy_lp_cap_get(sp->s_enp, &cap); 240 241 done: 242 mutex_exit(&(smp->sm_lock)); 243 244 return (cap & (1 << field)); 245 } 246 247 /* 248 * Set up the advertised capabilities that may have been asked for 249 * when the mac was not in the state SFXGE_MAC_STARTED. 250 * Must be called after efx_port_init(). 251 */ 252 int 253 sfxge_phy_cap_apply(sfxge_t *sp, boolean_t use_default) 254 { 255 sfxge_mac_t *smp = &(sp->s_mac); 256 efx_nic_t *enp; 257 uint32_t adv_cap; 258 int rc; 259 int err; 260 261 ASSERT(mutex_owned(&(smp->sm_lock))); 262 263 enp = sp->s_enp; 264 265 if (use_default) 266 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap); 267 else 268 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &adv_cap); 269 270 adv_cap |= smp->sm_phy_cap_to_set; 271 smp->sm_phy_cap_to_set = 0; 272 adv_cap &= ~(smp->sm_phy_cap_to_unset); 273 smp->sm_phy_cap_to_unset = 0; 274 if ((err = efx_phy_adv_cap_set(enp, adv_cap)) != 0) { 275 if (err == EINVAL) { 276 /* 277 * The configuation wasn't accepted, so set to 278 * defaults. 279 */ 280 uint32_t requested = adv_cap; 281 uint32_t supported; 282 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &supported); 283 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap); 284 if ((rc = efx_phy_adv_cap_set(enp, adv_cap)) != 0) 285 goto fail1; 286 dev_err(sp->s_dip, CE_WARN, SFXGE_CMN_ERR 287 "Setting of advertised link capabilities failed. " 288 "Using default settings. " 289 "(Requested 0x%x Given 0x%x Supported 0x%x)", 290 requested, 291 adv_cap, 292 supported); 293 } else { 294 rc = err; 295 goto fail2; 296 } 297 } 298 299 return (0); 300 301 fail2: 302 DTRACE_PROBE(fail2); 303 304 fail1: 305 DTRACE_PROBE1(fail1, int, rc); 306 307 return (rc); 308 } 309 310 uint8_t 311 sfxge_phy_cap_test(sfxge_t *sp, uint32_t flag, uint32_t field, 312 boolean_t *mutablep) 313 { 314 sfxge_mac_t *smp = &(sp->s_mac); 315 efx_nic_t *enp; 316 uint32_t cap = 0; 317 uint32_t perm = 0; 318 319 mutex_enter(&(smp->sm_lock)); 320 enp = sp->s_enp; 321 322 if (smp->sm_state != SFXGE_MAC_STARTED) 323 goto done; 324 325 efx_phy_adv_cap_get(enp, flag, &cap); 326 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &perm); 327 328 done: 329 mutex_exit(&(smp->sm_lock)); 330 331 if (mutablep) 332 *mutablep = (perm & (1 << field)) ? B_TRUE : B_FALSE; 333 334 return ((cap & (1 << field)) ? 1 : 0); 335 } 336 337 338 int 339 sfxge_phy_cap_set(sfxge_t *sp, uint32_t field, int set) 340 { 341 sfxge_mac_t *smp = &(sp->s_mac); 342 efx_nic_t *enp = sp->s_enp; 343 uint32_t cap; 344 int rc = 0; 345 346 mutex_enter(&(smp->sm_lock)); 347 348 if (smp->sm_state != SFXGE_MAC_STARTED) { 349 /* Store the request for when the mac is started */ 350 if (set) 351 smp->sm_phy_cap_to_set |= (1 << field); 352 else 353 smp->sm_phy_cap_to_unset |= (1 << field); 354 goto done; 355 } 356 357 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &cap); 358 359 if (set) 360 cap |= (1 << field); 361 else 362 cap &= ~(1 << field); 363 364 rc = efx_phy_adv_cap_set(enp, cap); 365 done: 366 mutex_exit(&(smp->sm_lock)); 367 368 return (rc); 369 } 370 371 372 void 373 sfxge_phy_fini(sfxge_t *sp) 374 { 375 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 376 efsys_mem_t *esmp = &(spp->sp_mem); 377 378 sfxge_dma_buffer_destroy(esmp); 379 }