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


Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates 2020-01-09

This series contains fixes to e1000e, igb, ixgbe, ixgbevf, i40e and iavf
drivers.

Brett fixes the validation of the virtchnl queue select bitmaps by
comparing the bitmaps against BIT(I40E_MAX_VF_QUEUES).

Radoslaw removes the limitation of only 10 filter entries for a VF and
allows use of all free RAR entries for the forwarding database, if
needed.

Cambda Zhu fixes the calculation of queue when restoring flow director
filters after resetting the adapter for ixgbe.

Manfred Rudigier fixes the SGMIISFP module discovery for 100FX/LX
modules for igb.

Stefan Assmann fixes iavf where during a VF reset event, MAC filters
were not altered, which could lead to a stale filter when an
administratively set MAC address is forced by the PF.

Adam adds the missing code to set the PHY access flag on X722 devices,
which supports accessing PHY registers with the admin queue command.

Revert a previous commit for e1000e to use "delayed work" which was
causing connections to reset unexpectedly and possible driver crashes.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e21dba7a d5ad7a6a
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -185,13 +185,12 @@ struct e1000_phy_regs {

/* board specific private data structure */
struct e1000_adapter {
	struct timer_list watchdog_timer;
	struct timer_list phy_info_timer;
	struct timer_list blink_timer;

	struct work_struct reset_task;
	struct delayed_work watchdog_task;

	struct workqueue_struct *e1000_workqueue;
	struct work_struct watchdog_task;

	const struct e1000_info *ei;

+25 −29
Original line number Diff line number Diff line
@@ -1780,8 +1780,7 @@ static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data)
		}
		/* guard against interrupt when we're going down */
		if (!test_bit(__E1000_DOWN, &adapter->state))
			mod_delayed_work(adapter->e1000_workqueue,
					 &adapter->watchdog_task, HZ);
			mod_timer(&adapter->watchdog_timer, jiffies + 1);
	}

	/* Reset on uncorrectable ECC error */
@@ -1861,8 +1860,7 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data)
		}
		/* guard against interrupt when we're going down */
		if (!test_bit(__E1000_DOWN, &adapter->state))
			mod_delayed_work(adapter->e1000_workqueue,
					 &adapter->watchdog_task, HZ);
			mod_timer(&adapter->watchdog_timer, jiffies + 1);
	}

	/* Reset on uncorrectable ECC error */
@@ -1907,8 +1905,7 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
		hw->mac.get_link_status = true;
		/* guard against interrupt when we're going down */
		if (!test_bit(__E1000_DOWN, &adapter->state))
			mod_delayed_work(adapter->e1000_workqueue,
					 &adapter->watchdog_task, HZ);
			mod_timer(&adapter->watchdog_timer, jiffies + 1);
	}

	if (!test_bit(__E1000_DOWN, &adapter->state))
@@ -4284,6 +4281,7 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)

	napi_synchronize(&adapter->napi);

	del_timer_sync(&adapter->watchdog_timer);
	del_timer_sync(&adapter->phy_info_timer);

	spin_lock(&adapter->stats64_lock);
@@ -5155,11 +5153,25 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
	}
}

/**
 * e1000_watchdog - Timer Call-back
 * @data: pointer to adapter cast into an unsigned long
 **/
static void e1000_watchdog(struct timer_list *t)
{
	struct e1000_adapter *adapter = from_timer(adapter, t, watchdog_timer);

	/* Do the rest outside of interrupt context */
	schedule_work(&adapter->watchdog_task);

	/* TODO: make this use queue_delayed_work() */
}

static void e1000_watchdog_task(struct work_struct *work)
{
	struct e1000_adapter *adapter = container_of(work,
						     struct e1000_adapter,
						     watchdog_task.work);
						     watchdog_task);
	struct net_device *netdev = adapter->netdev;
	struct e1000_mac_info *mac = &adapter->hw.mac;
	struct e1000_phy_info *phy = &adapter->hw.phy;
@@ -5407,9 +5419,8 @@ link_up:

	/* Reset the timer */
	if (!test_bit(__E1000_DOWN, &adapter->state))
		queue_delayed_work(adapter->e1000_workqueue,
				   &adapter->watchdog_task,
				   round_jiffies(2 * HZ));
		mod_timer(&adapter->watchdog_timer,
			  round_jiffies(jiffies + 2 * HZ));
}

#define E1000_TX_FLAGS_CSUM		0x00000001
@@ -7449,21 +7460,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
		goto err_eeprom;
	}

	adapter->e1000_workqueue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0,
						   e1000e_driver_name);

	if (!adapter->e1000_workqueue) {
		err = -ENOMEM;
		goto err_workqueue;
	}

	INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog_task);
	queue_delayed_work(adapter->e1000_workqueue, &adapter->watchdog_task,
			   0);

	timer_setup(&adapter->watchdog_timer, e1000_watchdog, 0);
	timer_setup(&adapter->phy_info_timer, e1000_update_phy_info, 0);

	INIT_WORK(&adapter->reset_task, e1000_reset_task);
	INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
	INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
	INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
	INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);
@@ -7557,9 +7558,6 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	return 0;

err_register:
	flush_workqueue(adapter->e1000_workqueue);
	destroy_workqueue(adapter->e1000_workqueue);
err_workqueue:
	if (!(adapter->flags & FLAG_HAS_AMT))
		e1000e_release_hw_control(adapter);
err_eeprom:
@@ -7604,17 +7602,15 @@ static void e1000_remove(struct pci_dev *pdev)
	 * from being rescheduled.
	 */
	set_bit(__E1000_DOWN, &adapter->state);
	del_timer_sync(&adapter->watchdog_timer);
	del_timer_sync(&adapter->phy_info_timer);

	cancel_work_sync(&adapter->reset_task);
	cancel_work_sync(&adapter->watchdog_task);
	cancel_work_sync(&adapter->downshift_task);
	cancel_work_sync(&adapter->update_phy_task);
	cancel_work_sync(&adapter->print_hang_task);

	cancel_delayed_work(&adapter->watchdog_task);
	flush_workqueue(adapter->e1000_workqueue);
	destroy_workqueue(adapter->e1000_workqueue);

	if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) {
		cancel_work_sync(&adapter->tx_hwtstamp_work);
		if (adapter->tx_hwtstamp_skb) {
+5 −0
Original line number Diff line number Diff line
@@ -536,6 +536,11 @@ static void i40e_set_hw_flags(struct i40e_hw *hw)
		    (aq->api_maj_ver == 1 &&
		     aq->api_min_ver >= I40E_MINOR_VER_FW_LLDP_STOPPABLE_X722))
			hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;

		if (aq->api_maj_ver > 1 ||
		    (aq->api_maj_ver == 1 &&
		     aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_X722))
			hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
		/* fall through */
	default:
		break;
+18 −4
Original line number Diff line number Diff line
@@ -2321,6 +2321,22 @@ static int i40e_ctrl_vf_rx_rings(struct i40e_vsi *vsi, unsigned long q_map,
	return ret;
}

/**
 * i40e_vc_validate_vqs_bitmaps - validate Rx/Tx queue bitmaps from VIRTHCHNL
 * @vqs: virtchnl_queue_select structure containing bitmaps to validate
 *
 * Returns true if validation was successful, else false.
 */
static bool i40e_vc_validate_vqs_bitmaps(struct virtchnl_queue_select *vqs)
{
	if ((!vqs->rx_queues && !vqs->tx_queues) ||
	    vqs->rx_queues >= BIT(I40E_MAX_VF_QUEUES) ||
	    vqs->tx_queues >= BIT(I40E_MAX_VF_QUEUES))
		return false;

	return true;
}

/**
 * i40e_vc_enable_queues_msg
 * @vf: pointer to the VF info
@@ -2346,7 +2362,7 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg)
		goto error_param;
	}

	if ((0 == vqs->rx_queues) && (0 == vqs->tx_queues)) {
	if (i40e_vc_validate_vqs_bitmaps(vqs)) {
		aq_ret = I40E_ERR_PARAM;
		goto error_param;
	}
@@ -2408,9 +2424,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg)
		goto error_param;
	}

	if ((vqs->rx_queues == 0 && vqs->tx_queues == 0) ||
	    vqs->rx_queues > I40E_MAX_VF_QUEUES ||
	    vqs->tx_queues > I40E_MAX_VF_QUEUES) {
	if (i40e_vc_validate_vqs_bitmaps(vqs)) {
		aq_ret = I40E_ERR_PARAM;
		goto error_param;
	}
+2 −0
Original line number Diff line number Diff line
@@ -415,4 +415,6 @@ void iavf_enable_channels(struct iavf_adapter *adapter);
void iavf_disable_channels(struct iavf_adapter *adapter);
void iavf_add_cloud_filter(struct iavf_adapter *adapter);
void iavf_del_cloud_filter(struct iavf_adapter *adapter);
struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
					const u8 *macaddr);
#endif /* _IAVF_H_ */
Loading