Pull up following revision(s) (requested by msaitoh in ticket #133): sys/dev/pci/ixgbe/ixgbe.c: revision 1.200 sys/dev/pci/ixgbe/ixgbe.c: revision 1.201 sys/dev/pci/ixgbe/ixv.c: revision 1.126 sys/dev/pci/ixgbe/ixv.c: revision 1.127 sys/net/if_vlan.c: revision 1.142 sys/net/if_vlan.c: revision 1.143 sys/net/if_vlan.c: revision 1.144 sys/net/if_vlan.c: revision 1.145 sys/net/if_vlan.c: revision 1.146 Check ec_capenable instead of ec_capabilities to control TX side of VLAN HW tagging correctly. XXX pullup-9 Add missing IFNET_LOCK() and IFNET_UNLOCK() in vlan_config(). XXX pullup-9 Fix a bug that VLAN HW "tagging" enable/disable may not reflect correctly. - Always call ec_vlan_cb() if it exists. - Some (or all?) ethernet drivers don't enable HW tagging if no any vlan is attached. ixgbe is one of them. Check the the transition and update VLAN HW tagging function. XXX pullup-9 Use ETHER_LOCK()/ETHER_UNLOCK() suggested by knakahara. - kmem_alloc(,KM_SLEEP) never return NULL, so remove NULL check. - VLAN ID is never duplicated, so break the loop when found. Also move kmen_free() outside of ETHER_LOCK(ec)/ETHER_UNLOCK(ec) to reduce the hold time. suggested by ozaki-r. - Whitespace fix.diff -r1.199 -r1.199.2.1 src/sys/dev/pci/ixgbe/ixgbe.c
(martin)
--- src/sys/dev/pci/ixgbe/ixgbe.c 2019/07/30 08:44:28 1.199
+++ src/sys/dev/pci/ixgbe/ixgbe.c 2019/09/01 11:07:05 1.199.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ixgbe.c,v 1.199 2019/07/30 08:44:28 msaitoh Exp $ */ | 1 | /* $NetBSD: ixgbe.c,v 1.199.2.1 2019/09/01 11:07:05 martin Exp $ */ | |
2 | 2 | |||
3 | /****************************************************************************** | 3 | /****************************************************************************** | |
4 | 4 | |||
5 | Copyright (c) 2001-2017, Intel Corporation | 5 | Copyright (c) 2001-2017, Intel Corporation | |
6 | All rights reserved. | 6 | All rights reserved. | |
7 | 7 | |||
8 | Redistribution and use in source and binary forms, with or without | 8 | Redistribution and use in source and binary forms, with or without | |
9 | modification, are permitted provided that the following conditions are met: | 9 | modification, are permitted provided that the following conditions are met: | |
10 | 10 | |||
11 | 1. Redistributions of source code must retain the above copyright notice, | 11 | 1. Redistributions of source code must retain the above copyright notice, | |
12 | this list of conditions and the following disclaimer. | 12 | this list of conditions and the following disclaimer. | |
13 | 13 | |||
14 | 2. Redistributions in binary form must reproduce the above copyright | 14 | 2. Redistributions in binary form must reproduce the above copyright | |
@@ -209,26 +209,27 @@ static void ixgbe_disable_rx_drop(struct | @@ -209,26 +209,27 @@ static void ixgbe_disable_rx_drop(struct | |||
209 | static void ixgbe_initialize_rss_mapping(struct adapter *); | 209 | static void ixgbe_initialize_rss_mapping(struct adapter *); | |
210 | 210 | |||
211 | static void ixgbe_enable_intr(struct adapter *); | 211 | static void ixgbe_enable_intr(struct adapter *); | |
212 | static void ixgbe_disable_intr(struct adapter *); | 212 | static void ixgbe_disable_intr(struct adapter *); | |
213 | static void ixgbe_update_stats_counters(struct adapter *); | 213 | static void ixgbe_update_stats_counters(struct adapter *); | |
214 | static void ixgbe_set_promisc(struct adapter *); | 214 | static void ixgbe_set_promisc(struct adapter *); | |
215 | static void ixgbe_set_multi(struct adapter *); | 215 | static void ixgbe_set_multi(struct adapter *); | |
216 | static void ixgbe_update_link_status(struct adapter *); | 216 | static void ixgbe_update_link_status(struct adapter *); | |
217 | static void ixgbe_set_ivar(struct adapter *, u8, u8, s8); | 217 | static void ixgbe_set_ivar(struct adapter *, u8, u8, s8); | |
218 | static void ixgbe_configure_ivars(struct adapter *); | 218 | static void ixgbe_configure_ivars(struct adapter *); | |
219 | static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | 219 | static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | |
220 | static void ixgbe_eitr_write(struct adapter *, uint32_t, uint32_t); | 220 | static void ixgbe_eitr_write(struct adapter *, uint32_t, uint32_t); | |
221 | 221 | |||
222 | static void ixgbe_setup_vlan_hw_tagging(struct adapter *); | |||
222 | static void ixgbe_setup_vlan_hw_support(struct adapter *); | 223 | static void ixgbe_setup_vlan_hw_support(struct adapter *); | |
223 | static int ixgbe_vlan_cb(struct ethercom *, uint16_t, bool); | 224 | static int ixgbe_vlan_cb(struct ethercom *, uint16_t, bool); | |
224 | static int ixgbe_register_vlan(void *, struct ifnet *, u16); | 225 | static int ixgbe_register_vlan(void *, struct ifnet *, u16); | |
225 | static int ixgbe_unregister_vlan(void *, struct ifnet *, u16); | 226 | static int ixgbe_unregister_vlan(void *, struct ifnet *, u16); | |
226 | 227 | |||
227 | static void ixgbe_add_device_sysctls(struct adapter *); | 228 | static void ixgbe_add_device_sysctls(struct adapter *); | |
228 | static void ixgbe_add_hw_stats(struct adapter *); | 229 | static void ixgbe_add_hw_stats(struct adapter *); | |
229 | static void ixgbe_clear_evcnt(struct adapter *); | 230 | static void ixgbe_clear_evcnt(struct adapter *); | |
230 | static int ixgbe_set_flowcntl(struct adapter *, int); | 231 | static int ixgbe_set_flowcntl(struct adapter *, int); | |
231 | static int ixgbe_set_advertise(struct adapter *, int); | 232 | static int ixgbe_set_advertise(struct adapter *, int); | |
232 | static int ixgbe_get_advertise(struct adapter *); | 233 | static int ixgbe_get_advertise(struct adapter *); | |
233 | 234 | |||
234 | /* Sysctl handlers */ | 235 | /* Sysctl handlers */ | |
@@ -2295,33 +2296,44 @@ ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS) | @@ -2295,33 +2296,44 @@ ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS) | |||
2295 | adapter = rxr->adapter; | 2296 | adapter = rxr->adapter; | |
2296 | if (ixgbe_fw_recovery_mode_swflag(adapter)) | 2297 | if (ixgbe_fw_recovery_mode_swflag(adapter)) | |
2297 | return (EPERM); | 2298 | return (EPERM); | |
2298 | 2299 | |||
2299 | val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDT(rxr->me)); | 2300 | val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDT(rxr->me)); | |
2300 | node.sysctl_data = &val; | 2301 | node.sysctl_data = &val; | |
2301 | return sysctl_lookup(SYSCTLFN_CALL(&node)); | 2302 | return sysctl_lookup(SYSCTLFN_CALL(&node)); | |
2302 | } /* ixgbe_sysctl_rdt_handler */ | 2303 | } /* ixgbe_sysctl_rdt_handler */ | |
2303 | 2304 | |||
2304 | static int | 2305 | static int | |
2305 | ixgbe_vlan_cb(struct ethercom *ec, uint16_t vid, bool set) | 2306 | ixgbe_vlan_cb(struct ethercom *ec, uint16_t vid, bool set) | |
2306 | { | 2307 | { | |
2307 | struct ifnet *ifp = &ec->ec_if; | 2308 | struct ifnet *ifp = &ec->ec_if; | |
2309 | struct adapter *adapter = ifp->if_softc; | |||
2308 | int rv; | 2310 | int rv; | |
2309 | 2311 | |||
2310 | if (set) | 2312 | if (set) | |
2311 | rv = ixgbe_register_vlan(ifp->if_softc, ifp, vid); | 2313 | rv = ixgbe_register_vlan(ifp->if_softc, ifp, vid); | |
2312 | else | 2314 | else | |
2313 | rv = ixgbe_unregister_vlan(ifp->if_softc, ifp, vid); | 2315 | rv = ixgbe_unregister_vlan(ifp->if_softc, ifp, vid); | |
2314 | 2316 | |||
2317 | if (rv != 0) | |||
2318 | return rv; | |||
2319 | ||||
2320 | /* | |||
2321 | * Control VLAN HW tagging when ec_nvlan is changed from 1 to 0 | |||
2322 | * or 0 to 1. | |||
2323 | */ | |||
2324 | if ((set && (ec->ec_nvlans == 1)) || (!set && (ec->ec_nvlans == 0))) | |||
2325 | ixgbe_setup_vlan_hw_tagging(adapter); | |||
2326 | ||||
2315 | return rv; | 2327 | return rv; | |
2316 | } | 2328 | } | |
2317 | 2329 | |||
2318 | /************************************************************************ | 2330 | /************************************************************************ | |
2319 | * ixgbe_register_vlan | 2331 | * ixgbe_register_vlan | |
2320 | * | 2332 | * | |
2321 | * Run via vlan config EVENT, it enables us to use the | 2333 | * Run via vlan config EVENT, it enables us to use the | |
2322 | * HW Filter table since we can get the vlan id. This | 2334 | * HW Filter table since we can get the vlan id. This | |
2323 | * just creates the entry in the soft version of the | 2335 | * just creates the entry in the soft version of the | |
2324 | * VFTA, init will repopulate the real table. | 2336 | * VFTA, init will repopulate the real table. | |
2325 | ************************************************************************/ | 2337 | ************************************************************************/ | |
2326 | static int | 2338 | static int | |
2327 | ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) | 2339 | ixgbe_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) | |
@@ -2371,91 +2383,113 @@ ixgbe_unregister_vlan(void *arg, struct | @@ -2371,91 +2383,113 @@ ixgbe_unregister_vlan(void *arg, struct | |||
2371 | index = (vtag >> 5) & 0x7F; | 2383 | index = (vtag >> 5) & 0x7F; | |
2372 | bit = vtag & 0x1F; | 2384 | bit = vtag & 0x1F; | |
2373 | adapter->shadow_vfta[index] &= ~((u32)1 << bit); | 2385 | adapter->shadow_vfta[index] &= ~((u32)1 << bit); | |
2374 | error = adapter->hw.mac.ops.set_vfta(&adapter->hw, vtag, 0, false, | 2386 | error = adapter->hw.mac.ops.set_vfta(&adapter->hw, vtag, 0, false, | |
2375 | true); | 2387 | true); | |
2376 | IXGBE_CORE_UNLOCK(adapter); | 2388 | IXGBE_CORE_UNLOCK(adapter); | |
2377 | if (error != 0) | 2389 | if (error != 0) | |
2378 | error = EACCES; | 2390 | error = EACCES; | |
2379 | 2391 | |||
2380 | return error; | 2392 | return error; | |
2381 | } /* ixgbe_unregister_vlan */ | 2393 | } /* ixgbe_unregister_vlan */ | |
2382 | 2394 | |||
2383 | static void | 2395 | static void | |
2384 | ixgbe_setup_vlan_hw_support(struct adapter *adapter) | 2396 | ixgbe_setup_vlan_hw_tagging(struct adapter *adapter) | |
2385 | { | 2397 | { | |
2386 | struct ethercom *ec = &adapter->osdep.ec; | 2398 | struct ethercom *ec = &adapter->osdep.ec; | |
2387 | struct ixgbe_hw *hw = &adapter->hw; | 2399 | struct ixgbe_hw *hw = &adapter->hw; | |
2388 | struct rx_ring *rxr; | 2400 | struct rx_ring *rxr; | |
2389 | int i; | |||
2390 | u32 ctrl; | 2401 | u32 ctrl; | |
2391 | struct vlanid_list *vlanidp; | 2402 | int i; | |
2392 | bool hwtagging; | 2403 | bool hwtagging; | |
2393 | 2404 | |||
2394 | /* | |||
2395 | * This function is called from both if_init and ifflags_cb() | |||
2396 | * on NetBSD. | |||
2397 | */ | |||
2398 | ||||
2399 | /* Enable HW tagging only if any vlan is attached */ | 2405 | /* Enable HW tagging only if any vlan is attached */ | |
2400 | hwtagging = (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) | 2406 | hwtagging = (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) | |
2401 | && VLAN_ATTACHED(ec); | 2407 | && VLAN_ATTACHED(ec); | |
2402 | 2408 | |||
2403 | /* Setup the queues for vlans */ | 2409 | /* Setup the queues for vlans */ | |
2404 | for (i = 0; i < adapter->num_queues; i++) { | 2410 | for (i = 0; i < adapter->num_queues; i++) { | |
2405 | rxr = &adapter->rx_rings[i]; | 2411 | rxr = &adapter->rx_rings[i]; | |
2406 | /* | 2412 | /* | |
2407 | * On 82599 and later, the VLAN enable is per/queue in RXDCTL. | 2413 | * On 82599 and later, the VLAN enable is per/queue in RXDCTL. | |
2408 | */ | 2414 | */ | |
2409 | if (hw->mac.type != ixgbe_mac_82598EB) { | 2415 | if (hw->mac.type != ixgbe_mac_82598EB) { | |
2410 | ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); | 2416 | ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxr->me)); | |
2411 | if (hwtagging) | 2417 | if (hwtagging) | |
2412 | ctrl |= IXGBE_RXDCTL_VME; | 2418 | ctrl |= IXGBE_RXDCTL_VME; | |
2413 | else | 2419 | else | |
2414 | ctrl &= ~IXGBE_RXDCTL_VME; | 2420 | ctrl &= ~IXGBE_RXDCTL_VME; | |
2415 | IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); | 2421 | IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxr->me), ctrl); | |
2416 | } | 2422 | } | |
2417 | rxr->vtag_strip = hwtagging ? TRUE : FALSE; | 2423 | rxr->vtag_strip = hwtagging ? TRUE : FALSE; | |
2418 | } | 2424 | } | |
2419 | 2425 | |||
2426 | /* VLAN hw tagging for 82598 */ | |||
2427 | if (hw->mac.type == ixgbe_mac_82598EB) { | |||
2428 | ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); | |||
2429 | if (hwtagging) | |||
2430 | ctrl |= IXGBE_VLNCTRL_VME; | |||
2431 | else | |||
2432 | ctrl &= ~IXGBE_VLNCTRL_VME; | |||
2433 | IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); | |||
2434 | } | |||
2435 | } /* ixgbe_setup_vlan_hw_tagging */ | |||
2436 | ||||
2437 | static void | |||
2438 | ixgbe_setup_vlan_hw_support(struct adapter *adapter) | |||
2439 | { | |||
2440 | struct ethercom *ec = &adapter->osdep.ec; | |||
2441 | struct ixgbe_hw *hw = &adapter->hw; | |||
2442 | int i; | |||
2443 | u32 ctrl; | |||
2444 | struct vlanid_list *vlanidp; | |||
2445 | ||||
2446 | /* | |||
2447 | * This function is called from both if_init and ifflags_cb() | |||
2448 | * on NetBSD. | |||
2449 | */ | |||
2450 | ||||
2451 | /* | |||
2452 | * Part 1: | |||
2453 | * Setup VLAN HW tagging | |||
2454 | */ | |||
2455 | ixgbe_setup_vlan_hw_tagging(adapter); | |||
2456 | ||||
2457 | /* | |||
2458 | * Part 2: | |||
2459 | * Setup VLAN HW filter | |||
2460 | */ | |||
2420 | /* Cleanup shadow_vfta */ | 2461 | /* Cleanup shadow_vfta */ | |
2421 | for (i = 0; i < IXGBE_VFTA_SIZE; i++) | 2462 | for (i = 0; i < IXGBE_VFTA_SIZE; i++) | |
2422 | adapter->shadow_vfta[i] = 0; | 2463 | adapter->shadow_vfta[i] = 0; | |
2423 | /* Generate shadow_vfta from ec_vids */ | 2464 | /* Generate shadow_vfta from ec_vids */ | |
2424 | mutex_enter(ec->ec_lock); | 2465 | ETHER_LOCK(ec); | |
2425 | SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { | 2466 | SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { | |
2426 | uint32_t idx; | 2467 | uint32_t idx; | |
2427 | 2468 | |||
2428 | idx = vlanidp->vid / 32; | 2469 | idx = vlanidp->vid / 32; | |
2429 | KASSERT(idx < IXGBE_VFTA_SIZE); | 2470 | KASSERT(idx < IXGBE_VFTA_SIZE); | |
2430 | adapter->shadow_vfta[idx] |= (u32)1 << (vlanidp->vid % 32); | 2471 | adapter->shadow_vfta[idx] |= (u32)1 << (vlanidp->vid % 32); | |
2431 | } | 2472 | } | |
2432 | mutex_exit(ec->ec_lock); | 2473 | ETHER_UNLOCK(ec); | |
2433 | for (i = 0; i < IXGBE_VFTA_SIZE; i++) | 2474 | for (i = 0; i < IXGBE_VFTA_SIZE; i++) | |
2434 | IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), adapter->shadow_vfta[i]); | 2475 | IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), adapter->shadow_vfta[i]); | |
2435 | 2476 | |||
2436 | ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); | 2477 | ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); | |
2437 | /* Enable the Filter Table if enabled */ | 2478 | /* Enable the Filter Table if enabled */ | |
2438 | if (ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) | 2479 | if (ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) | |
2439 | ctrl |= IXGBE_VLNCTRL_VFE; | 2480 | ctrl |= IXGBE_VLNCTRL_VFE; | |
2440 | else | 2481 | else | |
2441 | ctrl &= ~IXGBE_VLNCTRL_VFE; | 2482 | ctrl &= ~IXGBE_VLNCTRL_VFE; | |
2442 | /* VLAN hw tagging for 82598 */ | |||
2443 | if (hw->mac.type == ixgbe_mac_82598EB) { | |||
2444 | if (hwtagging) | |||
2445 | ctrl |= IXGBE_VLNCTRL_VME; | |||
2446 | else | |||
2447 | ctrl &= ~IXGBE_VLNCTRL_VME; | |||
2448 | } | |||
2449 | IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); | 2483 | IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); | |
2450 | } /* ixgbe_setup_vlan_hw_support */ | 2484 | } /* ixgbe_setup_vlan_hw_support */ | |
2451 | 2485 | |||
2452 | /************************************************************************ | 2486 | /************************************************************************ | |
2453 | * ixgbe_get_slot_info | 2487 | * ixgbe_get_slot_info | |
2454 | * | 2488 | * | |
2455 | * Get the width and transaction speed of | 2489 | * Get the width and transaction speed of | |
2456 | * the slot this adapter is plugged into. | 2490 | * the slot this adapter is plugged into. | |
2457 | ************************************************************************/ | 2491 | ************************************************************************/ | |
2458 | static void | 2492 | static void | |
2459 | ixgbe_get_slot_info(struct adapter *adapter) | 2493 | ixgbe_get_slot_info(struct adapter *adapter) | |
2460 | { | 2494 | { | |
2461 | device_t dev = adapter->dev; | 2495 | device_t dev = adapter->dev; |
--- src/sys/dev/pci/ixgbe/ixv.c 2019/07/30 08:38:03 1.125
+++ src/sys/dev/pci/ixgbe/ixv.c 2019/09/01 11:07:05 1.125.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /*$NetBSD: ixv.c,v 1.125 2019/07/30 08:38:03 msaitoh Exp $*/ | 1 | /*$NetBSD: ixv.c,v 1.125.2.1 2019/09/01 11:07:05 martin Exp $*/ | |
2 | 2 | |||
3 | /****************************************************************************** | 3 | /****************************************************************************** | |
4 | 4 | |||
5 | Copyright (c) 2001-2017, Intel Corporation | 5 | Copyright (c) 2001-2017, Intel Corporation | |
6 | All rights reserved. | 6 | All rights reserved. | |
7 | 7 | |||
8 | Redistribution and use in source and binary forms, with or without | 8 | Redistribution and use in source and binary forms, with or without | |
9 | modification, are permitted provided that the following conditions are met: | 9 | modification, are permitted provided that the following conditions are met: | |
10 | 10 | |||
11 | 1. Redistributions of source code must retain the above copyright notice, | 11 | 1. Redistributions of source code must retain the above copyright notice, | |
12 | this list of conditions and the following disclaimer. | 12 | this list of conditions and the following disclaimer. | |
13 | 13 | |||
14 | 2. Redistributions in binary form must reproduce the above copyright | 14 | 2. Redistributions in binary form must reproduce the above copyright | |
@@ -110,26 +110,27 @@ static void ixv_initialize_receive_units | @@ -110,26 +110,27 @@ static void ixv_initialize_receive_units | |||
110 | static void ixv_initialize_rss_mapping(struct adapter *); | 110 | static void ixv_initialize_rss_mapping(struct adapter *); | |
111 | static s32 ixv_check_link(struct adapter *); | 111 | static s32 ixv_check_link(struct adapter *); | |
112 | 112 | |||
113 | static void ixv_enable_intr(struct adapter *); | 113 | static void ixv_enable_intr(struct adapter *); | |
114 | static void ixv_disable_intr(struct adapter *); | 114 | static void ixv_disable_intr(struct adapter *); | |
115 | static void ixv_set_multi(struct adapter *); | 115 | static void ixv_set_multi(struct adapter *); | |
116 | static void ixv_update_link_status(struct adapter *); | 116 | static void ixv_update_link_status(struct adapter *); | |
117 | static int ixv_sysctl_debug(SYSCTLFN_PROTO); | 117 | static int ixv_sysctl_debug(SYSCTLFN_PROTO); | |
118 | static void ixv_set_ivar(struct adapter *, u8, u8, s8); | 118 | static void ixv_set_ivar(struct adapter *, u8, u8, s8); | |
119 | static void ixv_configure_ivars(struct adapter *); | 119 | static void ixv_configure_ivars(struct adapter *); | |
120 | static u8 * ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | 120 | static u8 * ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *); | |
121 | static void ixv_eitr_write(struct adapter *, uint32_t, uint32_t); | 121 | static void ixv_eitr_write(struct adapter *, uint32_t, uint32_t); | |
122 | 122 | |||
123 | static void ixv_setup_vlan_tagging(struct adapter *); | |||
123 | static int ixv_setup_vlan_support(struct adapter *); | 124 | static int ixv_setup_vlan_support(struct adapter *); | |
124 | static int ixv_vlan_cb(struct ethercom *, uint16_t, bool); | 125 | static int ixv_vlan_cb(struct ethercom *, uint16_t, bool); | |
125 | static int ixv_register_vlan(void *, struct ifnet *, u16); | 126 | static int ixv_register_vlan(void *, struct ifnet *, u16); | |
126 | static int ixv_unregister_vlan(void *, struct ifnet *, u16); | 127 | static int ixv_unregister_vlan(void *, struct ifnet *, u16); | |
127 | 128 | |||
128 | static void ixv_add_device_sysctls(struct adapter *); | 129 | static void ixv_add_device_sysctls(struct adapter *); | |
129 | static void ixv_save_stats(struct adapter *); | 130 | static void ixv_save_stats(struct adapter *); | |
130 | static void ixv_init_stats(struct adapter *); | 131 | static void ixv_init_stats(struct adapter *); | |
131 | static void ixv_update_stats(struct adapter *); | 132 | static void ixv_update_stats(struct adapter *); | |
132 | static void ixv_add_stats_sysctls(struct adapter *); | 133 | static void ixv_add_stats_sysctls(struct adapter *); | |
133 | 134 | |||
134 | /* Sysctl handlers */ | 135 | /* Sysctl handlers */ | |
135 | static void ixv_set_sysctl_value(struct adapter *, const char *, | 136 | static void ixv_set_sysctl_value(struct adapter *, const char *, | |
@@ -1925,83 +1926,100 @@ ixv_sysctl_rdt_handler(SYSCTLFN_ARGS) | @@ -1925,83 +1926,100 @@ ixv_sysctl_rdt_handler(SYSCTLFN_ARGS) | |||
1925 | { | 1926 | { | |
1926 | struct sysctlnode node = *rnode; | 1927 | struct sysctlnode node = *rnode; | |
1927 | struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data; | 1928 | struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data; | |
1928 | uint32_t val; | 1929 | uint32_t val; | |
1929 | 1930 | |||
1930 | if (!rxr) | 1931 | if (!rxr) | |
1931 | return (0); | 1932 | return (0); | |
1932 | 1933 | |||
1933 | val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_VFRDT(rxr->me)); | 1934 | val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_VFRDT(rxr->me)); | |
1934 | node.sysctl_data = &val; | 1935 | node.sysctl_data = &val; | |
1935 | return sysctl_lookup(SYSCTLFN_CALL(&node)); | 1936 | return sysctl_lookup(SYSCTLFN_CALL(&node)); | |
1936 | } /* ixv_sysctl_rdt_handler */ | 1937 | } /* ixv_sysctl_rdt_handler */ | |
1937 | 1938 | |||
1938 | /************************************************************************ | 1939 | static void | |
1939 | * ixv_setup_vlan_support | 1940 | ixv_setup_vlan_tagging(struct adapter *adapter) | |
1940 | ************************************************************************/ | |||
1941 | static int | |||
1942 | ixv_setup_vlan_support(struct adapter *adapter) | |||
1943 | { | 1941 | { | |
1944 | struct ethercom *ec = &adapter->osdep.ec; | 1942 | struct ethercom *ec = &adapter->osdep.ec; | |
1945 | struct ixgbe_hw *hw = &adapter->hw; | 1943 | struct ixgbe_hw *hw = &adapter->hw; | |
1946 | struct rx_ring *rxr; | 1944 | struct rx_ring *rxr; | |
1947 | u32 ctrl, vid, vfta, retry; | 1945 | u32 ctrl; | |
1948 | struct vlanid_list *vlanidp; | 1946 | int i; | |
1949 | int rv, error = 0; | |||
1950 | bool usevlan; | |||
1951 | bool hwtagging; | 1947 | bool hwtagging; | |
1952 | 1948 | |||
1953 | /* | |||
1954 | * This function is called from both if_init and ifflags_cb() | |||
1955 | * on NetBSD. | |||
1956 | */ | |||
1957 | usevlan = VLAN_ATTACHED(ec); | |||
1958 | ||||
1959 | /* Enable HW tagging only if any vlan is attached */ | 1949 | /* Enable HW tagging only if any vlan is attached */ | |
1960 | hwtagging = (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) | 1950 | hwtagging = (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) | |
1961 | && VLAN_ATTACHED(ec); | 1951 | && VLAN_ATTACHED(ec); | |
1962 | 1952 | |||
1963 | /* Enable the queues */ | 1953 | /* Enable the queues */ | |
1964 | for (int i = 0; i < adapter->num_queues; i++) { | 1954 | for (i = 0; i < adapter->num_queues; i++) { | |
1965 | rxr = &adapter->rx_rings[i]; | 1955 | rxr = &adapter->rx_rings[i]; | |
1966 | ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(rxr->me)); | 1956 | ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(rxr->me)); | |
1967 | if (hwtagging) | 1957 | if (hwtagging) | |
1968 | ctrl |= IXGBE_RXDCTL_VME; | 1958 | ctrl |= IXGBE_RXDCTL_VME; | |
1969 | else | 1959 | else | |
1970 | ctrl &= ~IXGBE_RXDCTL_VME; | 1960 | ctrl &= ~IXGBE_RXDCTL_VME; | |
1971 | IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(rxr->me), ctrl); | 1961 | IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(rxr->me), ctrl); | |
1972 | /* | 1962 | /* | |
1973 | * Let Rx path know that it needs to store VLAN tag | 1963 | * Let Rx path know that it needs to store VLAN tag | |
1974 | * as part of extra mbuf info. | 1964 | * as part of extra mbuf info. | |
1975 | */ | 1965 | */ | |
1976 | rxr->vtag_strip = hwtagging ? TRUE : FALSE; | 1966 | rxr->vtag_strip = hwtagging ? TRUE : FALSE; | |
1977 | } | 1967 | } | |
1968 | } /* ixv_setup_vlan_tagging */ | |||
1969 | ||||
1970 | /************************************************************************ | |||
1971 | * ixv_setup_vlan_support | |||
1972 | ************************************************************************/ | |||
1973 | static int | |||
1974 | ixv_setup_vlan_support(struct adapter *adapter) | |||
1975 | { | |||
1976 | struct ethercom *ec = &adapter->osdep.ec; | |||
1977 | struct ixgbe_hw *hw = &adapter->hw; | |||
1978 | u32 vid, vfta, retry; | |||
1979 | struct vlanid_list *vlanidp; | |||
1980 | int rv, error = 0; | |||
1981 | ||||
1982 | /* | |||
1983 | * This function is called from both if_init and ifflags_cb() | |||
1984 | * on NetBSD. | |||
1985 | */ | |||
1986 | ||||
1987 | /* | |||
1988 | * Part 1: | |||
1989 | * Setup VLAN HW tagging | |||
1990 | */ | |||
1991 | ixv_setup_vlan_tagging(adapter); | |||
1978 | 1992 | |||
1979 | if (!usevlan) | 1993 | if (!VLAN_ATTACHED(ec)) | |
1980 | return 0; | 1994 | return 0; | |
1981 | 1995 | |||
1996 | /* | |||
1997 | * Part 2: | |||
1998 | * Setup VLAN HW filter | |||
1999 | */ | |||
1982 | /* Cleanup shadow_vfta */ | 2000 | /* Cleanup shadow_vfta */ | |
1983 | for (int i = 0; i < IXGBE_VFTA_SIZE; i++) | 2001 | for (int i = 0; i < IXGBE_VFTA_SIZE; i++) | |
1984 | adapter->shadow_vfta[i] = 0; | 2002 | adapter->shadow_vfta[i] = 0; | |
1985 | /* Generate shadow_vfta from ec_vids */ | 2003 | /* Generate shadow_vfta from ec_vids */ | |
1986 | mutex_enter(ec->ec_lock); | 2004 | ETHER_LOCK(ec); | |
1987 | SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { | 2005 | SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { | |
1988 | uint32_t idx; | 2006 | uint32_t idx; | |
1989 | 2007 | |||
1990 | idx = vlanidp->vid / 32; | 2008 | idx = vlanidp->vid / 32; | |
1991 | KASSERT(idx < IXGBE_VFTA_SIZE); | 2009 | KASSERT(idx < IXGBE_VFTA_SIZE); | |
1992 | adapter->shadow_vfta[idx] |= (u32)1 << (vlanidp->vid % 32); | 2010 | adapter->shadow_vfta[idx] |= (u32)1 << (vlanidp->vid % 32); | |
1993 | } | 2011 | } | |
1994 | mutex_exit(ec->ec_lock); | 2012 | ETHER_UNLOCK(ec); | |
1995 | 2013 | |||
1996 | /* | 2014 | /* | |
1997 | * A soft reset zero's out the VFTA, so | 2015 | * A soft reset zero's out the VFTA, so | |
1998 | * we need to repopulate it now. | 2016 | * we need to repopulate it now. | |
1999 | */ | 2017 | */ | |
2000 | for (int i = 0; i < IXGBE_VFTA_SIZE; i++) { | 2018 | for (int i = 0; i < IXGBE_VFTA_SIZE; i++) { | |
2001 | if (adapter->shadow_vfta[i] == 0) | 2019 | if (adapter->shadow_vfta[i] == 0) | |
2002 | continue; | 2020 | continue; | |
2003 | vfta = adapter->shadow_vfta[i]; | 2021 | vfta = adapter->shadow_vfta[i]; | |
2004 | /* | 2022 | /* | |
2005 | * Reconstruct the vlan id's | 2023 | * Reconstruct the vlan id's | |
2006 | * based on the bits set in each | 2024 | * based on the bits set in each | |
2007 | * of the array ints. | 2025 | * of the array ints. | |
@@ -2026,33 +2044,44 @@ ixv_setup_vlan_support(struct adapter *a | @@ -2026,33 +2044,44 @@ ixv_setup_vlan_support(struct adapter *a | |||
2026 | device_printf(adapter->dev, | 2044 | device_printf(adapter->dev, | |
2027 | "failed to set vlan %d\n", vid); | 2045 | "failed to set vlan %d\n", vid); | |
2028 | error = EACCES; | 2046 | error = EACCES; | |
2029 | } | 2047 | } | |
2030 | } | 2048 | } | |
2031 | } | 2049 | } | |
2032 | return error; | 2050 | return error; | |
2033 | } /* ixv_setup_vlan_support */ | 2051 | } /* ixv_setup_vlan_support */ | |
2034 | 2052 | |||
2035 | static int | 2053 | static int | |
2036 | ixv_vlan_cb(struct ethercom *ec, uint16_t vid, bool set) | 2054 | ixv_vlan_cb(struct ethercom *ec, uint16_t vid, bool set) | |
2037 | { | 2055 | { | |
2038 | struct ifnet *ifp = &ec->ec_if; | 2056 | struct ifnet *ifp = &ec->ec_if; | |
2057 | struct adapter *adapter = ifp->if_softc; | |||
2039 | int rv; | 2058 | int rv; | |
2040 | 2059 | |||
2041 | if (set) | 2060 | if (set) | |
2042 | rv = ixv_register_vlan(ifp->if_softc, ifp, vid); | 2061 | rv = ixv_register_vlan(ifp->if_softc, ifp, vid); | |
2043 | else | 2062 | else | |
2044 | rv = ixv_unregister_vlan(ifp->if_softc, ifp, vid); | 2063 | rv = ixv_unregister_vlan(ifp->if_softc, ifp, vid); | |
2045 | 2064 | |||
2065 | if (rv != 0) | |||
2066 | return rv; | |||
2067 | ||||
2068 | /* | |||
2069 | * Control VLAN HW tagging when ec_nvlan is changed from 1 to 0 | |||
2070 | * or 0 to 1. | |||
2071 | */ | |||
2072 | if ((set && (ec->ec_nvlans == 1)) || (!set && (ec->ec_nvlans == 0))) | |||
2073 | ixv_setup_vlan_tagging(adapter); | |||
2074 | ||||
2046 | return rv; | 2075 | return rv; | |
2047 | } | 2076 | } | |
2048 | 2077 | |||
2049 | /************************************************************************ | 2078 | /************************************************************************ | |
2050 | * ixv_register_vlan | 2079 | * ixv_register_vlan | |
2051 | * | 2080 | * | |
2052 | * Run via a vlan config EVENT, it enables us to use the | 2081 | * Run via a vlan config EVENT, it enables us to use the | |
2053 | * HW Filter table since we can get the vlan id. This just | 2082 | * HW Filter table since we can get the vlan id. This just | |
2054 | * creates the entry in the soft version of the VFTA, init | 2083 | * creates the entry in the soft version of the VFTA, init | |
2055 | * will repopulate the real table. | 2084 | * will repopulate the real table. | |
2056 | ************************************************************************/ | 2085 | ************************************************************************/ | |
2057 | static int | 2086 | static int | |
2058 | ixv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) | 2087 | ixv_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) |
--- src/sys/net/if_vlan.c 2019/07/17 03:26:24 1.141
+++ src/sys/net/if_vlan.c 2019/09/01 11:07:06 1.141.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if_vlan.c,v 1.141 2019/07/17 03:26:24 msaitoh Exp $ */ | 1 | /* $NetBSD: if_vlan.c,v 1.141.2.1 2019/09/01 11:07:06 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Doran, and by Jason R. Thorpe of Zembu Labs, Inc. | 8 | * by Andrew Doran, and by Jason R. Thorpe of Zembu Labs, Inc. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -68,27 +68,27 @@ | @@ -68,27 +68,27 @@ | |||
68 | * enough of an Ethernet implementation to make ARP work. The way we do | 68 | * enough of an Ethernet implementation to make ARP work. The way we do | |
69 | * this is by telling everyone that we are an Ethernet interface, and then | 69 | * this is by telling everyone that we are an Ethernet interface, and then | |
70 | * catch the packets that ether_output() left on our output queue when it | 70 | * catch the packets that ether_output() left on our output queue when it | |
71 | * calls if_start(), rewrite them for use by the real outgoing interface, | 71 | * calls if_start(), rewrite them for use by the real outgoing interface, | |
72 | * and ask it to send them. | 72 | * and ask it to send them. | |
73 | * | 73 | * | |
74 | * TODO: | 74 | * TODO: | |
75 | * | 75 | * | |
76 | * - Need some way to notify vlan interfaces when the parent | 76 | * - Need some way to notify vlan interfaces when the parent | |
77 | * interface changes MTU. | 77 | * interface changes MTU. | |
78 | */ | 78 | */ | |
79 | 79 | |||
80 | #include <sys/cdefs.h> | 80 | #include <sys/cdefs.h> | |
81 | __KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.141 2019/07/17 03:26:24 msaitoh Exp $"); | 81 | __KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.141.2.1 2019/09/01 11:07:06 martin Exp $"); | |
82 | 82 | |||
83 | #ifdef _KERNEL_OPT | 83 | #ifdef _KERNEL_OPT | |
84 | #include "opt_inet.h" | 84 | #include "opt_inet.h" | |
85 | #include "opt_net_mpsafe.h" | 85 | #include "opt_net_mpsafe.h" | |
86 | #endif | 86 | #endif | |
87 | 87 | |||
88 | #include <sys/param.h> | 88 | #include <sys/param.h> | |
89 | #include <sys/systm.h> | 89 | #include <sys/systm.h> | |
90 | #include <sys/kernel.h> | 90 | #include <sys/kernel.h> | |
91 | #include <sys/mbuf.h> | 91 | #include <sys/mbuf.h> | |
92 | #include <sys/queue.h> | 92 | #include <sys/queue.h> | |
93 | #include <sys/socket.h> | 93 | #include <sys/socket.h> | |
94 | #include <sys/sockio.h> | 94 | #include <sys/sockio.h> | |
@@ -475,54 +475,47 @@ vlan_config(struct ifvlan *ifv, struct i | @@ -475,54 +475,47 @@ vlan_config(struct ifvlan *ifv, struct i | |||
475 | nmib->ifvm_mtufudge = 0; | 475 | nmib->ifvm_mtufudge = 0; | |
476 | } else { | 476 | } else { | |
477 | /* | 477 | /* | |
478 | * Fudge the MTU by the encapsulation size. This | 478 | * Fudge the MTU by the encapsulation size. This | |
479 | * makes us incompatible with strictly compliant | 479 | * makes us incompatible with strictly compliant | |
480 | * 802.1Q implementations, but allows us to use | 480 | * 802.1Q implementations, but allows us to use | |
481 | * the feature with other NetBSD | 481 | * the feature with other NetBSD | |
482 | * implementations, which might still be useful. | 482 | * implementations, which might still be useful. | |
483 | */ | 483 | */ | |
484 | nmib->ifvm_mtufudge = nmib->ifvm_encaplen; | 484 | nmib->ifvm_mtufudge = nmib->ifvm_encaplen; | |
485 | } | 485 | } | |
486 | error = 0; | 486 | error = 0; | |
487 | } | 487 | } | |
488 | /* | 488 | /* Add a vid to the list */ | |
489 | * Add a vid to the list even if it's not enabled in case | 489 | vidmem = kmem_alloc(sizeof(struct vlanid_list), KM_SLEEP); | |
490 | * it's enabled later. | 490 | vidmem->vid = vid; | |
491 | */ | 491 | ETHER_LOCK(ec); | |
492 | if (ec->ec_capabilities & ETHERCAP_VLAN_HWFILTER) { | 492 | SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidmem, vid_list); | |
493 | vidmem = kmem_alloc(sizeof(struct vlanid_list), | 493 | ETHER_UNLOCK(ec); | |
494 | KM_SLEEP); | 494 | ||
495 | if (vidmem == NULL){ | 495 | if (ec->ec_vlan_cb != NULL) { | |
496 | /* | |||
497 | * Call ec_vlan_cb(). It will setup VLAN HW filter or | |||
498 | * HW tagging function. | |||
499 | */ | |||
500 | error = (*ec->ec_vlan_cb)(ec, vid, true); | |||
501 | if (error) { | |||
496 | ec->ec_nvlans--; | 502 | ec->ec_nvlans--; | |
497 | if (ec->ec_nvlans == 0) | 503 | if (ec->ec_nvlans == 0) { | |
504 | IFNET_LOCK(p); | |||
498 | (void)ether_disable_vlan_mtu(p); | 505 | (void)ether_disable_vlan_mtu(p); | |
499 | error = ENOMEM; | 506 | IFNET_UNLOCK(p); | |
500 | goto done; | |||
501 | } | |||
502 | vidmem->vid = vid; | |||
503 | mutex_enter(ec->ec_lock); | |||
504 | SIMPLEQ_INSERT_TAIL(&ec->ec_vids, vidmem, vid_list); | |||
505 | mutex_exit(ec->ec_lock); | |||
506 | } | |||
507 | if (ec->ec_capenable & ETHERCAP_VLAN_HWFILTER) { | |||
508 | if (ec->ec_vlan_cb != NULL) { | |||
509 | error = (*ec->ec_vlan_cb)(ec, vid, true); | |||
510 | if (error) { | |||
511 | ec->ec_nvlans--; | |||
512 | if (ec->ec_nvlans == 0) | |||
513 | (void)ether_disable_vlan_mtu(p); | |||
514 | goto done; | |||
515 | } | 507 | } | |
508 | goto done; | |||
516 | } | 509 | } | |
517 | } | 510 | } | |
518 | /* | 511 | /* | |
519 | * If the parent interface can do hardware-assisted | 512 | * If the parent interface can do hardware-assisted | |
520 | * VLAN encapsulation, then propagate its hardware- | 513 | * VLAN encapsulation, then propagate its hardware- | |
521 | * assisted checksumming flags and tcp segmentation | 514 | * assisted checksumming flags and tcp segmentation | |
522 | * offload. | 515 | * offload. | |
523 | */ | 516 | */ | |
524 | if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { | 517 | if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { | |
525 | ifp->if_capabilities = p->if_capabilities & | 518 | ifp->if_capabilities = p->if_capabilities & | |
526 | (IFCAP_TSOv4 | IFCAP_TSOv6 | | 519 | (IFCAP_TSOv4 | IFCAP_TSOv6 | | |
527 | IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx | | 520 | IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx | | |
528 | IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx | | 521 | IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx | | |
@@ -630,40 +623,48 @@ vlan_unconfig_locked(struct ifvlan *ifv, | @@ -630,40 +623,48 @@ vlan_unconfig_locked(struct ifvlan *ifv, | |||
630 | 623 | |||
631 | /* | 624 | /* | |
632 | * Since the interface is being unconfigured, we need to empty the | 625 | * Since the interface is being unconfigured, we need to empty the | |
633 | * list of multicast groups that we may have joined while we were | 626 | * list of multicast groups that we may have joined while we were | |
634 | * alive and remove them from the parent's list also. | 627 | * alive and remove them from the parent's list also. | |
635 | */ | 628 | */ | |
636 | (*nmib->ifvm_msw->vmsw_purgemulti)(ifv); | 629 | (*nmib->ifvm_msw->vmsw_purgemulti)(ifv); | |
637 | 630 | |||
638 | /* Disconnect from parent. */ | 631 | /* Disconnect from parent. */ | |
639 | switch (p->if_type) { | 632 | switch (p->if_type) { | |
640 | case IFT_ETHER: | 633 | case IFT_ETHER: | |
641 | { | 634 | { | |
642 | struct ethercom *ec = (void *)p; | 635 | struct ethercom *ec = (void *)p; | |
643 | struct vlanid_list *vlanidp, *tmpp; | 636 | struct vlanid_list *vlanidp; | |
644 | uint16_t vid = EVL_VLANOFTAG(nmib->ifvm_tag); | 637 | uint16_t vid = EVL_VLANOFTAG(nmib->ifvm_tag); | |
645 | 638 | |||
646 | mutex_enter(ec->ec_lock); | 639 | ETHER_LOCK(ec); | |
647 | SIMPLEQ_FOREACH_SAFE(vlanidp, &ec->ec_vids, vid_list, tmpp) { | 640 | SIMPLEQ_FOREACH(vlanidp, &ec->ec_vids, vid_list) { | |
648 | if (vlanidp->vid == vid) { | 641 | if (vlanidp->vid == vid) { | |
649 | SIMPLEQ_REMOVE(&ec->ec_vids, vlanidp, | 642 | SIMPLEQ_REMOVE(&ec->ec_vids, vlanidp, | |
650 | vlanid_list, vid_list); | 643 | vlanid_list, vid_list); | |
651 | kmem_free(vlanidp, sizeof(*vlanidp)); | 644 | break; | |
652 | } | 645 | } | |
653 | } | 646 | } | |
654 | mutex_exit(ec->ec_lock); | 647 | ETHER_UNLOCK(ec); | |
655 | if (ec->ec_vlan_cb != NULL) | 648 | if (vlanidp != NULL) | |
649 | kmem_free(vlanidp, sizeof(*vlanidp)); | |||
650 | ||||
651 | if (ec->ec_vlan_cb != NULL) { | |||
652 | /* | |||
653 | * Call ec_vlan_cb(). It will setup VLAN HW filter or | |||
654 | * HW tagging function. | |||
655 | */ | |||
656 | (void)(*ec->ec_vlan_cb)(ec, vid, false); | 656 | (void)(*ec->ec_vlan_cb)(ec, vid, false); | |
657 | } | |||
657 | if (--ec->ec_nvlans == 0) { | 658 | if (--ec->ec_nvlans == 0) { | |
658 | IFNET_LOCK(p); | 659 | IFNET_LOCK(p); | |
659 | (void)ether_disable_vlan_mtu(p); | 660 | (void)ether_disable_vlan_mtu(p); | |
660 | IFNET_UNLOCK(p); | 661 | IFNET_UNLOCK(p); | |
661 | } | 662 | } | |
662 | 663 | |||
663 | /* XXX ether_ifdetach must not be called with IFNET_LOCK */ | 664 | /* XXX ether_ifdetach must not be called with IFNET_LOCK */ | |
664 | mutex_exit(&ifv->ifv_lock); | 665 | mutex_exit(&ifv->ifv_lock); | |
665 | IFNET_UNLOCK(ifp); | 666 | IFNET_UNLOCK(ifp); | |
666 | ether_ifdetach(ifp); | 667 | ether_ifdetach(ifp); | |
667 | IFNET_LOCK(ifp); | 668 | IFNET_LOCK(ifp); | |
668 | mutex_enter(&ifv->ifv_lock); | 669 | mutex_enter(&ifv->ifv_lock); | |
669 | 670 | |||
@@ -1025,27 +1026,27 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd | @@ -1025,27 +1026,27 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd | |||
1025 | curlwp_bindx(bound); | 1026 | curlwp_bindx(bound); | |
1026 | 1027 | |||
1027 | vlan_unconfig(ifp); | 1028 | vlan_unconfig(ifp); | |
1028 | break; | 1029 | break; | |
1029 | } | 1030 | } | |
1030 | if (vlr.vlr_tag != EVL_VLANOFTAG(vlr.vlr_tag)) { | 1031 | if (vlr.vlr_tag != EVL_VLANOFTAG(vlr.vlr_tag)) { | |
1031 | error = EINVAL; /* check for valid tag */ | 1032 | error = EINVAL; /* check for valid tag */ | |
1032 | break; | 1033 | break; | |
1033 | } | 1034 | } | |
1034 | if ((pr = ifunit(vlr.vlr_parent)) == NULL) { | 1035 | if ((pr = ifunit(vlr.vlr_parent)) == NULL) { | |
1035 | error = ENOENT; | 1036 | error = ENOENT; | |
1036 | break; | 1037 | break; | |
1037 | } | 1038 | } | |
1038 | 1039 | |||
1039 | error = vlan_config(ifv, pr, vlr.vlr_tag); | 1040 | error = vlan_config(ifv, pr, vlr.vlr_tag); | |
1040 | if (error != 0) | 1041 | if (error != 0) | |
1041 | break; | 1042 | break; | |
1042 | 1043 | |||
1043 | /* Update promiscuous mode, if necessary. */ | 1044 | /* Update promiscuous mode, if necessary. */ | |
1044 | vlan_set_promisc(ifp); | 1045 | vlan_set_promisc(ifp); | |
1045 | 1046 | |||
1046 | ifp->if_flags |= IFF_RUNNING; | 1047 | ifp->if_flags |= IFF_RUNNING; | |
1047 | break; | 1048 | break; | |
1048 | 1049 | |||
1049 | case SIOCGETVLAN: | 1050 | case SIOCGETVLAN: | |
1050 | memset(&vlr, 0, sizeof(vlr)); | 1051 | memset(&vlr, 0, sizeof(vlr)); | |
1051 | bound = curlwp_bind(); | 1052 | bound = curlwp_bind(); | |
@@ -1363,27 +1364,27 @@ vlan_start(struct ifnet *ifp) | @@ -1363,27 +1364,27 @@ vlan_start(struct ifnet *ifp) | |||
1363 | break; | 1364 | break; | |
1364 | default: | 1365 | default: | |
1365 | panic("%s: impossible (altq)", __func__); | 1366 | panic("%s: impossible (altq)", __func__); | |
1366 | } | 1367 | } | |
1367 | } | 1368 | } | |
1368 | KERNEL_UNLOCK_ONE(NULL); | 1369 | KERNEL_UNLOCK_ONE(NULL); | |
1369 | #endif /* ALTQ */ | 1370 | #endif /* ALTQ */ | |
1370 | 1371 | |||
1371 | bpf_mtap(ifp, m, BPF_D_OUT); | 1372 | bpf_mtap(ifp, m, BPF_D_OUT); | |
1372 | /* | 1373 | /* | |
1373 | * If the parent can insert the tag itself, just mark | 1374 | * If the parent can insert the tag itself, just mark | |
1374 | * the tag in the mbuf header. | 1375 | * the tag in the mbuf header. | |
1375 | */ | 1376 | */ | |
1376 | if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { | 1377 | if (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) { | |
1377 | vlan_set_tag(m, mib->ifvm_tag); | 1378 | vlan_set_tag(m, mib->ifvm_tag); | |
1378 | } else { | 1379 | } else { | |
1379 | /* | 1380 | /* | |
1380 | * insert the tag ourselves | 1381 | * insert the tag ourselves | |
1381 | */ | 1382 | */ | |
1382 | M_PREPEND(m, mib->ifvm_encaplen, M_DONTWAIT); | 1383 | M_PREPEND(m, mib->ifvm_encaplen, M_DONTWAIT); | |
1383 | if (m == NULL) { | 1384 | if (m == NULL) { | |
1384 | printf("%s: unable to prepend encap header", | 1385 | printf("%s: unable to prepend encap header", | |
1385 | p->if_xname); | 1386 | p->if_xname); | |
1386 | ifp->if_oerrors++; | 1387 | ifp->if_oerrors++; | |
1387 | continue; | 1388 | continue; | |
1388 | } | 1389 | } | |
1389 | 1390 | |||
@@ -1481,27 +1482,27 @@ vlan_transmit(struct ifnet *ifp, struct | @@ -1481,27 +1482,27 @@ vlan_transmit(struct ifnet *ifp, struct | |||
1481 | ec = (void *)mib->ifvm_p; | 1482 | ec = (void *)mib->ifvm_p; | |
1482 | 1483 | |||
1483 | bpf_mtap(ifp, m, BPF_D_OUT); | 1484 | bpf_mtap(ifp, m, BPF_D_OUT); | |
1484 | 1485 | |||
1485 | if ((error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT)) != 0) | 1486 | if ((error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT)) != 0) | |
1486 | goto out; | 1487 | goto out; | |
1487 | if (m == NULL) | 1488 | if (m == NULL) | |
1488 | goto out; | 1489 | goto out; | |
1489 | 1490 | |||
1490 | /* | 1491 | /* | |
1491 | * If the parent can insert the tag itself, just mark | 1492 | * If the parent can insert the tag itself, just mark | |
1492 | * the tag in the mbuf header. | 1493 | * the tag in the mbuf header. | |
1493 | */ | 1494 | */ | |
1494 | if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) { | 1495 | if (ec->ec_capenable & ETHERCAP_VLAN_HWTAGGING) { | |
1495 | vlan_set_tag(m, mib->ifvm_tag); | 1496 | vlan_set_tag(m, mib->ifvm_tag); | |
1496 | } else { | 1497 | } else { | |
1497 | /* | 1498 | /* | |
1498 | * insert the tag ourselves | 1499 | * insert the tag ourselves | |
1499 | */ | 1500 | */ | |
1500 | M_PREPEND(m, mib->ifvm_encaplen, M_DONTWAIT); | 1501 | M_PREPEND(m, mib->ifvm_encaplen, M_DONTWAIT); | |
1501 | if (m == NULL) { | 1502 | if (m == NULL) { | |
1502 | printf("%s: unable to prepend encap header", | 1503 | printf("%s: unable to prepend encap header", | |
1503 | p->if_xname); | 1504 | p->if_xname); | |
1504 | ifp->if_oerrors++; | 1505 | ifp->if_oerrors++; | |
1505 | error = ENOBUFS; | 1506 | error = ENOBUFS; | |
1506 | goto out; | 1507 | goto out; | |
1507 | } | 1508 | } |