]> git.itanic.dy.fi Git - linux-stable/blobdiff - drivers/net/ethernet/intel/i40e/i40e_main.c
i40e: Fix set max_tx_rate when it is lower than 1 Mbps
[linux-stable] / drivers / net / ethernet / intel / i40e / i40e_main.c
index aa786fd5595113c521c6f1b500ed94b4f0d80dd1..57e27f2024d38a27ebd41355c8a0cedacc10d5f5 100644 (file)
@@ -384,7 +384,9 @@ static void i40e_tx_timeout(struct net_device *netdev, unsigned int txqueue)
                set_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state);
                break;
        default:
-               netdev_err(netdev, "tx_timeout recovery unsuccessful\n");
+               netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in non-recoverable state.\n");
+               set_bit(__I40E_DOWN_REQUESTED, pf->state);
+               set_bit(__I40E_VSI_DOWN_REQUESTED, vsi->state);
                break;
        }
 
@@ -1925,11 +1927,15 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
                 * non-zero req_queue_pairs says that user requested a new
                 * queue count via ethtool's set_channels, so use this
                 * value for queues distribution across traffic classes
+                * We need at least one queue pair for the interface
+                * to be usable as we see in else statement.
                 */
                if (vsi->req_queue_pairs > 0)
                        vsi->num_queue_pairs = vsi->req_queue_pairs;
                else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
                        vsi->num_queue_pairs = pf->num_lan_msix;
+               else
+                       vsi->num_queue_pairs = 1;
        }
 
        /* Number of queues per enabled TC */
@@ -5333,7 +5339,7 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
        u8 num_tc = 0;
        struct i40e_dcbx_config *dcbcfg = &hw->local_dcbx_config;
 
-       if (pf->flags & I40E_FLAG_TC_MQPRIO)
+       if (i40e_is_tc_mqprio_enabled(pf))
                return pf->vsi[pf->lan_vsi]->mqprio_qopt.qopt.num_tc;
 
        /* If neither MQPRIO nor DCB is enabled, then always use single TC */
@@ -5365,7 +5371,7 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
  **/
 static u8 i40e_pf_get_tc_map(struct i40e_pf *pf)
 {
-       if (pf->flags & I40E_FLAG_TC_MQPRIO)
+       if (i40e_is_tc_mqprio_enabled(pf))
                return i40e_mqprio_get_enabled_tc(pf);
 
        /* If neither MQPRIO nor DCB is enabled for this PF then just return
@@ -5462,7 +5468,7 @@ static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc,
        int i;
 
        /* There is no need to reset BW when mqprio mode is on.  */
-       if (pf->flags & I40E_FLAG_TC_MQPRIO)
+       if (i40e_is_tc_mqprio_enabled(pf))
                return 0;
        if (!vsi->mqprio_qopt.qopt.hw && !(pf->flags & I40E_FLAG_DCB_ENABLED)) {
                ret = i40e_set_bw_limit(vsi, vsi->seid, 0);
@@ -5534,7 +5540,7 @@ static void i40e_vsi_config_netdev_tc(struct i40e_vsi *vsi, u8 enabled_tc)
                                        vsi->tc_config.tc_info[i].qoffset);
        }
 
-       if (pf->flags & I40E_FLAG_TC_MQPRIO)
+       if (i40e_is_tc_mqprio_enabled(pf))
                return;
 
        /* Assign UP2TC map for the VSI */
@@ -5695,7 +5701,7 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc)
        ctxt.vf_num = 0;
        ctxt.uplink_seid = vsi->uplink_seid;
        ctxt.info = vsi->info;
-       if (vsi->back->flags & I40E_FLAG_TC_MQPRIO) {
+       if (i40e_is_tc_mqprio_enabled(pf)) {
                ret = i40e_vsi_setup_queue_map_mqprio(vsi, &ctxt, enabled_tc);
                if (ret)
                        goto out;
@@ -5779,6 +5785,26 @@ static int i40e_get_link_speed(struct i40e_vsi *vsi)
        }
 }
 
+/**
+ * i40e_bw_bytes_to_mbits - Convert max_tx_rate from bytes to mbits
+ * @vsi: Pointer to vsi structure
+ * @max_tx_rate: max TX rate in bytes to be converted into Mbits
+ *
+ * Helper function to convert units before send to set BW limit
+ **/
+static u64 i40e_bw_bytes_to_mbits(struct i40e_vsi *vsi, u64 max_tx_rate)
+{
+       if (max_tx_rate < I40E_BW_MBPS_DIVISOR) {
+               dev_warn(&vsi->back->pdev->dev,
+                        "Setting max tx rate to minimum usable value of 50Mbps.\n");
+               max_tx_rate = I40E_BW_CREDIT_DIVISOR;
+       } else {
+               do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
+       }
+
+       return max_tx_rate;
+}
+
 /**
  * i40e_set_bw_limit - setup BW limit for Tx traffic based on max_tx_rate
  * @vsi: VSI to be configured
@@ -5801,10 +5827,10 @@ int i40e_set_bw_limit(struct i40e_vsi *vsi, u16 seid, u64 max_tx_rate)
                        max_tx_rate, seid);
                return -EINVAL;
        }
-       if (max_tx_rate && max_tx_rate < 50) {
+       if (max_tx_rate && max_tx_rate < I40E_BW_CREDIT_DIVISOR) {
                dev_warn(&pf->pdev->dev,
                         "Setting max tx rate to minimum usable value of 50Mbps.\n");
-               max_tx_rate = 50;
+               max_tx_rate = I40E_BW_CREDIT_DIVISOR;
        }
 
        /* Tx rate credits are in values of 50Mbps, 0 is disabled */
@@ -6419,7 +6445,7 @@ int i40e_create_queue_channel(struct i40e_vsi *vsi,
                pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
 
                if (vsi->type == I40E_VSI_MAIN) {
-                       if (pf->flags & I40E_FLAG_TC_MQPRIO)
+                       if (i40e_is_tc_mqprio_enabled(pf))
                                i40e_do_reset(pf, I40E_PF_RESET_FLAG, true);
                        else
                                i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG);
@@ -6530,6 +6556,9 @@ static int i40e_configure_queue_channels(struct i40e_vsi *vsi)
                        vsi->tc_seid_map[i] = ch->seid;
                }
        }
+
+       /* reset to reconfigure TX queue contexts */
+       i40e_do_reset(vsi->back, I40E_PF_RESET_FLAG, true);
        return ret;
 
 err_free:
@@ -7813,7 +7842,7 @@ static void *i40e_fwd_add(struct net_device *netdev, struct net_device *vdev)
                netdev_info(netdev, "Macvlans are not supported when DCB is enabled\n");
                return ERR_PTR(-EINVAL);
        }
-       if ((pf->flags & I40E_FLAG_TC_MQPRIO)) {
+       if (i40e_is_tc_mqprio_enabled(pf)) {
                netdev_info(netdev, "Macvlans are not supported when HW TC offload is on\n");
                return ERR_PTR(-EINVAL);
        }
@@ -8066,7 +8095,7 @@ static int i40e_setup_tc(struct net_device *netdev, void *type_data)
        /* Quiesce VSI queues */
        i40e_quiesce_vsi(vsi);
 
-       if (!hw && !(pf->flags & I40E_FLAG_TC_MQPRIO))
+       if (!hw && !i40e_is_tc_mqprio_enabled(pf))
                i40e_remove_queue_channels(vsi);
 
        /* Configure VSI for enabled TCs */
@@ -8090,11 +8119,11 @@ static int i40e_setup_tc(struct net_device *netdev, void *type_data)
                 "Setup channel (id:%u) utilizing num_queues %d\n",
                 vsi->seid, vsi->tc_config.tc_info[0].qcount);
 
-       if (pf->flags & I40E_FLAG_TC_MQPRIO) {
+       if (i40e_is_tc_mqprio_enabled(pf)) {
                if (vsi->mqprio_qopt.max_rate[0]) {
-                       u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
+                       u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
+                                                 vsi->mqprio_qopt.max_rate[0]);
 
-                       do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
                        ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
                        if (!ret) {
                                u64 credits = max_tx_rate;
@@ -10650,7 +10679,7 @@ static int i40e_reset(struct i40e_pf *pf)
  **/
 static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 {
-       int old_recovery_mode_bit = test_bit(__I40E_RECOVERY_MODE, pf->state);
+       const bool is_recovery_mode_reported = i40e_check_recovery_mode(pf);
        struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
        struct i40e_hw *hw = &pf->hw;
        i40e_status ret;
@@ -10658,13 +10687,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
        int v;
 
        if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
-           i40e_check_recovery_mode(pf)) {
+           is_recovery_mode_reported)
                i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev);
-       }
 
        if (test_bit(__I40E_DOWN, pf->state) &&
-           !test_bit(__I40E_RECOVERY_MODE, pf->state) &&
-           !old_recovery_mode_bit)
+           !test_bit(__I40E_RECOVERY_MODE, pf->state))
                goto clear_recovery;
        dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
 
@@ -10691,13 +10718,12 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
         * accordingly with regard to resources initialization
         * and deinitialization
         */
-       if (test_bit(__I40E_RECOVERY_MODE, pf->state) ||
-           old_recovery_mode_bit) {
+       if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
                if (i40e_get_capabilities(pf,
                                          i40e_aqc_opc_list_func_capabilities))
                        goto end_unlock;
 
-               if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
+               if (is_recovery_mode_reported) {
                        /* we're staying in recovery mode so we'll reinitialize
                         * misc vector here
                         */
@@ -10747,7 +10773,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
         * unless I40E_FLAG_TC_MQPRIO was enabled or DCB
         * is not supported with new link speed
         */
-       if (pf->flags & I40E_FLAG_TC_MQPRIO) {
+       if (i40e_is_tc_mqprio_enabled(pf)) {
                i40e_aq_set_dcb_parameters(hw, false, NULL);
        } else {
                if (I40E_IS_X710TL_DEVICE(hw->device_id) &&
@@ -10842,10 +10868,10 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
        }
 
        if (vsi->mqprio_qopt.max_rate[0]) {
-               u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
+               u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
+                                                 vsi->mqprio_qopt.max_rate[0]);
                u64 credits = 0;
 
-               do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
                ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
                if (ret)
                        goto end_unlock;