Print this page
MFV: illumos-joyent@61dc3dec4f82a3e13e94609a0a83d5f66c64e760
OS-6846 want i40e multi-group support
OS-7372 i40e_alloc_ring_mem() unwinds when it shouldn't
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Author: Ryan Zezeski <rpz@joyent.com>
MFV: illumos-joyent@9e30beee2f0c127bf41868db46257124206e28d6
OS-5225 Want Fortville TSO support
Reviewed by: Ryan Zezeski <rpz@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
Author: Rob Johnston <rob.johnston@joyent.com>
MFV: illumos-gate@286d309c80aad9eac1fdbcb0388ed194d995d837
9805 i40e should read SFP data when firmware supports it
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Rob Johnston <rob.johnston@joyent.com>
Reviewed by: Dale Ghent <dale.ghent@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Dan McDonald <danmcd@joyent.com>
Author: Robert Mustacchi <rm@joyent.com>
NEX-13226 xvv710 25Gb NIC panics system under load
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-7822 40Gb Intel XL710 NIC performance data
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/i40e/i40e_gld.c
+++ new/usr/src/uts/common/io/i40e/i40e_gld.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
14 - * Copyright (c) 2017, Joyent, Inc.
14 + * Copyright (c) 2018, Joyent, Inc.
15 15 * Copyright 2017 Tegile Systems, Inc. All rights reserved.
16 16 */
17 17
18 18 /*
19 19 * For more information, please see the big theory statement in i40e_main.c.
20 20 */
21 21
22 22 #include "i40e_sw.h"
23 23
24 24 #define I40E_PROP_RX_DMA_THRESH "_rx_dma_threshold"
25 25 #define I40E_PROP_TX_DMA_THRESH "_tx_dma_threshold"
26 26 #define I40E_PROP_RX_ITR "_rx_intr_throttle"
27 27 #define I40E_PROP_TX_ITR "_tx_intr_throttle"
28 28 #define I40E_PROP_OTHER_ITR "_other_intr_throttle"
29 29
30 30 char *i40e_priv_props[] = {
31 31 I40E_PROP_RX_DMA_THRESH,
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
32 32 I40E_PROP_TX_DMA_THRESH,
33 33 I40E_PROP_RX_ITR,
34 34 I40E_PROP_TX_ITR,
35 35 I40E_PROP_OTHER_ITR,
36 36 NULL
37 37 };
38 38
39 39 static int
40 40 i40e_group_remove_mac(void *arg, const uint8_t *mac_addr)
41 41 {
42 - i40e_t *i40e = arg;
42 + i40e_rx_group_t *rxg = arg;
43 + i40e_t *i40e = rxg->irg_i40e;
43 44 struct i40e_aqc_remove_macvlan_element_data filt;
44 45 struct i40e_hw *hw = &i40e->i40e_hw_space;
45 46 int ret, i, last;
46 47 i40e_uaddr_t *iua;
47 48
48 49 if (I40E_IS_MULTICAST(mac_addr))
49 50 return (EINVAL);
50 51
51 52 mutex_enter(&i40e->i40e_general_lock);
52 53
53 54 if (i40e->i40e_state & I40E_SUSPENDED) {
54 55 ret = ECANCELED;
55 56 goto done;
56 57 }
57 58
58 59 for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
59 60 if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
60 61 ETHERADDRL) == 0)
61 62 break;
62 63 }
63 64
64 65 if (i == i40e->i40e_resources.ifr_nmacfilt_used) {
65 66 ret = ENOENT;
66 67 goto done;
67 68 }
68 69
69 70 iua = &i40e->i40e_uaddrs[i];
70 71 ASSERT(i40e->i40e_resources.ifr_nmacfilt_used > 0);
71 72
72 73 bzero(&filt, sizeof (filt));
73 74 bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
74 75 filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
75 76 I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
76 77
77 78 if (i40e_aq_remove_macvlan(hw, iua->iua_vsi, &filt, 1, NULL) !=
78 79 I40E_SUCCESS) {
79 80 i40e_error(i40e, "failed to remove mac address "
80 81 "%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d",
81 82 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
82 83 mac_addr[4], mac_addr[5], filt.error_code);
83 84 ret = EIO;
84 85 goto done;
85 86 }
86 87
87 88 last = i40e->i40e_resources.ifr_nmacfilt_used - 1;
88 89 if (i != last) {
89 90 i40e_uaddr_t *src = &i40e->i40e_uaddrs[last];
90 91 bcopy(src, iua, sizeof (i40e_uaddr_t));
91 92 }
92 93
93 94 /*
94 95 * Set the multicast bit in the last one to indicate to ourselves that
95 96 * it's invalid.
96 97 */
97 98 bzero(&i40e->i40e_uaddrs[last], sizeof (i40e_uaddr_t));
98 99 i40e->i40e_uaddrs[last].iua_mac[0] = 0x01;
99 100 i40e->i40e_resources.ifr_nmacfilt_used--;
|
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
100 101 ret = 0;
101 102 done:
102 103 mutex_exit(&i40e->i40e_general_lock);
103 104
104 105 return (ret);
105 106 }
106 107
107 108 static int
108 109 i40e_group_add_mac(void *arg, const uint8_t *mac_addr)
109 110 {
110 - i40e_t *i40e = arg;
111 - struct i40e_hw *hw = &i40e->i40e_hw_space;
112 - int i, ret;
113 - i40e_uaddr_t *iua;
111 + i40e_rx_group_t *rxg = arg;
112 + i40e_t *i40e = rxg->irg_i40e;
113 + struct i40e_hw *hw = &i40e->i40e_hw_space;
114 + int i, ret;
115 + i40e_uaddr_t *iua;
114 116 struct i40e_aqc_add_macvlan_element_data filt;
115 117
116 118 if (I40E_IS_MULTICAST(mac_addr))
117 119 return (EINVAL);
118 120
119 121 mutex_enter(&i40e->i40e_general_lock);
120 122 if (i40e->i40e_state & I40E_SUSPENDED) {
121 123 ret = ECANCELED;
122 124 goto done;
123 125 }
124 126
125 127 if (i40e->i40e_resources.ifr_nmacfilt ==
126 128 i40e->i40e_resources.ifr_nmacfilt_used) {
127 129 ret = ENOSPC;
128 130 goto done;
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
129 131 }
130 132
131 133 for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
132 134 if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
133 135 ETHERADDRL) == 0) {
134 136 ret = EEXIST;
135 137 goto done;
136 138 }
137 139 }
138 140
139 - /*
140 - * Note, the general use of the i40e_vsi_id will have to be refactored
141 - * when we have proper group support.
142 - */
143 141 bzero(&filt, sizeof (filt));
144 142 bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
145 143 filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH |
146 144 I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
147 145
148 - if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1,
146 + if ((ret = i40e_aq_add_macvlan(hw, rxg->irg_vsi_seid, &filt, 1,
149 147 NULL)) != I40E_SUCCESS) {
150 148 i40e_error(i40e, "failed to add mac address "
151 149 "%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d",
152 150 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
153 151 mac_addr[4], mac_addr[5], ret);
154 152 ret = EIO;
155 153 goto done;
156 154 }
157 155
158 156 iua = &i40e->i40e_uaddrs[i40e->i40e_resources.ifr_nmacfilt_used];
159 157 bcopy(mac_addr, iua->iua_mac, ETHERADDRL);
160 - iua->iua_vsi = i40e->i40e_vsi_id;
158 + iua->iua_vsi = rxg->irg_vsi_seid;
161 159 i40e->i40e_resources.ifr_nmacfilt_used++;
162 160 ASSERT(i40e->i40e_resources.ifr_nmacfilt_used <=
163 161 i40e->i40e_resources.ifr_nmacfilt);
164 162 ret = 0;
165 163 done:
166 164 mutex_exit(&i40e->i40e_general_lock);
167 165 return (ret);
168 166 }
169 167
170 168 static int
171 169 i40e_m_start(void *arg)
172 170 {
173 171 i40e_t *i40e = arg;
174 172 int rc = 0;
175 173
176 174 mutex_enter(&i40e->i40e_general_lock);
177 175 if (i40e->i40e_state & I40E_SUSPENDED) {
178 176 rc = ECANCELED;
179 177 goto done;
180 178 }
181 179
182 180 if (!i40e_start(i40e, B_TRUE)) {
183 181 rc = EIO;
184 182 goto done;
185 183 }
186 184
187 185 atomic_or_32(&i40e->i40e_state, I40E_STARTED);
188 186 done:
189 187 mutex_exit(&i40e->i40e_general_lock);
190 188
191 189 return (rc);
192 190 }
193 191
194 192 static void
195 193 i40e_m_stop(void *arg)
196 194 {
197 195 i40e_t *i40e = arg;
198 196
199 197 mutex_enter(&i40e->i40e_general_lock);
200 198
201 199 if (i40e->i40e_state & I40E_SUSPENDED)
202 200 goto done;
203 201
204 202 atomic_and_32(&i40e->i40e_state, ~I40E_STARTED);
205 203 i40e_stop(i40e, B_TRUE);
206 204 done:
207 205 mutex_exit(&i40e->i40e_general_lock);
208 206 }
209 207
210 208 /*
211 209 * Enable and disable promiscuous mode as requested. We have to toggle both
212 210 * unicast and multicast. Note that multicast may already be enabled due to the
213 211 * i40e_m_multicast may toggle it itself. See i40e_main.c for more information
214 212 * on this.
215 213 */
216 214 static int
217 215 i40e_m_promisc(void *arg, boolean_t on)
218 216 {
219 217 i40e_t *i40e = arg;
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
220 218 struct i40e_hw *hw = &i40e->i40e_hw_space;
221 219 int ret = 0, err = 0;
222 220
223 221 mutex_enter(&i40e->i40e_general_lock);
224 222 if (i40e->i40e_state & I40E_SUSPENDED) {
225 223 ret = ECANCELED;
226 224 goto done;
227 225 }
228 226
229 227
230 - ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id,
228 + ret = i40e_aq_set_vsi_unicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
231 229 on, NULL, B_FALSE);
232 230 if (ret != I40E_SUCCESS) {
233 231 i40e_error(i40e, "failed to %s unicast promiscuity on "
234 232 "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
235 233 ret);
236 234 err = EIO;
237 235 goto done;
238 236 }
239 237
240 238 /*
241 239 * If we have a non-zero mcast_promisc_count, then it has already been
242 240 * enabled or we need to leave it that way and not touch it.
243 241 */
244 242 if (i40e->i40e_mcast_promisc_count > 0) {
245 243 i40e->i40e_promisc_on = on;
246 244 goto done;
247 245 }
248 246
249 - ret = i40e_aq_set_vsi_multicast_promiscuous(hw, i40e->i40e_vsi_id,
247 + ret = i40e_aq_set_vsi_multicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
250 248 on, NULL);
251 249 if (ret != I40E_SUCCESS) {
252 250 i40e_error(i40e, "failed to %s multicast promiscuity on "
253 251 "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
254 252 ret);
255 253
256 254 /*
257 255 * Try our best to put us back into a state that MAC expects us
258 256 * to be in.
259 257 */
260 - ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id,
261 - !on, NULL, B_FALSE);
258 + ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
259 + I40E_DEF_VSI_SEID(i40e), !on, NULL, B_FALSE);
262 260 if (ret != I40E_SUCCESS) {
263 261 i40e_error(i40e, "failed to %s unicast promiscuity on "
264 262 "the default VSI after toggling multicast failed: "
265 263 "%d", on == B_TRUE ? "disable" : "enable", ret);
266 264 }
267 265
268 266 err = EIO;
269 267 goto done;
270 268 } else {
271 269 i40e->i40e_promisc_on = on;
272 270 }
273 271
274 272 done:
275 273 mutex_exit(&i40e->i40e_general_lock);
276 274 return (err);
277 275 }
278 276
279 277 /*
280 278 * See the big theory statement in i40e_main.c for multicast address management.
281 279 */
282 280 static int
283 281 i40e_multicast_add(i40e_t *i40e, const uint8_t *multicast_address)
284 282 {
285 283 struct i40e_hw *hw = &i40e->i40e_hw_space;
286 284 struct i40e_aqc_add_macvlan_element_data filt;
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
287 285 i40e_maddr_t *mc;
288 286 int ret;
289 287
290 288 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
291 289
292 290 if (i40e->i40e_resources.ifr_nmcastfilt_used ==
293 291 i40e->i40e_resources.ifr_nmcastfilt) {
294 292 if (i40e->i40e_mcast_promisc_count == 0 &&
295 293 i40e->i40e_promisc_on == B_FALSE) {
296 294 ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
297 - i40e->i40e_vsi_id, B_TRUE, NULL);
295 + I40E_DEF_VSI_SEID(i40e), B_TRUE, NULL);
298 296 if (ret != I40E_SUCCESS) {
299 297 i40e_error(i40e, "failed to enable multicast "
300 298 "promiscuous mode on VSI %d: %d",
301 - i40e->i40e_vsi_id, ret);
299 + I40E_DEF_VSI_SEID(i40e), ret);
302 300 return (EIO);
303 301 }
304 302 }
305 303 i40e->i40e_mcast_promisc_count++;
306 304 return (0);
307 305 }
308 306
309 307 mc = &i40e->i40e_maddrs[i40e->i40e_resources.ifr_nmcastfilt_used];
310 308 bzero(&filt, sizeof (filt));
311 309 bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
312 310 filt.flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH |
313 311 I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
314 312
315 - if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1,
313 + if ((ret = i40e_aq_add_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt, 1,
316 314 NULL)) != I40E_SUCCESS) {
317 315 i40e_error(i40e, "failed to add mac address "
318 316 "%2x:%2x:%2x:%2x:%2x:%2x to multicast filter: %d",
319 317 multicast_address[0], multicast_address[1],
320 318 multicast_address[2], multicast_address[3],
321 319 multicast_address[4], multicast_address[5],
322 320 ret);
323 321 return (EIO);
324 322 }
325 323
326 324 bcopy(multicast_address, mc->ima_mac, ETHERADDRL);
327 325 i40e->i40e_resources.ifr_nmcastfilt_used++;
328 326 return (0);
329 327 }
330 328
331 329 /*
332 330 * See the big theory statement in i40e_main.c for multicast address management.
333 331 */
334 332 static int
335 333 i40e_multicast_remove(i40e_t *i40e, const uint8_t *multicast_address)
336 334 {
337 335 int i, ret;
338 336 struct i40e_hw *hw = &i40e->i40e_hw_space;
339 337
340 338 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
341 339
342 340 for (i = 0; i < i40e->i40e_resources.ifr_nmcastfilt_used; i++) {
343 341 struct i40e_aqc_remove_macvlan_element_data filt;
344 342 int last;
345 343
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
346 344 if (bcmp(multicast_address, i40e->i40e_maddrs[i].ima_mac,
347 345 ETHERADDRL) != 0) {
348 346 continue;
349 347 }
350 348
351 349 bzero(&filt, sizeof (filt));
352 350 bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
353 351 filt.flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH |
354 352 I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
355 353
356 - if (i40e_aq_remove_macvlan(hw, i40e->i40e_vsi_id,
357 - &filt, 1, NULL) != I40E_SUCCESS) {
354 + if (i40e_aq_remove_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt,
355 + 1, NULL) != I40E_SUCCESS) {
358 356 i40e_error(i40e, "failed to remove mac address "
359 357 "%2x:%2x:%2x:%2x:%2x:%2x from multicast "
360 358 "filter: %d",
361 359 multicast_address[0], multicast_address[1],
362 360 multicast_address[2], multicast_address[3],
363 361 multicast_address[4], multicast_address[5],
364 362 filt.error_code);
365 363 return (EIO);
366 364 }
367 365
368 366 last = i40e->i40e_resources.ifr_nmcastfilt_used - 1;
369 367 if (i != last) {
370 368 bcopy(&i40e->i40e_maddrs[last], &i40e->i40e_maddrs[i],
371 369 sizeof (i40e_maddr_t));
372 370 bzero(&i40e->i40e_maddrs[last], sizeof (i40e_maddr_t));
373 371 }
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
374 372
375 373 ASSERT(i40e->i40e_resources.ifr_nmcastfilt_used > 0);
376 374 i40e->i40e_resources.ifr_nmcastfilt_used--;
377 375 return (0);
378 376 }
379 377
380 378 if (i40e->i40e_mcast_promisc_count > 0) {
381 379 if (i40e->i40e_mcast_promisc_count == 1 &&
382 380 i40e->i40e_promisc_on == B_FALSE) {
383 381 ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
384 - i40e->i40e_vsi_id, B_FALSE, NULL);
382 + I40E_DEF_VSI_SEID(i40e), B_FALSE, NULL);
385 383 if (ret != I40E_SUCCESS) {
386 384 i40e_error(i40e, "failed to disable "
387 385 "multicast promiscuous mode on VSI %d: %d",
388 - i40e->i40e_vsi_id, ret);
386 + I40E_DEF_VSI_SEID(i40e), ret);
389 387 return (EIO);
390 388 }
391 389 }
392 390 i40e->i40e_mcast_promisc_count--;
393 391
394 392 return (0);
395 393 }
396 394
397 395 return (ENOENT);
398 396 }
399 397
400 398 static int
401 399 i40e_m_multicast(void *arg, boolean_t add, const uint8_t *multicast_address)
402 400 {
403 401 i40e_t *i40e = arg;
404 402 int rc;
405 403
406 404 mutex_enter(&i40e->i40e_general_lock);
407 405
408 406 if (i40e->i40e_state & I40E_SUSPENDED) {
409 407 mutex_exit(&i40e->i40e_general_lock);
410 408 return (ECANCELED);
411 409 }
412 410
413 411 if (add == B_TRUE) {
414 412 rc = i40e_multicast_add(i40e, multicast_address);
415 413 } else {
416 414 rc = i40e_multicast_remove(i40e, multicast_address);
417 415 }
418 416
419 417 mutex_exit(&i40e->i40e_general_lock);
420 418 return (rc);
421 419 }
422 420
423 421 /* ARGSUSED */
424 422 static void
425 423 i40e_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
426 424 {
427 425 /*
428 426 * At this time, we don't support toggling i40e into loopback mode. It's
429 427 * questionable how much value this has when there's no clear way to
430 428 * toggle this behavior from a supported way in userland.
431 429 */
432 430 miocnak(q, mp, 0, EINVAL);
433 431 }
434 432
435 433 static int
436 434 i40e_ring_start(mac_ring_driver_t rh, uint64_t gen_num)
437 435 {
438 436 i40e_trqpair_t *itrq = (i40e_trqpair_t *)rh;
439 437
440 438 /*
441 439 * GLDv3 requires we keep track of a generation number, as it uses
442 440 * that number to keep track of whether or not a ring is active.
443 441 */
444 442 mutex_enter(&itrq->itrq_rx_lock);
445 443 itrq->itrq_rxgen = gen_num;
446 444 mutex_exit(&itrq->itrq_rx_lock);
447 445 return (0);
448 446 }
449 447
450 448 /* ARGSUSED */
451 449 static int
452 450 i40e_rx_ring_intr_enable(mac_intr_handle_t intrh)
453 451 {
454 452 i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
455 453
456 454 mutex_enter(&itrq->itrq_rx_lock);
457 455 ASSERT(itrq->itrq_intr_poll == B_TRUE);
458 456 i40e_intr_rx_queue_enable(itrq);
459 457 itrq->itrq_intr_poll = B_FALSE;
460 458 mutex_exit(&itrq->itrq_rx_lock);
461 459
462 460 return (0);
463 461 }
464 462
465 463 /* ARGSUSED */
466 464 static int
467 465 i40e_rx_ring_intr_disable(mac_intr_handle_t intrh)
468 466 {
469 467 i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
470 468
471 469 mutex_enter(&itrq->itrq_rx_lock);
472 470 i40e_intr_rx_queue_disable(itrq);
473 471 itrq->itrq_intr_poll = B_TRUE;
474 472 mutex_exit(&itrq->itrq_rx_lock);
475 473
476 474 return (0);
477 475 }
478 476
479 477 /* ARGSUSED */
480 478 static void
481 479 i40e_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
482 480 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
|
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
483 481 {
484 482 i40e_t *i40e = arg;
485 483 mac_intr_t *mintr = &infop->mri_intr;
486 484 i40e_trqpair_t *itrq = &(i40e->i40e_trqpairs[ring_index]);
487 485
488 486 /*
489 487 * Note the group index here is expected to be -1 due to the fact that
490 488 * we're not actually grouping things tx-wise at this time.
491 489 */
492 490 ASSERT(group_index == -1);
493 - ASSERT(ring_index < i40e->i40e_num_trqpairs);
491 + ASSERT(ring_index < i40e->i40e_num_trqpairs_per_vsi);
494 492
495 493 itrq->itrq_mactxring = rh;
496 494 infop->mri_driver = (mac_ring_driver_t)itrq;
497 495 infop->mri_start = NULL;
498 496 infop->mri_stop = NULL;
499 497 infop->mri_tx = i40e_ring_tx;
500 498 infop->mri_stat = i40e_tx_ring_stat;
501 499
502 500 /*
503 501 * We only provide the handle in cases where we have MSI-X interrupts,
504 502 * to indicate that we'd actually support retargetting.
505 503 */
506 504 if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
507 505 mintr->mi_ddi_handle =
508 506 i40e->i40e_intr_handles[itrq->itrq_tx_intrvec];
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
509 507 }
510 508 }
511 509
512 510 /* ARGSUSED */
513 511 static void
514 512 i40e_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
515 513 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
516 514 {
517 515 i40e_t *i40e = arg;
518 516 mac_intr_t *mintr = &infop->mri_intr;
519 - i40e_trqpair_t *itrq = &i40e->i40e_trqpairs[ring_index];
517 + uint_t trqpair_index;
518 + i40e_trqpair_t *itrq;
520 519
521 - /*
522 - * We assert the group number and ring index to help sanity check
523 - * ourselves and mark that we'll need to rework this when we have
524 - * multiple groups.
525 - */
526 - ASSERT3S(group_index, ==, 0);
527 - ASSERT3S(ring_index, <, i40e->i40e_num_trqpairs);
520 + /* This assumes static groups. */
521 + ASSERT3S(group_index, >=, 0);
522 + ASSERT3S(ring_index, >=, 0);
523 + trqpair_index = (group_index * i40e->i40e_num_trqpairs_per_vsi) +
524 + ring_index;
525 + ASSERT3U(trqpair_index, <, i40e->i40e_num_trqpairs);
526 + itrq = &i40e->i40e_trqpairs[trqpair_index];
528 527
529 528 itrq->itrq_macrxring = rh;
530 529 infop->mri_driver = (mac_ring_driver_t)itrq;
531 530 infop->mri_start = i40e_ring_start;
532 531 infop->mri_stop = NULL;
533 532 infop->mri_poll = i40e_ring_rx_poll;
534 533 infop->mri_stat = i40e_rx_ring_stat;
535 534 mintr->mi_handle = (mac_intr_handle_t)itrq;
536 535 mintr->mi_enable = i40e_rx_ring_intr_enable;
537 536 mintr->mi_disable = i40e_rx_ring_intr_disable;
538 537
539 538 /*
540 539 * We only provide the handle in cases where we have MSI-X interrupts,
541 540 * to indicate that we'd actually support retargetting.
542 541 */
543 542 if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
544 543 mintr->mi_ddi_handle =
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
545 544 i40e->i40e_intr_handles[itrq->itrq_rx_intrvec];
546 545 }
547 546 }
548 547
549 548 /* ARGSUSED */
550 549 static void
551 550 i40e_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index,
552 551 mac_group_info_t *infop, mac_group_handle_t gh)
553 552 {
554 553 i40e_t *i40e = arg;
554 + i40e_rx_group_t *rxg;
555 555
556 556 if (rtype != MAC_RING_TYPE_RX)
557 557 return;
558 558
559 - /*
560 - * Note, this is a simplified view of a group, given that we only have a
561 - * single group and a single ring at the moment. We'll want to expand
562 - * upon this as we leverage more hardware functionality.
563 - */
564 - i40e->i40e_rx_group_handle = gh;
565 - infop->mgi_driver = (mac_group_driver_t)i40e;
559 + rxg = &i40e->i40e_rx_groups[index];
560 + rxg->irg_grp_hdl = gh;
561 +
562 + infop->mgi_driver = (mac_group_driver_t)rxg;
566 563 infop->mgi_start = NULL;
567 564 infop->mgi_stop = NULL;
568 565 infop->mgi_addmac = i40e_group_add_mac;
569 566 infop->mgi_remmac = i40e_group_remove_mac;
570 567
571 - ASSERT(i40e->i40e_num_rx_groups == I40E_GROUP_MAX);
572 - infop->mgi_count = i40e->i40e_num_trqpairs;
568 + ASSERT(i40e->i40e_num_rx_groups <= I40E_GROUP_MAX);
569 + infop->mgi_count = i40e->i40e_num_trqpairs_per_vsi;
573 570 }
574 571
575 572 static int
576 573 i40e_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
577 574 {
578 575 boolean_t present, usable;
579 576 i40e_t *i40e = arg;
580 577
581 578 if (id != 0 || infop == NULL)
582 579 return (EINVAL);
583 580
584 581 mutex_enter(&i40e->i40e_general_lock);
582 + switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
583 + case I40E_MODULE_TYPE_SFP:
584 + case I40E_MODULE_TYPE_QSFP:
585 + break;
586 + default:
587 + mutex_exit(&i40e->i40e_general_lock);
588 + return (ENOTSUP);
589 + }
590 +
585 591 present = !!(i40e->i40e_hw_space.phy.link_info.link_info &
586 592 I40E_AQ_MEDIA_AVAILABLE);
587 593 if (present) {
588 594 usable = !!(i40e->i40e_hw_space.phy.link_info.an_info &
589 595 I40E_AQ_QUALIFIED_MODULE);
590 596 } else {
591 597 usable = B_FALSE;
592 598 }
593 599 mutex_exit(&i40e->i40e_general_lock);
594 600
595 601 mac_transceiver_info_set_usable(infop, usable);
596 602 mac_transceiver_info_set_present(infop, present);
597 603
598 604 return (0);
599 605 }
600 606
601 607 static int
608 +i40e_transceiver_read(void *arg, uint_t id, uint_t page, void *buf,
609 + size_t nbytes, off_t offset, size_t *nread)
610 +{
611 + i40e_t *i40e = arg;
612 + struct i40e_hw *hw = &i40e->i40e_hw_space;
613 + uint8_t *buf8 = buf;
614 + size_t i;
615 +
616 + if (id != 0 || buf == NULL || nbytes == 0 || nread == NULL ||
617 + (page != 0xa0 && page != 0xa2) || offset < 0)
618 + return (EINVAL);
619 +
620 + /*
621 + * Both supported pages have a length of 256 bytes, ensure nothing asks
622 + * us to go beyond that.
623 + */
624 + if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
625 + return (EINVAL);
626 + }
627 +
628 + mutex_enter(&i40e->i40e_general_lock);
629 + switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
630 + case I40E_MODULE_TYPE_SFP:
631 + case I40E_MODULE_TYPE_QSFP:
632 + break;
633 + default:
634 + mutex_exit(&i40e->i40e_general_lock);
635 + return (ENOTSUP);
636 + }
637 +
638 + /*
639 + * Make sure we have a sufficiently new firmware version to run this
640 + * command. This was introduced in firmware API 1.7. This is apparently
641 + * only supported on the XL710 MAC, not the XL722.
642 + */
643 + if (hw->mac.type != I40E_MAC_XL710 || hw->aq.api_maj_ver != 1 ||
644 + hw->aq.api_min_ver < 7) {
645 + mutex_exit(&i40e->i40e_general_lock);
646 + return (ENOTSUP);
647 + }
648 +
649 + for (i = 0; i < nbytes; i++, offset++) {
650 + enum i40e_status_code status;
651 + uint32_t val;
652 +
653 + status = i40e_aq_get_phy_register(hw,
654 + I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, page, offset,
655 + &val, NULL);
656 + if (status != I40E_SUCCESS) {
657 + mutex_exit(&i40e->i40e_general_lock);
658 + return (EIO);
659 + }
660 +
661 + buf8[i] = (uint8_t)val;
662 + }
663 +
664 + mutex_exit(&i40e->i40e_general_lock);
665 + *nread = nbytes;
666 +
667 + return (0);
668 +}
669 +
670 +static int
602 671 i40e_gld_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
603 672 {
604 673 i40e_t *i40e = arg;
605 674 struct i40e_hw *hw = &i40e->i40e_hw_space;
606 675
607 676 if (flags != 0)
608 677 return (EINVAL);
609 678
610 679 if (mode != MAC_LED_DEFAULT &&
611 680 mode != MAC_LED_IDENT &&
612 681 mode != MAC_LED_OFF &&
613 682 mode != MAC_LED_ON)
614 683 return (ENOTSUP);
615 684
616 685 if (mode != MAC_LED_DEFAULT && !i40e->i40e_led_saved) {
617 686 i40e->i40e_led_status = i40e_led_get(hw);
618 687 i40e->i40e_led_saved = B_TRUE;
619 688 }
620 689
621 690 switch (mode) {
622 691 case MAC_LED_DEFAULT:
623 692 if (i40e->i40e_led_saved) {
624 693 i40e_led_set(hw, i40e->i40e_led_status, B_FALSE);
625 694 i40e->i40e_led_status = 0;
626 695 i40e->i40e_led_saved = B_FALSE;
627 696 }
628 697 break;
629 698 case MAC_LED_IDENT:
630 699 i40e_led_set(hw, 0xf, B_TRUE);
631 700 break;
632 701 case MAC_LED_OFF:
633 702 i40e_led_set(hw, 0x0, B_FALSE);
634 703 break;
635 704 case MAC_LED_ON:
636 705 i40e_led_set(hw, 0xf, B_FALSE);
637 706 break;
638 707 default:
639 708 return (ENOTSUP);
640 709 }
641 710
642 711 return (0);
643 712 }
644 713
645 714 static boolean_t
646 715 i40e_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
647 716 {
648 717 i40e_t *i40e = arg;
649 718 mac_capab_rings_t *cap_rings;
650 719 mac_capab_transceiver_t *mct;
651 720 mac_capab_led_t *mcl;
652 721
|
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
653 722 switch (cap) {
654 723 case MAC_CAPAB_HCKSUM: {
655 724 uint32_t *txflags = cap_data;
656 725
657 726 *txflags = 0;
658 727 if (i40e->i40e_tx_hcksum_enable == B_TRUE)
659 728 *txflags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
660 729 break;
661 730 }
662 731
732 + case MAC_CAPAB_LSO: {
733 + mac_capab_lso_t *cap_lso = cap_data;
734 +
735 + if (i40e->i40e_tx_lso_enable == B_TRUE) {
736 + cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
737 + cap_lso->lso_basic_tcp_ipv4.lso_max = I40E_LSO_MAXLEN;
738 + } else {
739 + return (B_FALSE);
740 + }
741 + break;
742 + }
743 +
663 744 case MAC_CAPAB_RINGS:
664 745 cap_rings = cap_data;
665 746 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
666 747 switch (cap_rings->mr_type) {
667 748 case MAC_RING_TYPE_TX:
668 749 /*
669 - * Note, saying we have no rings, but some number of
670 - * groups indicates to MAC that it should create
671 - * psuedo-groups with one for each TX ring. This may not
672 - * be the long term behavior we want, but it'll work for
673 - * now.
750 + * Note, saying we have no groups, but some
751 + * number of rings indicates to MAC that it
752 + * should create psuedo-groups with one for
753 + * each TX ring. This may not be the long term
754 + * behavior we want, but it'll work for now.
674 755 */
675 756 cap_rings->mr_gnum = 0;
676 - cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
757 + cap_rings->mr_rnum = i40e->i40e_num_trqpairs_per_vsi;
677 758 cap_rings->mr_rget = i40e_fill_tx_ring;
678 759 cap_rings->mr_gget = NULL;
679 760 cap_rings->mr_gaddring = NULL;
680 761 cap_rings->mr_gremring = NULL;
681 762 break;
682 763 case MAC_RING_TYPE_RX:
683 764 cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
684 765 cap_rings->mr_rget = i40e_fill_rx_ring;
685 - cap_rings->mr_gnum = I40E_GROUP_MAX;
766 + cap_rings->mr_gnum = i40e->i40e_num_rx_groups;
686 767 cap_rings->mr_gget = i40e_fill_rx_group;
687 768 cap_rings->mr_gaddring = NULL;
688 769 cap_rings->mr_gremring = NULL;
689 770 break;
690 771 default:
691 772 return (B_FALSE);
692 773 }
693 774 break;
694 775 case MAC_CAPAB_TRANSCEIVER:
695 776 mct = cap_data;
696 777
697 778 /*
698 779 * Firmware doesn't have a great way of telling us in advance
699 780 * whether we'd expect a SFF transceiver. As such, we always
700 781 * advertise the support for this capability.
701 782 */
702 783 mct->mct_flags = 0;
703 784 mct->mct_ntransceivers = 1;
704 785 mct->mct_info = i40e_transceiver_info;
705 - mct->mct_read = NULL;
786 + mct->mct_read = i40e_transceiver_read;
706 787
707 788 return (B_TRUE);
708 789 case MAC_CAPAB_LED:
709 790 mcl = cap_data;
710 791
711 792 mcl->mcl_flags = 0;
712 793 mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT | MAC_LED_OFF |
713 794 MAC_LED_ON;
714 795 mcl->mcl_set = i40e_gld_led_set;
715 796 break;
716 797
717 798 default:
718 799 return (B_FALSE);
719 800 }
720 801
721 802 return (B_TRUE);
722 803 }
723 804
724 805 /* ARGSUSED */
725 806 static int
726 807 i40e_m_setprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
727 808 const void *pr_val)
728 809 {
729 810 int ret;
730 811 long val;
731 812 char *eptr;
732 813
733 814 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
734 815
735 816 if ((ret = ddi_strtol(pr_val, &eptr, 10, &val)) != 0 ||
736 817 *eptr != '\0') {
737 818 return (ret);
738 819 }
739 820
740 821 if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
741 822 if (val < I40E_MIN_RX_DMA_THRESH ||
742 823 val > I40E_MAX_RX_DMA_THRESH) {
743 824 return (EINVAL);
744 825 }
745 826 i40e->i40e_rx_dma_min = (uint32_t)val;
746 827 return (0);
747 828 }
748 829
749 830 if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
750 831 if (val < I40E_MIN_TX_DMA_THRESH ||
751 832 val > I40E_MAX_TX_DMA_THRESH) {
752 833 return (EINVAL);
753 834 }
754 835 i40e->i40e_tx_dma_min = (uint32_t)val;
755 836 return (0);
756 837 }
757 838
758 839 if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
759 840 if (val < I40E_MIN_ITR ||
760 841 val > I40E_MAX_ITR) {
761 842 return (EINVAL);
762 843 }
763 844 i40e->i40e_rx_itr = (uint32_t)val;
764 845 i40e_intr_set_itr(i40e, I40E_ITR_INDEX_RX, i40e->i40e_rx_itr);
765 846 return (0);
766 847 }
767 848
768 849 if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
769 850 if (val < I40E_MIN_ITR ||
770 851 val > I40E_MAX_ITR) {
771 852 return (EINVAL);
772 853 }
773 854 i40e->i40e_tx_itr = (uint32_t)val;
774 855 i40e_intr_set_itr(i40e, I40E_ITR_INDEX_TX, i40e->i40e_tx_itr);
775 856 return (0);
776 857 }
777 858
778 859 if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
779 860 if (val < I40E_MIN_ITR ||
780 861 val > I40E_MAX_ITR) {
781 862 return (EINVAL);
782 863 }
783 864 i40e->i40e_tx_itr = (uint32_t)val;
784 865 i40e_intr_set_itr(i40e, I40E_ITR_INDEX_OTHER,
785 866 i40e->i40e_other_itr);
786 867 return (0);
787 868 }
788 869
789 870 return (ENOTSUP);
790 871 }
791 872
792 873 static int
793 874 i40e_m_getprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
794 875 void *pr_val)
795 876 {
796 877 uint32_t val;
797 878
798 879 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
799 880
800 881 if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
801 882 val = i40e->i40e_rx_dma_min;
802 883 } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
803 884 val = i40e->i40e_tx_dma_min;
804 885 } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
805 886 val = i40e->i40e_rx_itr;
806 887 } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
807 888 val = i40e->i40e_tx_itr;
808 889 } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
809 890 val = i40e->i40e_other_itr;
810 891 } else {
811 892 return (ENOTSUP);
812 893 }
813 894
814 895 if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize)
815 896 return (ERANGE);
816 897 return (0);
817 898 }
818 899
819 900 /*
820 901 * Annoyingly for private properties MAC seems to ignore default values that
821 902 * aren't strings. That means that we have to translate all of these into
822 903 * uint32_t's and instead we size the buffer to be large enough to hold a
823 904 * uint32_t.
824 905 */
825 906 /* ARGSUSED */
826 907 static void
827 908 i40e_m_propinfo_private(i40e_t *i40e, const char *pr_name,
828 909 mac_prop_info_handle_t prh)
829 910 {
830 911 char buf[64];
831 912 uint32_t def;
832 913
833 914 if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
834 915 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
835 916 def = I40E_DEF_RX_DMA_THRESH;
836 917 mac_prop_info_set_range_uint32(prh,
837 918 I40E_MIN_RX_DMA_THRESH,
838 919 I40E_MAX_RX_DMA_THRESH);
839 920 } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
840 921 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
841 922 def = I40E_DEF_TX_DMA_THRESH;
842 923 mac_prop_info_set_range_uint32(prh,
843 924 I40E_MIN_TX_DMA_THRESH,
844 925 I40E_MAX_TX_DMA_THRESH);
845 926 } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
846 927 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
847 928 def = I40E_DEF_RX_ITR;
848 929 mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
849 930 } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
850 931 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
851 932 def = I40E_DEF_TX_ITR;
852 933 mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
853 934 } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
854 935 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
855 936 def = I40E_DEF_OTHER_ITR;
856 937 mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
857 938 } else {
858 939 return;
859 940 }
860 941
861 942 (void) snprintf(buf, sizeof (buf), "%d", def);
862 943 mac_prop_info_set_default_str(prh, buf);
863 944 }
864 945
865 946 static int
866 947 i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
867 948 uint_t pr_valsize, const void *pr_val)
868 949 {
869 950 uint32_t new_mtu;
870 951 i40e_t *i40e = arg;
871 952 int ret = 0;
872 953
873 954 mutex_enter(&i40e->i40e_general_lock);
874 955 if (i40e->i40e_state & I40E_SUSPENDED) {
875 956 mutex_exit(&i40e->i40e_general_lock);
876 957 return (ECANCELED);
877 958 }
878 959
879 960 switch (pr_num) {
880 961 /*
881 962 * These properties are always read-only across every device.
882 963 */
883 964 case MAC_PROP_DUPLEX:
884 965 case MAC_PROP_SPEED:
885 966 case MAC_PROP_STATUS:
886 967 case MAC_PROP_ADV_100FDX_CAP:
887 968 case MAC_PROP_ADV_1000FDX_CAP:
888 969 case MAC_PROP_ADV_10GFDX_CAP:
889 970 case MAC_PROP_ADV_25GFDX_CAP:
890 971 case MAC_PROP_ADV_40GFDX_CAP:
891 972 ret = ENOTSUP;
892 973 break;
893 974 /*
894 975 * These are read-only at this time as we don't support configuring
895 976 * auto-negotiation. See the theory statement in i40e_main.c.
896 977 */
897 978 case MAC_PROP_EN_100FDX_CAP:
898 979 case MAC_PROP_EN_1000FDX_CAP:
899 980 case MAC_PROP_EN_10GFDX_CAP:
900 981 case MAC_PROP_EN_25GFDX_CAP:
901 982 case MAC_PROP_EN_40GFDX_CAP:
902 983 case MAC_PROP_AUTONEG:
903 984 case MAC_PROP_FLOWCTRL:
904 985 ret = ENOTSUP;
905 986 break;
906 987
907 988 case MAC_PROP_MTU:
908 989 bcopy(pr_val, &new_mtu, sizeof (new_mtu));
909 990 if (new_mtu == i40e->i40e_sdu)
910 991 break;
911 992
912 993 if (new_mtu < I40E_MIN_MTU ||
913 994 new_mtu > I40E_MAX_MTU) {
914 995 ret = EINVAL;
915 996 break;
916 997 }
917 998
918 999 if (i40e->i40e_state & I40E_STARTED) {
919 1000 ret = EBUSY;
920 1001 break;
921 1002 }
922 1003
923 1004 ret = mac_maxsdu_update(i40e->i40e_mac_hdl, new_mtu);
924 1005 if (ret == 0) {
925 1006 i40e->i40e_sdu = new_mtu;
926 1007 i40e_update_mtu(i40e);
927 1008 }
928 1009 break;
929 1010
930 1011 case MAC_PROP_PRIVATE:
931 1012 ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val);
932 1013 break;
933 1014 default:
934 1015 ret = ENOTSUP;
935 1016 break;
936 1017 }
937 1018
938 1019 mutex_exit(&i40e->i40e_general_lock);
939 1020 return (ret);
940 1021 }
941 1022
942 1023 static int
943 1024 i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
944 1025 uint_t pr_valsize, void *pr_val)
945 1026 {
946 1027 i40e_t *i40e = arg;
947 1028 uint64_t speed;
948 1029 int ret = 0;
949 1030 uint8_t *u8;
950 1031 link_flowctrl_t fctl;
951 1032
952 1033 mutex_enter(&i40e->i40e_general_lock);
953 1034
954 1035 switch (pr_num) {
955 1036 case MAC_PROP_DUPLEX:
956 1037 if (pr_valsize < sizeof (link_duplex_t)) {
957 1038 ret = EOVERFLOW;
958 1039 break;
959 1040 }
960 1041 bcopy(&i40e->i40e_link_duplex, pr_val, sizeof (link_duplex_t));
961 1042 break;
962 1043 case MAC_PROP_SPEED:
963 1044 if (pr_valsize < sizeof (uint64_t)) {
964 1045 ret = EOVERFLOW;
965 1046 break;
966 1047 }
967 1048 speed = i40e->i40e_link_speed * 1000000ULL;
968 1049 bcopy(&speed, pr_val, sizeof (speed));
969 1050 break;
970 1051 case MAC_PROP_STATUS:
971 1052 if (pr_valsize < sizeof (link_state_t)) {
972 1053 ret = EOVERFLOW;
973 1054 break;
974 1055 }
975 1056 bcopy(&i40e->i40e_link_state, pr_val, sizeof (link_state_t));
976 1057 break;
977 1058 case MAC_PROP_AUTONEG:
978 1059 if (pr_valsize < sizeof (uint8_t)) {
979 1060 ret = EOVERFLOW;
980 1061 break;
981 1062 }
982 1063 u8 = pr_val;
983 1064 *u8 = 1;
984 1065 break;
985 1066 case MAC_PROP_FLOWCTRL:
986 1067 /*
987 1068 * Because we don't currently support hardware flow control, we
988 1069 * just hardcode this to be none.
989 1070 */
990 1071 if (pr_valsize < sizeof (link_flowctrl_t)) {
991 1072 ret = EOVERFLOW;
992 1073 break;
993 1074 }
994 1075 fctl = LINK_FLOWCTRL_NONE;
995 1076 bcopy(&fctl, pr_val, sizeof (link_flowctrl_t));
996 1077 break;
997 1078 case MAC_PROP_MTU:
998 1079 if (pr_valsize < sizeof (uint32_t)) {
999 1080 ret = EOVERFLOW;
1000 1081 break;
1001 1082 }
1002 1083 bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t));
1003 1084 break;
1004 1085
1005 1086 /*
1006 1087 * Because we don't let users control the speeds we may auto-negotiate
1007 1088 * to, the values of the ADV_ and EN_ will always be the same.
1008 1089 */
1009 1090 case MAC_PROP_ADV_100FDX_CAP:
1010 1091 case MAC_PROP_EN_100FDX_CAP:
1011 1092 if (pr_valsize < sizeof (uint8_t)) {
1012 1093 ret = EOVERFLOW;
1013 1094 break;
1014 1095 }
1015 1096 u8 = pr_val;
1016 1097 *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0;
1017 1098 break;
1018 1099 case MAC_PROP_ADV_1000FDX_CAP:
1019 1100 case MAC_PROP_EN_1000FDX_CAP:
1020 1101 if (pr_valsize < sizeof (uint8_t)) {
1021 1102 ret = EOVERFLOW;
1022 1103 break;
1023 1104 }
1024 1105 u8 = pr_val;
1025 1106 *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0;
1026 1107 break;
1027 1108 case MAC_PROP_ADV_10GFDX_CAP:
1028 1109 case MAC_PROP_EN_10GFDX_CAP:
1029 1110 if (pr_valsize < sizeof (uint8_t)) {
1030 1111 ret = EOVERFLOW;
1031 1112 break;
1032 1113 }
1033 1114 u8 = pr_val;
1034 1115 *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0;
1035 1116 break;
1036 1117 case MAC_PROP_ADV_25GFDX_CAP:
1037 1118 case MAC_PROP_EN_25GFDX_CAP:
1038 1119 if (pr_valsize < sizeof (uint8_t)) {
1039 1120 ret = EOVERFLOW;
1040 1121 break;
1041 1122 }
1042 1123 u8 = pr_val;
1043 1124 *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0;
1044 1125 break;
1045 1126 case MAC_PROP_ADV_40GFDX_CAP:
1046 1127 case MAC_PROP_EN_40GFDX_CAP:
1047 1128 if (pr_valsize < sizeof (uint8_t)) {
1048 1129 ret = EOVERFLOW;
1049 1130 break;
1050 1131 }
1051 1132 u8 = pr_val;
1052 1133 *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0;
1053 1134 break;
1054 1135 case MAC_PROP_PRIVATE:
1055 1136 ret = i40e_m_getprop_private(i40e, pr_name, pr_valsize, pr_val);
1056 1137 break;
1057 1138 default:
1058 1139 ret = ENOTSUP;
1059 1140 break;
1060 1141 }
1061 1142
1062 1143 mutex_exit(&i40e->i40e_general_lock);
1063 1144
1064 1145 return (ret);
1065 1146 }
1066 1147
1067 1148 static void
1068 1149 i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1069 1150 mac_prop_info_handle_t prh)
1070 1151 {
1071 1152 i40e_t *i40e = arg;
1072 1153
1073 1154 mutex_enter(&i40e->i40e_general_lock);
1074 1155
1075 1156 switch (pr_num) {
1076 1157 case MAC_PROP_DUPLEX:
1077 1158 case MAC_PROP_SPEED:
1078 1159 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1079 1160 break;
1080 1161 case MAC_PROP_FLOWCTRL:
1081 1162 /*
1082 1163 * At the moment, the driver doesn't support flow control, hence
1083 1164 * why this is set to read-only and none.
1084 1165 */
1085 1166 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1086 1167 mac_prop_info_set_default_link_flowctrl(prh,
1087 1168 LINK_FLOWCTRL_NONE);
1088 1169 break;
1089 1170 case MAC_PROP_MTU:
1090 1171 mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU);
1091 1172 break;
1092 1173
1093 1174 /*
1094 1175 * We set the defaults for these based upon the phy's ability to
1095 1176 * support the speeds. Note, auto-negotiation is required for fiber,
1096 1177 * hence it is read-only and always enabled. When we have access to
1097 1178 * copper phys we can revisit this.
1098 1179 */
1099 1180 case MAC_PROP_AUTONEG:
1100 1181 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1101 1182 mac_prop_info_set_default_uint8(prh, 1);
1102 1183 break;
1103 1184 case MAC_PROP_ADV_100FDX_CAP:
1104 1185 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1105 1186 mac_prop_info_set_default_uint8(prh,
1106 1187 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
1107 1188 break;
1108 1189 case MAC_PROP_EN_100FDX_CAP:
1109 1190 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1110 1191 mac_prop_info_set_default_uint8(prh,
1111 1192 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
1112 1193 break;
1113 1194 case MAC_PROP_ADV_1000FDX_CAP:
1114 1195 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1115 1196 mac_prop_info_set_default_uint8(prh,
1116 1197 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
1117 1198 break;
1118 1199 case MAC_PROP_EN_1000FDX_CAP:
1119 1200 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1120 1201 mac_prop_info_set_default_uint8(prh,
1121 1202 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
1122 1203 break;
1123 1204 case MAC_PROP_ADV_10GFDX_CAP:
1124 1205 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1125 1206 mac_prop_info_set_default_uint8(prh,
1126 1207 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
1127 1208 break;
1128 1209 case MAC_PROP_EN_10GFDX_CAP:
1129 1210 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1130 1211 mac_prop_info_set_default_uint8(prh,
1131 1212 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
1132 1213 break;
1133 1214 case MAC_PROP_ADV_25GFDX_CAP:
1134 1215 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1135 1216 mac_prop_info_set_default_uint8(prh,
1136 1217 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
1137 1218 break;
1138 1219 case MAC_PROP_EN_25GFDX_CAP:
1139 1220 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1140 1221 mac_prop_info_set_default_uint8(prh,
1141 1222 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
1142 1223 break;
1143 1224 case MAC_PROP_ADV_40GFDX_CAP:
1144 1225 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1145 1226 mac_prop_info_set_default_uint8(prh,
1146 1227 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
1147 1228 break;
1148 1229 case MAC_PROP_EN_40GFDX_CAP:
1149 1230 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1150 1231 mac_prop_info_set_default_uint8(prh,
1151 1232 (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
1152 1233 break;
1153 1234 case MAC_PROP_PRIVATE:
1154 1235 i40e_m_propinfo_private(i40e, pr_name, prh);
1155 1236 break;
1156 1237 default:
1157 1238 break;
1158 1239 }
1159 1240
1160 1241 mutex_exit(&i40e->i40e_general_lock);
1161 1242 }
1162 1243
1163 1244 #define I40E_M_CALLBACK_FLAGS \
1164 1245 (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
1165 1246
1166 1247 static mac_callbacks_t i40e_m_callbacks = {
1167 1248 I40E_M_CALLBACK_FLAGS,
1168 1249 i40e_m_stat,
1169 1250 i40e_m_start,
1170 1251 i40e_m_stop,
1171 1252 i40e_m_promisc,
1172 1253 i40e_m_multicast,
1173 1254 NULL,
1174 1255 NULL,
1175 1256 NULL,
1176 1257 i40e_m_ioctl,
1177 1258 i40e_m_getcapab,
1178 1259 NULL,
1179 1260 NULL,
1180 1261 i40e_m_setprop,
1181 1262 i40e_m_getprop,
1182 1263 i40e_m_propinfo
1183 1264 };
1184 1265
1185 1266 boolean_t
1186 1267 i40e_register_mac(i40e_t *i40e)
1187 1268 {
1188 1269 struct i40e_hw *hw = &i40e->i40e_hw_space;
1189 1270 int status;
1190 1271 mac_register_t *mac = mac_alloc(MAC_VERSION);
1191 1272
1192 1273 if (mac == NULL)
1193 1274 return (B_FALSE);
1194 1275
1195 1276 mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1196 1277 mac->m_driver = i40e;
1197 1278 mac->m_dip = i40e->i40e_dip;
1198 1279 mac->m_src_addr = hw->mac.addr;
1199 1280 mac->m_callbacks = &i40e_m_callbacks;
1200 1281 mac->m_min_sdu = 0;
1201 1282 mac->m_max_sdu = i40e->i40e_sdu;
1202 1283 mac->m_margin = VLAN_TAGSZ;
1203 1284 mac->m_priv_props = i40e_priv_props;
1204 1285 mac->m_v12n = MAC_VIRT_LEVEL1;
1205 1286
1206 1287 status = mac_register(mac, &i40e->i40e_mac_hdl);
1207 1288 if (status != 0)
1208 1289 i40e_error(i40e, "mac_register() returned %d", status);
1209 1290 mac_free(mac);
1210 1291
1211 1292 return (status == 0);
1212 1293 }
|
↓ open down ↓ |
497 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX