ice: Don't reject odd values of usecs set by user
authorBrett Creeley <brett.creeley@intel.com>
Thu, 13 Feb 2020 21:31:23 +0000 (13:31 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 19 Feb 2020 19:50:41 +0000 (11:50 -0800)
Currently if a user sets an odd [tx|rx]-usecs value through ethtool,
the request is denied because the hardware is set to have an ITR
granularity of 2us. This caused poor customer experience. Fix this by
aligning to a register allowed value, which results in rounding down.
Also, print a once per ring container type message to be clear about
our intentions.

Also, change the ITR_TO_REG define to be the bitwise and of the ITR
setting and the ICE_ITR_MASK. This makes the purpose of ITR_TO_REG more
obvious.

Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_txrx.h

index b002ab4e5838cebafcc9433881d98cda0817afcf..a8876306668176343b29ab9104acd0baa0c80c1a 100644 (file)
@@ -3489,21 +3489,13 @@ ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,
                return -EINVAL;
        }
 
-       /* hardware only supports an ITR granularity of 2us */
-       if (coalesce_usecs % 2 != 0) {
-               netdev_info(vsi->netdev, "Invalid value, %s-usecs must be even\n",
-                           c_type_str);
-               return -EINVAL;
-       }
-
        if (use_adaptive_coalesce) {
                rc->itr_setting |= ICE_ITR_DYNAMIC;
        } else {
-               /* store user facing value how it was set */
+               /* save the user set usecs */
                rc->itr_setting = coalesce_usecs;
-               /* set to static and convert to value HW understands */
-               rc->target_itr =
-                       ITR_TO_REG(ITR_REG_ALIGN(rc->itr_setting));
+               /* device ITR granularity is in 2 usec increments */
+               rc->target_itr = ITR_REG_ALIGN(rc->itr_setting);
        }
 
        return 0;
@@ -3596,6 +3588,30 @@ ice_is_coalesce_param_invalid(struct net_device *netdev,
        return 0;
 }
 
+/**
+ * ice_print_if_odd_usecs - print message if user tries to set odd [tx|rx]-usecs
+ * @netdev: netdev used for print
+ * @itr_setting: previous user setting
+ * @use_adaptive_coalesce: if adaptive coalesce is enabled or being enabled
+ * @coalesce_usecs: requested value of [tx|rx]-usecs
+ * @c_type_str: either "rx" or "tx" to match user set field of [tx|rx]-usecs
+ */
+static void
+ice_print_if_odd_usecs(struct net_device *netdev, u16 itr_setting,
+                      u32 use_adaptive_coalesce, u32 coalesce_usecs,
+                      const char *c_type_str)
+{
+       if (use_adaptive_coalesce)
+               return;
+
+       itr_setting = ITR_TO_REG(itr_setting);
+
+       if (itr_setting != coalesce_usecs && (coalesce_usecs % 2))
+               netdev_info(netdev, "User set %s-usecs to %d, device only supports even values. Rounding down and attempting to set %s-usecs to %d\n",
+                           c_type_str, coalesce_usecs, c_type_str,
+                           ITR_REG_ALIGN(coalesce_usecs));
+}
+
 /**
  * __ice_set_coalesce - set ITR/INTRL values for the device
  * @netdev: pointer to the netdev associated with this query
@@ -3616,8 +3632,19 @@ __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec,
                return -EINVAL;
 
        if (q_num < 0) {
+               struct ice_q_vector *q_vector = vsi->q_vectors[0];
                int v_idx;
 
+               if (q_vector) {
+                       ice_print_if_odd_usecs(netdev, q_vector->rx.itr_setting,
+                                              ec->use_adaptive_rx_coalesce,
+                                              ec->rx_coalesce_usecs, "rx");
+
+                       ice_print_if_odd_usecs(netdev, q_vector->tx.itr_setting,
+                                              ec->use_adaptive_tx_coalesce,
+                                              ec->tx_coalesce_usecs, "tx");
+               }
+
                ice_for_each_q_vector(vsi, v_idx) {
                        /* In some cases if DCB is configured the num_[rx|tx]q
                         * can be less than vsi->num_q_vectors. This check
index 14a1bf445889fc4f4f282449bb50938db253cb71..7ee00a1286634a5eed591f5d22c5a29ebbc79cf3 100644 (file)
@@ -222,7 +222,7 @@ enum ice_rx_dtype {
 #define ICE_ITR_GRAN_S         1       /* ITR granularity is always 2us */
 #define ICE_ITR_GRAN_US                BIT(ICE_ITR_GRAN_S)
 #define ICE_ITR_MASK           0x1FFE  /* ITR register value alignment mask */
-#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~ICE_ITR_MASK)
+#define ITR_REG_ALIGN(setting) ((setting) & ICE_ITR_MASK)
 
 #define ICE_ITR_ADAPTIVE_MIN_INC       0x0002
 #define ICE_ITR_ADAPTIVE_MIN_USECS     0x0002