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

Commit 4e8ce063 authored by Niranjana Vishwanathapura's avatar Niranjana Vishwanathapura Committed by Gerrit - the friendly Code Review server
Browse files

msm: emac: Add interrupt coalescing support



Add support in driver to change interrupt coalescing times
for tx and rx interrupts using standard ethtool. Interrupt
coalescing helps in reducing the number of interrupts and thus
improving throughput.

Change-Id: I42c0056f7543474a9931ab84edf22394a7a6eb79
Signed-off-by: default avatarNiranjana Vishwanathapura <nvishwan@codeaurora.org>
parent 925035a3
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -19,11 +19,19 @@
#define DEV_REV_NUM_BMSK                                       0xff0000
#define DEV_REV_NUM_SHFT                                             16
#define INT_RD_CLR_EN                                            0x4000
#define IRQ_MODERATOR2_EN                                         0x800
#define IRQ_MODERATOR_EN                                          0x400
#define LPW_CLK_SEL                                                0x80
#define LPW_STATE                                                  0x20
#define LPW_MODE                                                   0x10
#define SOFT_RST                                                    0x1

/* EMAC_IRQ_MOD_TIM_INIT */
#define IRQ_MODERATOR2_INIT_BMSK                             0xffff0000
#define IRQ_MODERATOR2_INIT_SHFT                                     16
#define IRQ_MODERATOR_INIT_BMSK                                  0xffff
#define IRQ_MODERATOR_INIT_SHFT                                       0

/* EMAC_MDIO_CTRL */
#define MDIO_MODE                                            0x40000000
#define MDIO_PR                                              0x20000000
+38 −0
Original line number Diff line number Diff line
@@ -363,6 +363,42 @@ static int emac_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
	return 0;
}

static int emac_get_intr_coalesce(struct net_device *netdev,
				  struct ethtool_coalesce *ec)
{
	struct emac_adapter *adpt = netdev_priv(netdev);
	struct emac_hw *hw = &adpt->hw;
	u32 val;

	val = emac_reg_r32(hw, EMAC, EMAC_IRQ_MOD_TIM_INIT);

	/* irq moderator timers have resolution of 2us */
	ec->tx_coalesce_usecs = ((val & IRQ_MODERATOR_INIT_BMSK) >>
				 IRQ_MODERATOR_INIT_SHFT) * 2;
	ec->rx_coalesce_usecs = ((val & IRQ_MODERATOR2_INIT_BMSK) >>
				 IRQ_MODERATOR2_INIT_SHFT) * 2;

	return 0;
}

static int emac_set_intr_coalesce(struct net_device *netdev,
				  struct ethtool_coalesce *ec)
{
	struct emac_adapter *adpt = netdev_priv(netdev);
	struct emac_hw *hw = &adpt->hw;
	u32 val;

	/* irq moderator timers have resolution of 2us */
	val = ((ec->rx_coalesce_usecs / 2) << IRQ_MODERATOR2_INIT_SHFT) &
		IRQ_MODERATOR2_INIT_BMSK;
	val |= ((ec->tx_coalesce_usecs / 2) << IRQ_MODERATOR_INIT_SHFT) &
		IRQ_MODERATOR_INIT_BMSK;

	emac_reg_w32(hw, EMAC, EMAC_IRQ_MOD_TIM_INIT, val);

	return 0;
}

static int emac_nway_reset(struct net_device *netdev)
{
	struct emac_adapter *adpt = netdev_priv(netdev);
@@ -423,6 +459,8 @@ static const struct ethtool_ops emac_ethtool_ops = {
	.set_wol         = emac_set_wol,
	.get_msglevel    = emac_get_msglevel,
	.set_msglevel    = emac_set_msglevel,
	.get_coalesce    = emac_get_intr_coalesce,
	.set_coalesce    = emac_set_intr_coalesce,
	.nway_reset      = emac_nway_reset,
	.get_link        = ethtool_op_get_link,
	.get_sset_count  = emac_get_sset_count,
+6 −2
Original line number Diff line number Diff line
@@ -1188,8 +1188,12 @@ void emac_hw_start_mac(struct emac_hw *hw)
	emac_reg_w32(hw, EMAC_CSR, EMAC_EMAC_WRAPPER_CSR1, csr1);
	emac_reg_w32(hw, EMAC, EMAC_MAC_CTRL, mac);

	/* enable interrupt read clear, low power sleep mode and normal state */
	emac_reg_w32(hw, EMAC, EMAC_DMA_MAS_CTRL, (INT_RD_CLR_EN | LPW_MODE));
	/* enable interrupt read clear, low power sleep mode and
	   the irq moderators
	*/
	emac_reg_w32(hw, EMAC, EMAC_DMA_MAS_CTRL,
		     (INT_RD_CLR_EN | LPW_MODE |
		      IRQ_MODERATOR_EN | IRQ_MODERATOR2_EN));

	if (CHK_HW_FLAG(PTP_EN)) {
		if (hw->link_speed == EMAC_LINK_SPEED_1GB_FULL)