static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) { struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_hw *hw = &interface->hw; s32 err; /* updates do not apply to VLAN 0 */ if (!vid) return 0; if (vid >= VLAN_N_VID) return -EINVAL; /* Verify we have permission to add VLANs */ if (hw->mac.vlan_override) return -EACCES; /* if default VLAN is already present do nothing */ if (vid == hw->mac.default_vid) return -EBUSY; /* update active_vlans bitmask */ set_bit(vid, interface->active_vlans); if (!set) clear_bit(vid, interface->active_vlans); fm10k_mbx_lock(interface); /* only need to update the VLAN if not in promiscous mode */ if (!(netdev->flags & IFF_PROMISC)) { err = hw->mac.ops.update_vlan(hw, vid, 0, set); if (err) goto err_out; } /* update our base MAC address */ err = hw->mac.ops.update_uc_addr(hw, interface->glort, hw->mac.addr, vid, set, 0); if (err) goto err_out; /* set vid prior to syncing/unsyncing the VLAN */ interface->vid = vid + (set ? VLAN_N_VID : 0); /* Update the unicast and multicast address list to add/drop VLAN */ __dev_uc_unsync(netdev, fm10k_uc_vlan_unsync); __dev_mc_unsync(netdev, fm10k_mc_vlan_unsync); err_out: fm10k_mbx_unlock(interface); return err; }
void fm10k_reset_rx_state(struct fm10k_intfc *interface) { struct net_device *netdev = interface->netdev; struct fm10k_hw *hw = &interface->hw; fm10k_mbx_lock(interface); /* clear the logical port state on lower device */ hw->mac.ops.update_lport_state(hw, interface->glort, interface->glort_count, false); fm10k_mbx_unlock(interface); /* reset flags to default state */ interface->xcast_mode = FM10K_XCAST_MODE_NONE; /* clear the sync flag since the lport has been dropped */ __dev_uc_unsync(netdev, NULL); __dev_mc_unsync(netdev, NULL); }
static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) { struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_hw *hw = &interface->hw; s32 err; int i; /* updates do not apply to VLAN 0 */ if (!vid) return 0; if (vid >= VLAN_N_VID) return -EINVAL; /* Verify we have permission to add VLANs */ if (hw->mac.vlan_override) return -EACCES; /* update active_vlans bitmask */ set_bit(vid, interface->active_vlans); if (!set) clear_bit(vid, interface->active_vlans); /* disable the default VLAN ID on ring if we have an active VLAN */ for (i = 0; i < interface->num_rx_queues; i++) { struct fm10k_ring *rx_ring = interface->rx_ring[i]; u16 rx_vid = rx_ring->vid & (VLAN_N_VID - 1); if (test_bit(rx_vid, interface->active_vlans)) rx_ring->vid |= FM10K_VLAN_CLEAR; else rx_ring->vid &= ~FM10K_VLAN_CLEAR; } /* Do not remove default VLAN ID related entries from VLAN and MAC * tables */ if (!set && vid == hw->mac.default_vid) return 0; /* Do not throw an error if the interface is down. We will sync once * we come up */ if (test_bit(__FM10K_DOWN, &interface->state)) return 0; fm10k_mbx_lock(interface); /* only need to update the VLAN if not in promiscuous mode */ if (!(netdev->flags & IFF_PROMISC)) { err = hw->mac.ops.update_vlan(hw, vid, 0, set); if (err) goto err_out; } /* update our base MAC address */ err = hw->mac.ops.update_uc_addr(hw, interface->glort, hw->mac.addr, vid, set, 0); if (err) goto err_out; /* set VLAN ID prior to syncing/unsyncing the VLAN */ interface->vid = vid + (set ? VLAN_N_VID : 0); /* Update the unicast and multicast address list to add/drop VLAN */ __dev_uc_unsync(netdev, fm10k_uc_vlan_unsync); __dev_mc_unsync(netdev, fm10k_mc_vlan_unsync); err_out: fm10k_mbx_unlock(interface); return err; }