Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 831ec0b4 authored by Carolyn Wyborny's avatar Carolyn Wyborny Committed by Jeff Kirsher
Browse files

igb: Add DMA Coalescing feature to driver



This patch add DMA Coalescing which is a power-saving feature that
coalesces DMA writes in order to stay in a low-power state as much
as possible.  Feature is disabled by default.

Signed-off-by: default avatarCarolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: default avatarJeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 4322e561
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -287,7 +287,34 @@
#define E1000_TCTL_COLD   0x003ff000    /* collision distance */
#define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */

/* Transmit Arbitration Count */
/* DMA Coalescing register fields */
#define E1000_DMACR_DMACWT_MASK         0x00003FFF /* DMA Coalescing
							* Watchdog Timer */
#define E1000_DMACR_DMACTHR_MASK        0x00FF0000 /* DMA Coalescing Receive
							* Threshold */
#define E1000_DMACR_DMACTHR_SHIFT       16
#define E1000_DMACR_DMAC_LX_MASK        0x30000000 /* Lx when no PCIe
							* transactions */
#define E1000_DMACR_DMAC_LX_SHIFT       28
#define E1000_DMACR_DMAC_EN             0x80000000 /* Enable DMA Coalescing */

#define E1000_DMCTXTH_DMCTTHR_MASK      0x00000FFF /* DMA Coalescing Transmit
							* Threshold */

#define E1000_DMCTLX_TTLX_MASK          0x00000FFF /* Time to LX request */

#define E1000_DMCRTRH_UTRESH_MASK       0x0007FFFF /* Receive Traffic Rate
							* Threshold */
#define E1000_DMCRTRH_LRPRCW            0x80000000 /* Rcv packet rate in
							* current window */

#define E1000_DMCCNT_CCOUNT_MASK        0x01FFFFFF /* DMA Coal Rcv Traffic
							* Current Cnt */

#define E1000_FCRTC_RTH_COAL_MASK       0x0003FFF0 /* Flow ctrl Rcv Threshold
							* High val */
#define E1000_FCRTC_RTH_COAL_SHIFT      4
#define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision */

/* SerDes Control */
#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
+9 −0
Original line number Diff line number Diff line
@@ -106,6 +106,15 @@

#define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))

/* DMA Coalescing registers */
#define E1000_DMACR             0x02508 /* Control Register */
#define E1000_DMCTXTH           0x03550 /* Transmit Threshold */
#define E1000_DMCTLX            0x02514 /* Time to Lx Request */
#define E1000_DMCRTRH           0x05DD0 /* Receive Packet Rate Threshold */
#define E1000_DMCCNT            0x05DD4 /* Current Rx Count */
#define E1000_FCRTC             0x02170 /* Flow Control Rx high watermark */
#define E1000_PCIEMISC          0x05BB8 /* PCIE misc config register */

/* TX Rate Limit Registers */
#define E1000_RTTDQSEL	0x3604	/* Tx Desc Plane Queue Select - WO */
#define E1000_RTTBCNRC	0x36B0	/* Tx BCN Rate-Scheduler Config - WO */
+6 −0
Original line number Diff line number Diff line
@@ -333,6 +333,12 @@ struct igb_adapter {
#define IGB_FLAG_DCA_ENABLED       (1 << 1)
#define IGB_FLAG_QUAD_PORT_A       (1 << 2)
#define IGB_FLAG_QUEUE_PAIRS       (1 << 3)
#define IGB_FLAG_DMAC              (1 << 4)

/* DMA Coalescing defines */
#define IGB_MIN_TXPBSIZE           20408
#define IGB_TX_BUF_4096            4096
#define IGB_DMCTLX_DCFLUSH_DIS     0x80000000  /* Disable DMA Coal Flush */

#define IGB_82576_TSYNC_SHIFT 19
#define IGB_82580_TSYNC_SHIFT 24
+6 −0
Original line number Diff line number Diff line
@@ -2009,6 +2009,12 @@ static int igb_set_coalesce(struct net_device *netdev,
	if ((adapter->flags & IGB_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs)
		return -EINVAL;

	/* If ITR is disabled, disable DMAC */
	if (ec->rx_coalesce_usecs == 0) {
		if (adapter->flags & IGB_FLAG_DMAC)
			adapter->flags &= ~IGB_FLAG_DMAC;
	}

	/* convert to rate of irq's per second */
	if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3)
		adapter->rx_itr_setting = ec->rx_coalesce_usecs;
+57 −0
Original line number Diff line number Diff line
@@ -1674,7 +1674,58 @@ void igb_reset(struct igb_adapter *adapter)

	if (hw->mac.ops.init_hw(hw))
		dev_err(&pdev->dev, "Hardware Error\n");
	if (hw->mac.type > e1000_82580) {
		if (adapter->flags & IGB_FLAG_DMAC) {
			u32 reg;

			/*
			 * DMA Coalescing high water mark needs to be higher
			 * than * the * Rx threshold.  The Rx threshold is
			 * currently * pba - 6, so we * should use a high water
			 * mark of pba * - 4. */
			hwm = (pba - 4) << 10;

			reg = (((pba-6) << E1000_DMACR_DMACTHR_SHIFT)
			       & E1000_DMACR_DMACTHR_MASK);

			/* transition to L0x or L1 if available..*/
			reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);

			/* watchdog timer= +-1000 usec in 32usec intervals */
			reg |= (1000 >> 5);
			wr32(E1000_DMACR, reg);

			/* no lower threshold to disable coalescing(smart fifb)
			 * -UTRESH=0*/
			wr32(E1000_DMCRTRH, 0);

			/* set hwm to PBA -  2 * max frame size */
			wr32(E1000_FCRTC, hwm);

			/*
			 * This sets the time to wait before requesting tran-
			 * sition to * low power state to number of usecs needed
			 * to receive 1 512 * byte frame at gigabit line rate
			 */
			reg = rd32(E1000_DMCTLX);
			reg |= IGB_DMCTLX_DCFLUSH_DIS;

			/* Delay 255 usec before entering Lx state. */
			reg |= 0xFF;
			wr32(E1000_DMCTLX, reg);

			/* free space in Tx packet buffer to wake from DMAC */
			wr32(E1000_DMCTXTH,
			     (IGB_MIN_TXPBSIZE -
			     (IGB_TX_BUF_4096 + adapter->max_frame_size))
			     >> 6);

			/* make low power state decision controlled by DMAC */
			reg = rd32(E1000_PCIEMISC);
			reg |= E1000_PCIEMISC_LX_DECISION;
			wr32(E1000_PCIEMISC, reg);
		} /* end if IGB_FLAG_DMAC set */
	}
	if (hw->mac.type == e1000_82580) {
		u32 reg = rd32(E1000_PCIEMISC);
		wr32(E1000_PCIEMISC,
@@ -2157,6 +2208,9 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
			random_ether_addr(mac_addr);
			igb_set_vf_mac(adapter, i, mac_addr);
		}
		/* DMA Coalescing is not supported in IOV mode. */
		if (adapter->flags & IGB_FLAG_DMAC)
			adapter->flags &= ~IGB_FLAG_DMAC;
	}
#endif /* CONFIG_PCI_IOV */
}
@@ -2331,6 +2385,9 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
	/* Explicitly disable IRQ since the NIC can be in any state. */
	igb_irq_disable(adapter);

	if (hw->mac.type == e1000_i350)
		adapter->flags &= ~IGB_FLAG_DMAC;

	set_bit(__IGB_DOWN, &adapter->state);
	return 0;
}