]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
igc: Add initial LTR support
authorSasha Neftin <sasha.neftin@intel.com>
Tue, 2 Jun 2020 07:50:47 +0000 (10:50 +0300)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 30 Jun 2020 01:21:09 +0000 (18:21 -0700)
The LTR message on the PCIe inform the requested latency
on which the PCIe must become active to the downstream
PCIe port of the system.
This patch provide recommended LTR parameters by i225
specification.

Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igc/igc_defines.h
drivers/net/ethernet/intel/igc/igc_i225.c
drivers/net/ethernet/intel/igc/igc_i225.h
drivers/net/ethernet/intel/igc/igc_mac.c
drivers/net/ethernet/intel/igc/igc_regs.h

index ee7fa1c062a0ed77d9ab156988cf76f005c7968a..ed0e560daaae53e1be4e37b99078fc64c6c6b46c 100644 (file)
 #define IGC_EEER_LPI_FC                        0x00040000 /* EEER Ena on Flow Cntrl */
 #define IGC_EEE_SU_LPI_CLK_STP         0x00800000 /* EEE LPI Clock Stop */
 
+/* LTR defines */
+#define IGC_LTRC_EEEMS_EN              0x00000020 /* Enable EEE LTR max send */
+#define IGC_RXPBS_SIZE_I225_MASK       0x0000003F /* Rx packet buffer size */
+#define IGC_TW_SYSTEM_1000_MASK                0x000000FF
+/* Minimum time for 100BASE-T where no data will be transmit following move out
+ * of EEE LPI Tx state
+ */
+#define IGC_TW_SYSTEM_100_MASK         0x0000FF00
+#define IGC_TW_SYSTEM_100_SHIFT                8
+#define IGC_DMACR_DMAC_EN              0x80000000 /* Enable DMA Coalescing */
+#define IGC_DMACR_DMACTHR_MASK         0x00FF0000
+#define IGC_DMACR_DMACTHR_SHIFT                16
+/* Reg val to set scale to 1024 nsec */
+#define IGC_LTRMINV_SCALE_1024         2
+/* Reg val to set scale to 32768 nsec */
+#define IGC_LTRMINV_SCALE_32768                3
+/* Reg val to set scale to 1024 nsec */
+#define IGC_LTRMAXV_SCALE_1024         2
+/* Reg val to set scale to 32768 nsec */
+#define IGC_LTRMAXV_SCALE_32768                3
+#define IGC_LTRMINV_LTRV_MASK          0x000003FF /* LTR minimum value */
+#define IGC_LTRMAXV_LTRV_MASK          0x000003FF /* LTR maximum value */
+#define IGC_LTRMINV_LSNP_REQ           0x00008000 /* LTR Snoop Requirement */
+#define IGC_LTRMINV_SCALE_SHIFT                10
+#define IGC_LTRMAXV_LSNP_REQ           0x00008000 /* LTR Snoop Requirement */
+#define IGC_LTRMAXV_SCALE_SHIFT                10
+
 #endif /* _IGC_DEFINES_H_ */
index 3a4e982edb67255988ce810e8a41cfac44801525..8b67d9b49a83a61d76b3fcf44c65b46f33f5dd4f 100644 (file)
@@ -544,3 +544,103 @@ s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G,
 
        return IGC_SUCCESS;
 }
+
+/* igc_set_ltr_i225 - Set Latency Tolerance Reporting thresholds
+ * @hw: pointer to the HW structure
+ * @link: bool indicating link status
+ *
+ * Set the LTR thresholds based on the link speed (Mbps), EEE, and DMAC
+ * settings, otherwise specify that there is no LTR requirement.
+ */
+s32 igc_set_ltr_i225(struct igc_hw *hw, bool link)
+{
+       u32 tw_system, ltrc, ltrv, ltr_min, ltr_max, scale_min, scale_max;
+       u16 speed, duplex;
+       s32 size;
+
+       /* If we do not have link, LTR thresholds are zero. */
+       if (link) {
+               hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
+
+               /* Check if using copper interface with EEE enabled or if the
+                * link speed is 10 Mbps.
+                */
+               if (hw->dev_spec._base.eee_enable &&
+                   speed != SPEED_10) {
+                       /* EEE enabled, so send LTRMAX threshold. */
+                       ltrc = rd32(IGC_LTRC) |
+                              IGC_LTRC_EEEMS_EN;
+                       wr32(IGC_LTRC, ltrc);
+
+                       /* Calculate tw_system (nsec). */
+                       if (speed == SPEED_100) {
+                               tw_system = ((rd32(IGC_EEE_SU) &
+                                            IGC_TW_SYSTEM_100_MASK) >>
+                                            IGC_TW_SYSTEM_100_SHIFT) * 500;
+                       } else {
+                               tw_system = (rd32(IGC_EEE_SU) &
+                                            IGC_TW_SYSTEM_1000_MASK) * 500;
+                       }
+               } else {
+                       tw_system = 0;
+               }
+
+               /* Get the Rx packet buffer size. */
+               size = rd32(IGC_RXPBS) &
+                      IGC_RXPBS_SIZE_I225_MASK;
+
+               /* Calculations vary based on DMAC settings. */
+               if (rd32(IGC_DMACR) & IGC_DMACR_DMAC_EN) {
+                       size -= (rd32(IGC_DMACR) &
+                                IGC_DMACR_DMACTHR_MASK) >>
+                                IGC_DMACR_DMACTHR_SHIFT;
+                       /* Convert size to bits. */
+                       size *= 1024 * 8;
+               } else {
+                       /* Convert size to bytes, subtract the MTU, and then
+                        * convert the size to bits.
+                        */
+                       size *= 1024;
+                       size *= 8;
+               }
+
+               if (size < 0) {
+                       hw_dbg("Invalid effective Rx buffer size %d\n",
+                              size);
+                       return -IGC_ERR_CONFIG;
+               }
+
+               /* Calculate the thresholds. Since speed is in Mbps, simplify
+                * the calculation by multiplying size/speed by 1000 for result
+                * to be in nsec before dividing by the scale in nsec. Set the
+                * scale such that the LTR threshold fits in the register.
+                */
+               ltr_min = (1000 * size) / speed;
+               ltr_max = ltr_min + tw_system;
+               scale_min = (ltr_min / 1024) < 1024 ? IGC_LTRMINV_SCALE_1024 :
+                           IGC_LTRMINV_SCALE_32768;
+               scale_max = (ltr_max / 1024) < 1024 ? IGC_LTRMAXV_SCALE_1024 :
+                           IGC_LTRMAXV_SCALE_32768;
+               ltr_min /= scale_min == IGC_LTRMINV_SCALE_1024 ? 1024 : 32768;
+               ltr_min -= 1;
+               ltr_max /= scale_max == IGC_LTRMAXV_SCALE_1024 ? 1024 : 32768;
+               ltr_max -= 1;
+
+               /* Only write the LTR thresholds if they differ from before. */
+               ltrv = rd32(IGC_LTRMINV);
+               if (ltr_min != (ltrv & IGC_LTRMINV_LTRV_MASK)) {
+                       ltrv = IGC_LTRMINV_LSNP_REQ | ltr_min |
+                              (scale_min << IGC_LTRMINV_SCALE_SHIFT);
+                       wr32(IGC_LTRMINV, ltrv);
+               }
+
+               ltrv = rd32(IGC_LTRMAXV);
+               if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK)) {
+                       ltrv = IGC_LTRMAXV_LSNP_REQ | ltr_max |
+                              (scale_min << IGC_LTRMAXV_SCALE_SHIFT);
+                       wr32(IGC_LTRMAXV, ltrv);
+               }
+       }
+
+       return IGC_SUCCESS;
+}
index 04759e076a9ea5ff096a97d10ab4376ecf9d87eb..dae47e4f16b087a56c24b2a72a1b94bad8da9d26 100644 (file)
@@ -11,5 +11,6 @@ s32 igc_init_nvm_params_i225(struct igc_hw *hw);
 bool igc_get_flash_presence_i225(struct igc_hw *hw);
 s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G,
                     bool adv100M);
+s32 igc_set_ltr_i225(struct igc_hw *hw, bool link);
 
 #endif
index 410aeb01de5c27fbd07dedee5f473ec628d1d29d..bc077f230f17282d66091ffea3c6f2af31872e27 100644 (file)
@@ -417,6 +417,11 @@ s32 igc_check_for_copper_link(struct igc_hw *hw)
                hw_dbg("Error configuring flow control\n");
 
 out:
+       /* Now that we are aware of our link settings, we can set the LTR
+        * thresholds.
+        */
+       ret_val = igc_set_ltr_i225(hw, link);
+
        return ret_val;
 }
 
index 75e040a5d46f76cdcecf9a8487f7e94313ac22cc..97f9b928509f3900bb593c86c2a4957feaa878a3 100644 (file)
 #define IGC_IPCNFG     0x0E38 /* Internal PHY Configuration */
 #define IGC_EEE_SU     0x0E34 /* EEE Setup */
 
+/* LTR registers */
+#define IGC_LTRC       0x01A0 /* Latency Tolerance Reporting Control */
+#define IGC_DMACR      0x02508 /* DMA Coalescing Control Register */
+#define IGC_LTRMINV    0x5BB0 /* LTR Minimum Value */
+#define IGC_LTRMAXV    0x5BB4 /* LTR Maximum Value */
+
 /* forward declaration */
 struct igc_hw;
 u32 igc_rd32(struct igc_hw *hw, u32 reg);