Commit b57b44f7 authored by David S. Miller's avatar David S. Miller
Browse files

-queue

Tony Nguyen says:

====================
10GbE Intel Wired LAN Driver Updates 2022-03-08

This series contains updates to ixgbe and ixgbevf drivers.

Slawomir adds an implementation for ndo_set_vf_link_state() to allow
for disabling of VF link state as well a mailbox implementation so
the VF can query the state. Additionally, for 82599, the option to
disable a VF after receiving several malicious driver detection (MDD)
events are encountered is added. For ixgbevf, the corresponding
implementation to query and report a disabled state is added.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d82a6c5e 443ebdd6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -177,11 +177,14 @@ struct vf_data_storage {
	u16 pf_vlan; /* When set, guest VLAN config not allowed. */
	u16 pf_qos;
	u16 tx_rate;
	int link_enable;
	int link_state;
	u8 spoofchk_enabled;
	bool rss_query_enabled;
	u8 trusted;
	int xcast_mode;
	unsigned int vf_api;
	u8 primary_abort_count;
};

enum ixgbevf_xcast_modes {
@@ -556,6 +559,8 @@ struct ixgbe_mac_addr {
#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
#define IXGBE_SFP_POLL_JIFFIES (2 * HZ)	/* SFP poll every 2 seconds */

#define IXGBE_PRIMARY_ABORT_LIMIT	5

/* board specific private data structure */
struct ixgbe_adapter {
	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
@@ -614,6 +619,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_RX_LEGACY			BIT(16)
#define IXGBE_FLAG2_IPSEC_ENABLED		BIT(17)
#define IXGBE_FLAG2_VF_IPSEC_ENABLED		BIT(18)
#define IXGBE_FLAG2_AUTO_DISABLE_VF		BIT(19)

	/* Tx fast path data */
	int num_tx_queues;
+21 −0
Original line number Diff line number Diff line
@@ -138,6 +138,8 @@ static const char ixgbe_priv_flags_strings[][ETH_GSTRING_LEN] = {
	"legacy-rx",
#define IXGBE_PRIV_FLAGS_VF_IPSEC_EN	BIT(1)
	"vf-ipsec",
#define IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF	BIT(2)
	"mdd-disable-vf",
};

#define IXGBE_PRIV_FLAGS_STR_LEN ARRAY_SIZE(ixgbe_priv_flags_strings)
@@ -3510,6 +3512,9 @@ static u32 ixgbe_get_priv_flags(struct net_device *netdev)
	if (adapter->flags2 & IXGBE_FLAG2_VF_IPSEC_ENABLED)
		priv_flags |= IXGBE_PRIV_FLAGS_VF_IPSEC_EN;

	if (adapter->flags2 & IXGBE_FLAG2_AUTO_DISABLE_VF)
		priv_flags |= IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF;

	return priv_flags;
}

@@ -3517,6 +3522,7 @@ static int ixgbe_set_priv_flags(struct net_device *netdev, u32 priv_flags)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
	unsigned int flags2 = adapter->flags2;
	unsigned int i;

	flags2 &= ~IXGBE_FLAG2_RX_LEGACY;
	if (priv_flags & IXGBE_PRIV_FLAGS_LEGACY_RX)
@@ -3526,6 +3532,21 @@ static int ixgbe_set_priv_flags(struct net_device *netdev, u32 priv_flags)
	if (priv_flags & IXGBE_PRIV_FLAGS_VF_IPSEC_EN)
		flags2 |= IXGBE_FLAG2_VF_IPSEC_ENABLED;

	flags2 &= ~IXGBE_FLAG2_AUTO_DISABLE_VF;
	if (priv_flags & IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF) {
		if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
			/* Reset primary abort counter */
			for (i = 0; i < adapter->num_vfs; i++)
				adapter->vfinfo[i].primary_abort_count = 0;

			flags2 |= IXGBE_FLAG2_AUTO_DISABLE_VF;
		} else {
			e_info(probe,
			       "Cannot set private flags: Operation not supported\n");
			return -EOPNOTSUPP;
		}
	}

	if (flags2 != adapter->flags2) {
		adapter->flags2 = flags2;

+33 −6
Original line number Diff line number Diff line
@@ -5687,6 +5687,9 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
	ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);

	/* update setting rx tx for all active vfs */
	ixgbe_set_all_vfs(adapter);
}

void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
@@ -6144,11 +6147,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
		for (i = 0 ; i < adapter->num_vfs; i++)
			adapter->vfinfo[i].clear_to_send = false;

		/* ping all the active vfs to let them know we are going down */
		ixgbe_ping_all_vfs(adapter);

		/* Disable all VFTE/VFRE TX/RX */
		ixgbe_disable_tx_rx(adapter);
		/* update setting rx tx for all active vfs */
		ixgbe_set_all_vfs(adapter);
	}

	/* disable transmits in the hardware now that interrupts are off */
@@ -7613,6 +7613,27 @@ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter)
}

#ifdef CONFIG_PCI_IOV
static void ixgbe_bad_vf_abort(struct ixgbe_adapter *adapter, u32 vf)
{
	struct ixgbe_hw *hw = &adapter->hw;

	if (adapter->hw.mac.type == ixgbe_mac_82599EB &&
	    adapter->flags2 & IXGBE_FLAG2_AUTO_DISABLE_VF) {
		adapter->vfinfo[vf].primary_abort_count++;
		if (adapter->vfinfo[vf].primary_abort_count ==
		    IXGBE_PRIMARY_ABORT_LIMIT) {
			ixgbe_set_vf_link_state(adapter, vf,
						IFLA_VF_LINK_STATE_DISABLE);
			adapter->vfinfo[vf].primary_abort_count = 0;

			e_info(drv,
			       "Malicious Driver Detection event detected on PF %d VF %d MAC: %pM mdd-disable-vf=on",
			       hw->bus.func, vf,
			       adapter->vfinfo[vf].vf_mac_addresses);
		}
	}
}

static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
@@ -7644,10 +7665,12 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
			continue;
		pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
		if (status_reg != IXGBE_FAILED_READ_CFG_WORD &&
		    status_reg & PCI_STATUS_REC_MASTER_ABORT)
		    status_reg & PCI_STATUS_REC_MASTER_ABORT) {
			ixgbe_bad_vf_abort(adapter, vf);
			pcie_flr(vfdev);
		}
	}
}

static void ixgbe_spoof_check(struct ixgbe_adapter *adapter)
{
@@ -10284,6 +10307,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
	.ndo_set_vf_vlan	= ixgbe_ndo_set_vf_vlan,
	.ndo_set_vf_rate	= ixgbe_ndo_set_vf_bw,
	.ndo_set_vf_spoofchk	= ixgbe_ndo_set_vf_spoofchk,
	.ndo_set_vf_link_state	= ixgbe_ndo_set_vf_link_state,
	.ndo_set_vf_rss_query_en = ixgbe_ndo_set_vf_rss_query_en,
	.ndo_set_vf_trust	= ixgbe_ndo_set_vf_trust,
	.ndo_get_vf_config	= ixgbe_ndo_get_vf_config,
@@ -10745,6 +10769,9 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (err)
		goto err_sw_init;

	if (adapter->hw.mac.type == ixgbe_mac_82599EB)
		adapter->flags2 |= IXGBE_FLAG2_AUTO_DISABLE_VF;

	switch (adapter->hw.mac.type) {
	case ixgbe_mac_X550:
	case ixgbe_mac_X550EM_x:
+2 −0
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ enum ixgbe_pfvf_api_rev {
#define IXGBE_VF_IPSEC_ADD	0x0d
#define IXGBE_VF_IPSEC_DEL	0x0e

#define IXGBE_VF_GET_LINK_STATE 0x10 /* get vf link state */

/* length of permanent address message returned from PF */
#define IXGBE_VF_PERMADDR_MSG_LEN 4
/* word in permanent address message with the current multicast type */
+169 −38
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
	for (i = 0; i < num_vfs; i++) {
		/* enable spoof checking for all VFs */
		adapter->vfinfo[i].spoofchk_enabled = true;
		adapter->vfinfo[i].link_enable = true;

		/* We support VF RSS querying only for 82599 and x540
		 * devices at the moment. These devices share RSS
@@ -820,6 +821,57 @@ static inline void ixgbe_write_qde(struct ixgbe_adapter *adapter, u32 vf,
	}
}

/**
 * ixgbe_set_vf_rx_tx - Set VF rx tx
 * @adapter: Pointer to adapter struct
 * @vf: VF identifier
 *
 * Set or reset correct transmit and receive for vf
 **/
static void ixgbe_set_vf_rx_tx(struct ixgbe_adapter *adapter, int vf)
{
	u32 reg_cur_tx, reg_cur_rx, reg_req_tx, reg_req_rx;
	struct ixgbe_hw *hw = &adapter->hw;
	u32 reg_offset, vf_shift;

	vf_shift = vf % 32;
	reg_offset = vf / 32;

	reg_cur_tx = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
	reg_cur_rx = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));

	if (adapter->vfinfo[vf].link_enable) {
		reg_req_tx = reg_cur_tx | 1 << vf_shift;
		reg_req_rx = reg_cur_rx | 1 << vf_shift;
	} else {
		reg_req_tx = reg_cur_tx & ~(1 << vf_shift);
		reg_req_rx = reg_cur_rx & ~(1 << vf_shift);
	}

	/* The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
	 * For more info take a look at ixgbe_set_vf_lpe
	 */
	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
		struct net_device *dev = adapter->netdev;
		int pf_max_frame = dev->mtu + ETH_HLEN;

#if IS_ENABLED(CONFIG_FCOE)
		if (dev->features & NETIF_F_FCOE_MTU)
			pf_max_frame = max_t(int, pf_max_frame,
					     IXGBE_FCOE_JUMBO_FRAME_SIZE);
#endif /* CONFIG_FCOE */

		if (pf_max_frame > ETH_FRAME_LEN)
			reg_req_rx = reg_cur_rx & ~(1 << vf_shift);
	}

	/* Enable/Disable particular VF */
	if (reg_cur_tx != reg_req_tx)
		IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg_req_tx);
	if (reg_cur_rx != reg_req_rx)
		IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg_req_rx);
}

static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
{
	struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
@@ -845,11 +897,6 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
	vf_shift = vf % 32;
	reg_offset = vf / 32;

	/* enable transmit for vf */
	reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
	reg |= BIT(vf_shift);
	IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg);

	/* force drop enable for all VF Rx queues */
	reg = IXGBE_QDE_ENABLE;
	if (adapter->vfinfo[vf].pf_vlan)
@@ -857,27 +904,7 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)

	ixgbe_write_qde(adapter, vf, reg);

	/* enable receive for vf */
	reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
	reg |= BIT(vf_shift);
	/*
	 * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
	 * For more info take a look at ixgbe_set_vf_lpe
	 */
	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
		struct net_device *dev = adapter->netdev;
		int pf_max_frame = dev->mtu + ETH_HLEN;

#ifdef CONFIG_FCOE
		if (dev->features & NETIF_F_FCOE_MTU)
			pf_max_frame = max_t(int, pf_max_frame,
					     IXGBE_FCOE_JUMBO_FRAME_SIZE);

#endif /* CONFIG_FCOE */
		if (pf_max_frame > ETH_FRAME_LEN)
			reg &= ~BIT(vf_shift);
	}
	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg);
	ixgbe_set_vf_rx_tx(adapter, vf);

	/* enable VF mailbox for further messages */
	adapter->vfinfo[vf].clear_to_send = true;
@@ -1202,6 +1229,26 @@ static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter,
	return 0;
}

static int ixgbe_get_vf_link_state(struct ixgbe_adapter *adapter,
				   u32 *msgbuf, u32 vf)
{
	u32 *link_state = &msgbuf[1];

	/* verify the PF is supporting the correct API */
	switch (adapter->vfinfo[vf].vf_api) {
	case ixgbe_mbox_api_12:
	case ixgbe_mbox_api_13:
	case ixgbe_mbox_api_14:
		break;
	default:
		return -EOPNOTSUPP;
	}

	*link_state = adapter->vfinfo[vf].link_enable;

	return 0;
}

static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
{
	u32 mbx_size = IXGBE_VFMAILBOX_SIZE;
@@ -1267,6 +1314,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
	case IXGBE_VF_UPDATE_XCAST_MODE:
		retval = ixgbe_update_vf_xcast_mode(adapter, msgbuf, vf);
		break;
	case IXGBE_VF_GET_LINK_STATE:
		retval = ixgbe_get_vf_link_state(adapter, msgbuf, vf);
		break;
	case IXGBE_VF_IPSEC_ADD:
		retval = ixgbe_ipsec_vf_add_sa(adapter, msgbuf, vf);
		break;
@@ -1322,18 +1372,6 @@ void ixgbe_msg_task(struct ixgbe_adapter *adapter)
	}
}

void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;

	/* disable transmit and receive for all vfs */
	IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0);
	IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0);

	IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0);
	IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0);
}

static inline void ixgbe_ping_vf(struct ixgbe_adapter *adapter, int vf)
{
	struct ixgbe_hw *hw = &adapter->hw;
@@ -1359,6 +1397,21 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter)
	}
}

/**
 * ixgbe_set_all_vfs - update vfs queues
 * @adapter: Pointer to adapter struct
 *
 * Update setting transmit and receive queues for all vfs
 **/
void ixgbe_set_all_vfs(struct ixgbe_adapter *adapter)
{
	int i;

	for (i = 0 ; i < adapter->num_vfs; i++)
		ixgbe_set_vf_link_state(adapter, i,
					adapter->vfinfo[i].link_state);
}

int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -1656,6 +1709,84 @@ int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
	return 0;
}

/**
 * ixgbe_set_vf_link_state - Set link state
 * @adapter: Pointer to adapter struct
 * @vf: VF identifier
 * @state: required link state
 *
 * Set a link force state on/off a single vf
 **/
void ixgbe_set_vf_link_state(struct ixgbe_adapter *adapter, int vf, int state)
{
	adapter->vfinfo[vf].link_state = state;

	switch (state) {
	case IFLA_VF_LINK_STATE_AUTO:
		if (test_bit(__IXGBE_DOWN, &adapter->state))
			adapter->vfinfo[vf].link_enable = false;
		else
			adapter->vfinfo[vf].link_enable = true;
		break;
	case IFLA_VF_LINK_STATE_ENABLE:
		adapter->vfinfo[vf].link_enable = true;
		break;
	case IFLA_VF_LINK_STATE_DISABLE:
		adapter->vfinfo[vf].link_enable = false;
		break;
	}

	ixgbe_set_vf_rx_tx(adapter, vf);

	/* restart the VF */
	adapter->vfinfo[vf].clear_to_send = false;
	ixgbe_ping_vf(adapter, vf);
}

/**
 * ixgbe_ndo_set_vf_link_state - Set link state
 * @netdev: network interface device structure
 * @vf: VF identifier
 * @state: required link state
 *
 * Set the link state of a specified VF, regardless of physical link state
 **/
int ixgbe_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state)
{
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
	int ret = 0;

	if (vf < 0 || vf >= adapter->num_vfs) {
		dev_err(&adapter->pdev->dev,
			"NDO set VF link - invalid VF identifier %d\n", vf);
		return -EINVAL;
	}

	switch (state) {
	case IFLA_VF_LINK_STATE_ENABLE:
		dev_info(&adapter->pdev->dev,
			 "NDO set VF %d link state %d - not supported\n",
			vf, state);
		break;
	case IFLA_VF_LINK_STATE_DISABLE:
		dev_info(&adapter->pdev->dev,
			 "NDO set VF %d link state disable\n", vf);
		ixgbe_set_vf_link_state(adapter, vf, state);
		break;
	case IFLA_VF_LINK_STATE_AUTO:
		dev_info(&adapter->pdev->dev,
			 "NDO set VF %d link state auto\n", vf);
		ixgbe_set_vf_link_state(adapter, vf, state);
		break;
	default:
		dev_err(&adapter->pdev->dev,
			"NDO set VF %d - invalid link state %d\n", vf, state);
		ret = -EINVAL;
	}

	return ret;
}

int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf,
				  bool setting)
{
Loading