Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 368241
b: refs/heads/master
c: ff5b8ef
h: refs/heads/master
i:
  368239: 019362b
v: v3
  • Loading branch information
Mugunthan V N authored and David S. Miller committed Mar 13, 2013
1 parent 639dc00 commit f6eea8f
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d3bb9c58b567d240eaaa2dc8bd778696eaed5fbd
refs/heads/master: ff5b8ef2ef3af0fd7e1cf6c8c1ed9ec5afbda422
104 changes: 104 additions & 0 deletions trunk/drivers/net/ethernet/ti/cpsw.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ do { \
#define CPSW_FIFO_DUAL_MAC_MODE (1 << 15)
#define CPSW_FIFO_RATE_LIMIT_MODE (2 << 15)

#define CPSW_INTPACEEN (0x3f << 16)
#define CPSW_INTPRESCALE_MASK (0x7FF << 0)
#define CPSW_CMINTMAX_CNT 63
#define CPSW_CMINTMIN_CNT 2
#define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT)
#define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1)

#define cpsw_enable_irq(priv) \
do { \
u32 i; \
Expand Down Expand Up @@ -164,6 +171,15 @@ struct cpsw_wr_regs {
u32 rx_en;
u32 tx_en;
u32 misc_en;
u32 mem_allign1[8];
u32 rx_thresh_stat;
u32 rx_stat;
u32 tx_stat;
u32 misc_stat;
u32 mem_allign2[8];
u32 rx_imax;
u32 tx_imax;

};

struct cpsw_ss_regs {
Expand Down Expand Up @@ -318,6 +334,8 @@ struct cpsw_priv {
struct cpsw_host_regs __iomem *host_port_regs;
u32 msg_enable;
u32 version;
u32 coal_intvl;
u32 bus_freq_mhz;
struct net_device_stats stats;
int rx_packet_max;
int host_port;
Expand Down Expand Up @@ -616,6 +634,77 @@ static void cpsw_adjust_link(struct net_device *ndev)
}
}

static int cpsw_get_coalesce(struct net_device *ndev,
struct ethtool_coalesce *coal)
{
struct cpsw_priv *priv = netdev_priv(ndev);

coal->rx_coalesce_usecs = priv->coal_intvl;
return 0;
}

static int cpsw_set_coalesce(struct net_device *ndev,
struct ethtool_coalesce *coal)
{
struct cpsw_priv *priv = netdev_priv(ndev);
u32 int_ctrl;
u32 num_interrupts = 0;
u32 prescale = 0;
u32 addnl_dvdr = 1;
u32 coal_intvl = 0;

if (!coal->rx_coalesce_usecs)
return -EINVAL;

coal_intvl = coal->rx_coalesce_usecs;

int_ctrl = readl(&priv->wr_regs->int_control);
prescale = priv->bus_freq_mhz * 4;

if (coal_intvl < CPSW_CMINTMIN_INTVL)
coal_intvl = CPSW_CMINTMIN_INTVL;

if (coal_intvl > CPSW_CMINTMAX_INTVL) {
/* Interrupt pacer works with 4us Pulse, we can
* throttle further by dilating the 4us pulse.
*/
addnl_dvdr = CPSW_INTPRESCALE_MASK / prescale;

if (addnl_dvdr > 1) {
prescale *= addnl_dvdr;
if (coal_intvl > (CPSW_CMINTMAX_INTVL * addnl_dvdr))
coal_intvl = (CPSW_CMINTMAX_INTVL
* addnl_dvdr);
} else {
addnl_dvdr = 1;
coal_intvl = CPSW_CMINTMAX_INTVL;
}
}

num_interrupts = (1000 * addnl_dvdr) / coal_intvl;
writel(num_interrupts, &priv->wr_regs->rx_imax);
writel(num_interrupts, &priv->wr_regs->tx_imax);

int_ctrl |= CPSW_INTPACEEN;
int_ctrl &= (~CPSW_INTPRESCALE_MASK);
int_ctrl |= (prescale & CPSW_INTPRESCALE_MASK);
writel(int_ctrl, &priv->wr_regs->int_control);

cpsw_notice(priv, timer, "Set coalesce to %d usecs.\n", coal_intvl);
if (priv->data.dual_emac) {
int i;

for (i = 0; i < priv->data.slaves; i++) {
priv = netdev_priv(priv->slaves[i].ndev);
priv->coal_intvl = coal_intvl;
}
} else {
priv->coal_intvl = coal_intvl;
}

return 0;
}

static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
{
static char *leader = "........................................";
Expand Down Expand Up @@ -838,6 +927,14 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
}

/* Enable Interrupt pacing if configured */
if (priv->coal_intvl != 0) {
struct ethtool_coalesce coal;

coal.rx_coalesce_usecs = (priv->coal_intvl << 4);
cpsw_set_coalesce(ndev, &coal);
}

cpdma_ctlr_start(priv->dma);
cpsw_intr_enable(priv);
napi_enable(&priv->napi);
Expand Down Expand Up @@ -1279,6 +1376,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
.get_ts_info = cpsw_get_ts_info,
.get_settings = cpsw_get_settings,
.set_settings = cpsw_set_settings,
.get_coalesce = cpsw_get_coalesce,
.set_coalesce = cpsw_set_coalesce,
};

static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
Expand Down Expand Up @@ -1466,6 +1565,9 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
priv_sl2->slaves = priv->slaves;
priv_sl2->clk = priv->clk;

priv_sl2->coal_intvl = 0;
priv_sl2->bus_freq_mhz = priv->bus_freq_mhz;

priv_sl2->cpsw_res = priv->cpsw_res;
priv_sl2->regs = priv->regs;
priv_sl2->host_port = priv->host_port;
Expand Down Expand Up @@ -1575,6 +1677,8 @@ static int cpsw_probe(struct platform_device *pdev)
ret = -ENODEV;
goto clean_slave_ret;
}
priv->coal_intvl = 0;
priv->bus_freq_mhz = clk_get_rate(priv->clk) / 1000000;

priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!priv->cpsw_res) {
Expand Down

0 comments on commit f6eea8f

Please sign in to comment.