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