diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_lib.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_lib.c | 194 | 
1 files changed, 68 insertions, 126 deletions
| diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index f559e60992fa..2405e5ed9128 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -447,6 +447,7 @@ static void ice_vsi_free(struct ice_vsi *vsi)  	ice_vsi_free_stats(vsi);  	ice_vsi_free_arrays(vsi); +	mutex_destroy(&vsi->xdp_state_lock);  	mutex_unlock(&pf->sw_mutex);  	devm_kfree(dev, vsi);  } @@ -626,6 +627,8 @@ static struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)  	pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi,  					 pf->next_vsi); +	mutex_init(&vsi->xdp_state_lock); +  unlock_pf:  	mutex_unlock(&pf->sw_mutex);  	return vsi; @@ -2286,9 +2289,6 @@ static int ice_vsi_cfg_def(struct ice_vsi *vsi)  		ice_vsi_map_rings_to_vectors(vsi); -		/* Associate q_vector rings to napi */ -		ice_vsi_set_napi_queues(vsi); -  		vsi->stat_offsets_loaded = false;  		/* ICE_VSI_CTRL does not need RSS so skip RSS processing */ @@ -2413,20 +2413,13 @@ void ice_vsi_decfg(struct ice_vsi *vsi)  	struct ice_pf *pf = vsi->back;  	int err; -	/* The Rx rule will only exist to remove if the LLDP FW -	 * engine is currently stopped -	 */ -	if (!ice_is_safe_mode(pf) && vsi->type == ICE_VSI_PF && -	    !test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) -		ice_cfg_sw_lldp(vsi, false, false); -  	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);  	err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);  	if (err)  		dev_err(ice_pf_to_dev(pf), "Failed to remove RDMA scheduler config for VSI %u, err %d\n",  			vsi->vsi_num, err); -	if (ice_is_xdp_ena_vsi(vsi)) +	if (vsi->xdp_rings)  		/* return value check can be skipped here, it always returns  		 * 0 if reset is in progress  		 */ @@ -2528,7 +2521,7 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi)  		for (q = 0; q < q_vector->num_ring_tx; q++) {  			ice_write_itr(&q_vector->tx, 0);  			wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0); -			if (ice_is_xdp_ena_vsi(vsi)) { +			if (vsi->xdp_rings) {  				u32 xdp_txq = txq + vsi->num_xdp_txq;  				wr32(hw, QINT_TQCTL(vsi->txq_map[xdp_txq]), 0); @@ -2628,6 +2621,7 @@ void ice_vsi_close(struct ice_vsi *vsi)  	if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state))  		ice_down(vsi); +	ice_vsi_clear_napi_queues(vsi);  	ice_vsi_free_irq(vsi);  	ice_vsi_free_tx_rings(vsi);  	ice_vsi_free_rx_rings(vsi); @@ -2671,8 +2665,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked)   */  void ice_dis_vsi(struct ice_vsi *vsi, bool locked)  { -	if (test_bit(ICE_VSI_DOWN, vsi->state)) -		return; +	bool already_down = test_bit(ICE_VSI_DOWN, vsi->state);  	set_bit(ICE_VSI_NEEDS_RESTART, vsi->state); @@ -2680,134 +2673,70 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)  		if (netif_running(vsi->netdev)) {  			if (!locked)  				rtnl_lock(); - -			ice_vsi_close(vsi); +			already_down = test_bit(ICE_VSI_DOWN, vsi->state); +			if (!already_down) +				ice_vsi_close(vsi);  			if (!locked)  				rtnl_unlock(); -		} else { +		} else if (!already_down) {  			ice_vsi_close(vsi);  		} -	} else if (vsi->type == ICE_VSI_CTRL) { +	} else if (vsi->type == ICE_VSI_CTRL && !already_down) {  		ice_vsi_close(vsi);  	}  }  /** - * __ice_queue_set_napi - Set the napi instance for the queue - * @dev: device to which NAPI and queue belong - * @queue_index: Index of queue - * @type: queue type as RX or TX - * @napi: NAPI context - * @locked: is the rtnl_lock already held - * - * Set the napi instance for the queue. Caller indicates the lock status. - */ -static void -__ice_queue_set_napi(struct net_device *dev, unsigned int queue_index, -		     enum netdev_queue_type type, struct napi_struct *napi, -		     bool locked) -{ -	if (!locked) -		rtnl_lock(); -	netif_queue_set_napi(dev, queue_index, type, napi); -	if (!locked) -		rtnl_unlock(); -} - -/** - * ice_queue_set_napi - Set the napi instance for the queue - * @vsi: VSI being configured - * @queue_index: Index of queue - * @type: queue type as RX or TX - * @napi: NAPI context + * ice_vsi_set_napi_queues - associate netdev queues with napi + * @vsi: VSI pointer   * - * Set the napi instance for the queue. The rtnl lock state is derived from the - * execution path. + * Associate queue[s] with napi for all vectors. + * The caller must hold rtnl_lock.   */ -void -ice_queue_set_napi(struct ice_vsi *vsi, unsigned int queue_index, -		   enum netdev_queue_type type, struct napi_struct *napi) +void ice_vsi_set_napi_queues(struct ice_vsi *vsi)  { -	struct ice_pf *pf = vsi->back; +	struct net_device *netdev = vsi->netdev; +	int q_idx, v_idx; -	if (!vsi->netdev) +	if (!netdev)  		return; -	if (current_work() == &pf->serv_task || -	    test_bit(ICE_PREPARED_FOR_RESET, pf->state) || -	    test_bit(ICE_DOWN, pf->state) || -	    test_bit(ICE_SUSPENDED, pf->state)) -		__ice_queue_set_napi(vsi->netdev, queue_index, type, napi, -				     false); -	else -		__ice_queue_set_napi(vsi->netdev, queue_index, type, napi, -				     true); -} - -/** - * __ice_q_vector_set_napi_queues - Map queue[s] associated with the napi - * @q_vector: q_vector pointer - * @locked: is the rtnl_lock already held - * - * Associate the q_vector napi with all the queue[s] on the vector. - * Caller indicates the lock status. - */ -void __ice_q_vector_set_napi_queues(struct ice_q_vector *q_vector, bool locked) -{ -	struct ice_rx_ring *rx_ring; -	struct ice_tx_ring *tx_ring; - -	ice_for_each_rx_ring(rx_ring, q_vector->rx) -		__ice_queue_set_napi(q_vector->vsi->netdev, rx_ring->q_index, -				     NETDEV_QUEUE_TYPE_RX, &q_vector->napi, -				     locked); +	ice_for_each_rxq(vsi, q_idx) +		netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_RX, +				     &vsi->rx_rings[q_idx]->q_vector->napi); -	ice_for_each_tx_ring(tx_ring, q_vector->tx) -		__ice_queue_set_napi(q_vector->vsi->netdev, tx_ring->q_index, -				     NETDEV_QUEUE_TYPE_TX, &q_vector->napi, -				     locked); +	ice_for_each_txq(vsi, q_idx) +		netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_TX, +				     &vsi->tx_rings[q_idx]->q_vector->napi);  	/* Also set the interrupt number for the NAPI */ -	netif_napi_set_irq(&q_vector->napi, q_vector->irq.virq); -} - -/** - * ice_q_vector_set_napi_queues - Map queue[s] associated with the napi - * @q_vector: q_vector pointer - * - * Associate the q_vector napi with all the queue[s] on the vector - */ -void ice_q_vector_set_napi_queues(struct ice_q_vector *q_vector) -{ -	struct ice_rx_ring *rx_ring; -	struct ice_tx_ring *tx_ring; - -	ice_for_each_rx_ring(rx_ring, q_vector->rx) -		ice_queue_set_napi(q_vector->vsi, rx_ring->q_index, -				   NETDEV_QUEUE_TYPE_RX, &q_vector->napi); +	ice_for_each_q_vector(vsi, v_idx) { +		struct ice_q_vector *q_vector = vsi->q_vectors[v_idx]; -	ice_for_each_tx_ring(tx_ring, q_vector->tx) -		ice_queue_set_napi(q_vector->vsi, tx_ring->q_index, -				   NETDEV_QUEUE_TYPE_TX, &q_vector->napi); -	/* Also set the interrupt number for the NAPI */ -	netif_napi_set_irq(&q_vector->napi, q_vector->irq.virq); +		netif_napi_set_irq(&q_vector->napi, q_vector->irq.virq); +	}  }  /** - * ice_vsi_set_napi_queues + * ice_vsi_clear_napi_queues - dissociate netdev queues from napi   * @vsi: VSI pointer   * - * Associate queue[s] with napi for all vectors + * Clear the association between all VSI queues queue[s] and napi. + * The caller must hold rtnl_lock.   */ -void ice_vsi_set_napi_queues(struct ice_vsi *vsi) +void ice_vsi_clear_napi_queues(struct ice_vsi *vsi)  { -	int i; +	struct net_device *netdev = vsi->netdev; +	int q_idx; -	if (!vsi->netdev) +	if (!netdev)  		return; -	ice_for_each_q_vector(vsi, i) -		ice_q_vector_set_napi_queues(vsi->q_vectors[i]); +	ice_for_each_txq(vsi, q_idx) +		netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_TX, NULL); + +	ice_for_each_rxq(vsi, q_idx) +		netif_queue_set_napi(netdev, q_idx, NETDEV_QUEUE_TYPE_RX, NULL);  }  /** @@ -2828,6 +2757,14 @@ int ice_vsi_release(struct ice_vsi *vsi)  		ice_rss_clean(vsi);  	ice_vsi_close(vsi); + +	/* The Rx rule will only exist to remove if the LLDP FW +	 * engine is currently stopped +	 */ +	if (!ice_is_safe_mode(pf) && vsi->type == ICE_VSI_PF && +	    !test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) +		ice_cfg_sw_lldp(vsi, false, false); +  	ice_vsi_decfg(vsi);  	/* retain SW VSI data structure since it is needed to unregister and @@ -3039,19 +2976,23 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)  	if (WARN_ON(vsi->type == ICE_VSI_VF && !vsi->vf))  		return -EINVAL; +	mutex_lock(&vsi->xdp_state_lock); +  	ret = ice_vsi_realloc_stat_arrays(vsi);  	if (ret) -		goto err_vsi_cfg; +		goto unlock;  	ice_vsi_decfg(vsi);  	ret = ice_vsi_cfg_def(vsi);  	if (ret) -		goto err_vsi_cfg; +		goto unlock;  	coalesce = kcalloc(vsi->num_q_vectors,  			   sizeof(struct ice_coalesce_stored), GFP_KERNEL); -	if (!coalesce) -		return -ENOMEM; +	if (!coalesce) { +		ret = -ENOMEM; +		goto decfg; +	}  	prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce); @@ -3059,22 +3000,23 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)  	if (ret) {  		if (vsi_flags & ICE_VSI_FLAG_INIT) {  			ret = -EIO; -			goto err_vsi_cfg_tc_lan; +			goto free_coalesce;  		} -		kfree(coalesce); -		return ice_schedule_reset(pf, ICE_RESET_PFR); +		ret = ice_schedule_reset(pf, ICE_RESET_PFR); +		goto free_coalesce;  	}  	ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors); -	kfree(coalesce); - -	return 0; +	clear_bit(ICE_VSI_REBUILD_PENDING, vsi->state); -err_vsi_cfg_tc_lan: -	ice_vsi_decfg(vsi); +free_coalesce:  	kfree(coalesce); -err_vsi_cfg: +decfg: +	if (ret) +		ice_vsi_decfg(vsi); +unlock: +	mutex_unlock(&vsi->xdp_state_lock);  	return ret;  } | 
