diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 91 | 
1 files changed, 62 insertions, 29 deletions
| diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 861e59a350bd..2f20980dd9a5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4079,10 +4079,13 @@ static irqreturn_t i40e_intr(int irq, void *data)  	if (icr0 & I40E_PFINT_ICR0_TIMESYNC_MASK) {  		u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0); -		if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) { -			icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; +		if (prttsyn_stat & I40E_PRTTSYN_STAT_0_EVENT0_MASK) +			schedule_work(&pf->ptp_extts0_work); + +		if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK)  			i40e_ptp_tx_hwtstamp(pf); -		} + +		icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;  	}  	/* If a critical error is pending we have no choice but to reset the @@ -4454,11 +4457,10 @@ int i40e_control_wait_tx_q(int seid, struct i40e_pf *pf, int pf_q,  }  /** - * i40e_vsi_control_tx - Start or stop a VSI's rings + * i40e_vsi_enable_tx - Start a VSI's rings   * @vsi: the VSI being configured - * @enable: start or stop the rings   **/ -static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) +static int i40e_vsi_enable_tx(struct i40e_vsi *vsi)  {  	struct i40e_pf *pf = vsi->back;  	int i, pf_q, ret = 0; @@ -4467,7 +4469,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)  	for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {  		ret = i40e_control_wait_tx_q(vsi->seid, pf,  					     pf_q, -					     false /*is xdp*/, enable); +					     false /*is xdp*/, true);  		if (ret)  			break; @@ -4476,7 +4478,7 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)  		ret = i40e_control_wait_tx_q(vsi->seid, pf,  					     pf_q + vsi->alloc_queue_pairs, -					     true /*is xdp*/, enable); +					     true /*is xdp*/, true);  		if (ret)  			break;  	} @@ -4574,32 +4576,25 @@ int i40e_control_wait_rx_q(struct i40e_pf *pf, int pf_q, bool enable)  }  /** - * i40e_vsi_control_rx - Start or stop a VSI's rings + * i40e_vsi_enable_rx - Start a VSI's rings   * @vsi: the VSI being configured - * @enable: start or stop the rings   **/ -static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable) +static int i40e_vsi_enable_rx(struct i40e_vsi *vsi)  {  	struct i40e_pf *pf = vsi->back;  	int i, pf_q, ret = 0;  	pf_q = vsi->base_queue;  	for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) { -		ret = i40e_control_wait_rx_q(pf, pf_q, enable); +		ret = i40e_control_wait_rx_q(pf, pf_q, true);  		if (ret) {  			dev_info(&pf->pdev->dev, -				 "VSI seid %d Rx ring %d %sable timeout\n", -				 vsi->seid, pf_q, (enable ? "en" : "dis")); +				 "VSI seid %d Rx ring %d enable timeout\n", +				 vsi->seid, pf_q);  			break;  		}  	} -	/* Due to HW errata, on Rx disable only, the register can indicate done -	 * before it really is. Needs 50ms to be sure -	 */ -	if (!enable) -		mdelay(50); -  	return ret;  } @@ -4612,29 +4607,47 @@ int i40e_vsi_start_rings(struct i40e_vsi *vsi)  	int ret = 0;  	/* do rx first for enable and last for disable */ -	ret = i40e_vsi_control_rx(vsi, true); +	ret = i40e_vsi_enable_rx(vsi);  	if (ret)  		return ret; -	ret = i40e_vsi_control_tx(vsi, true); +	ret = i40e_vsi_enable_tx(vsi);  	return ret;  } +#define I40E_DISABLE_TX_GAP_MSEC	50 +  /**   * i40e_vsi_stop_rings - Stop a VSI's rings   * @vsi: the VSI being configured   **/  void i40e_vsi_stop_rings(struct i40e_vsi *vsi)  { +	struct i40e_pf *pf = vsi->back; +	int pf_q, err, q_end; +  	/* When port TX is suspended, don't wait */  	if (test_bit(__I40E_PORT_SUSPENDED, vsi->back->state))  		return i40e_vsi_stop_rings_no_wait(vsi); -	/* do rx first for enable and last for disable -	 * Ignore return value, we need to shutdown whatever we can -	 */ -	i40e_vsi_control_tx(vsi, false); -	i40e_vsi_control_rx(vsi, false); +	q_end = vsi->base_queue + vsi->num_queue_pairs; +	for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++) +		i40e_pre_tx_queue_cfg(&pf->hw, (u32)pf_q, false); + +	for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++) { +		err = i40e_control_wait_rx_q(pf, pf_q, false); +		if (err) +			dev_info(&pf->pdev->dev, +				 "VSI seid %d Rx ring %d disable timeout\n", +				 vsi->seid, pf_q); +	} + +	msleep(I40E_DISABLE_TX_GAP_MSEC); +	pf_q = vsi->base_queue; +	for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++) +		wr32(&pf->hw, I40E_QTX_ENA(pf_q), 0); + +	i40e_vsi_wait_queues_disabled(vsi);  }  /** @@ -7280,6 +7293,8 @@ static int i40e_validate_mqprio_qopt(struct i40e_vsi *vsi,  	}  	if (vsi->num_queue_pairs <  	    (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i])) { +		dev_err(&vsi->back->pdev->dev, +			"Failed to create traffic channel, insufficient number of queues.\n");  		return -EINVAL;  	}  	if (sum_max_rate > i40e_get_link_speed(vsi)) { @@ -13253,7 +13268,7 @@ static const struct net_device_ops i40e_netdev_ops = {  	.ndo_validate_addr	= eth_validate_addr,  	.ndo_set_mac_address	= i40e_set_mac,  	.ndo_change_mtu		= i40e_change_mtu, -	.ndo_do_ioctl		= i40e_ioctl, +	.ndo_eth_ioctl		= i40e_ioctl,  	.ndo_tx_timeout		= i40e_tx_timeout,  	.ndo_vlan_rx_add_vid	= i40e_vlan_rx_add_vid,  	.ndo_vlan_rx_kill_vid	= i40e_vlan_rx_kill_vid, @@ -13261,6 +13276,7 @@ static const struct net_device_ops i40e_netdev_ops = {  	.ndo_poll_controller	= i40e_netpoll,  #endif  	.ndo_setup_tc		= __i40e_setup_tc, +	.ndo_select_queue	= i40e_lan_select_queue,  	.ndo_set_features	= i40e_set_features,  	.ndo_set_vf_mac		= i40e_ndo_set_vf_mac,  	.ndo_set_vf_vlan	= i40e_ndo_set_vf_port_vlan, @@ -15168,6 +15184,22 @@ err_switch_setup:  }  /** + * i40e_set_subsystem_device_id - set subsystem device id + * @hw: pointer to the hardware info + * + * Set PCI subsystem device id either from a pci_dev structure or + * a specific FW register. + **/ +static inline void i40e_set_subsystem_device_id(struct i40e_hw *hw) +{ +	struct pci_dev *pdev = ((struct i40e_pf *)hw->back)->pdev; + +	hw->subsystem_device_id = pdev->subsystem_device ? +		pdev->subsystem_device : +		(ushort)(rd32(hw, I40E_PFPCI_SUBSYSID) & USHRT_MAX); +} + +/**   * i40e_probe - Device initialization routine   * @pdev: PCI device information struct   * @ent: entry in i40e_pci_tbl @@ -15262,7 +15294,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	hw->device_id = pdev->device;  	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);  	hw->subsystem_vendor_id = pdev->subsystem_vendor; -	hw->subsystem_device_id = pdev->subsystem_device; +	i40e_set_subsystem_device_id(hw);  	hw->bus.device = PCI_SLOT(pdev->devfn);  	hw->bus.func = PCI_FUNC(pdev->devfn);  	hw->bus.bus_id = pdev->bus->number; @@ -15442,6 +15474,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (is_valid_ether_addr(hw->mac.port_addr))  		pf->hw_features |= I40E_HW_PORT_ID_VALID; +	i40e_ptp_alloc_pins(pf);  	pci_set_drvdata(pdev, pf);  	pci_save_state(pdev); |