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
sfxge_phy_kstat_update(kstat_t * ksp,int rw)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
sfxge_phy_kstat_init(sfxge_t * sp)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
sfxge_phy_kstat_fini(sfxge_t * sp)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
sfxge_phy_init(sfxge_t * sp)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
sfxge_phy_lp_cap_test(sfxge_t * sp,uint32_t field)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
sfxge_phy_cap_apply(sfxge_t * sp,boolean_t use_default)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
sfxge_phy_cap_test(sfxge_t * sp,uint32_t flag,uint32_t field,boolean_t * mutablep)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
sfxge_phy_cap_set(sfxge_t * sp,uint32_t field,int set)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
sfxge_phy_fini(sfxge_t * sp)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 }
379