示例#1
0
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;
}
示例#2
0
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);
}
示例#3
0
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;
}