Skip to content

Commit

Permalink
Merge branch 'cpsw-next'
Browse files Browse the repository at this point in the history
Mugunthan V N says:

====================
CPSW interrupt handling cleanup and performance improvement

This patch series removes the irq controller disable interrupt and
adding a napi for tx event handling which improves the performance by
~180Mbps on dra7-evm

[  5] local 192.168.10.116 port 5001 connected with 192.168.10.165 port 44176
[  5]  0.0-60.0 sec  1.48 GBytes   210 Mbits/sec
[  4] local 192.168.10.116 port 5001 connected with 192.168.10.165 port 33257
[  4]  0.0-60.0 sec  2.71 GBytes   386 Mbits/sec

Changes from initial version:
* Added a patch to have napi only for first interface as there is
  no use of having seperate napis for each interface as the
  interrupt is shared by both interface and only one napi is
  scheduled for each interrupt.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 7, 2015
2 parents 5a9348b + 32a7432 commit adc4cc9
Showing 1 changed file with 35 additions and 48 deletions.
83 changes: 35 additions & 48 deletions drivers/net/ethernet/ti/cpsw.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,8 @@ struct cpsw_priv {
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
struct napi_struct napi;
struct napi_struct napi_rx;
struct napi_struct napi_tx;
struct device *dev;
struct cpsw_platform_data data;
struct cpsw_ss_regs __iomem *regs;
Expand All @@ -389,7 +390,6 @@ struct cpsw_priv {
/* snapshot of IRQ numbers */
u32 irqs_table[4];
u32 num_irqs;
bool irq_enabled;
struct cpts *cpts;
u32 emac_port;
};
Expand Down Expand Up @@ -752,13 +752,10 @@ static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
{
struct cpsw_priv *priv = dev_id;

writel(0, &priv->wr_regs->tx_en);
cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
cpdma_chan_process(priv->txch, 128);

priv = cpsw_get_slave_priv(priv, 1);
if (priv)
cpdma_chan_process(priv->txch, 128);

napi_schedule(&priv->napi_tx);
return IRQ_HANDLED;
}

Expand All @@ -767,45 +764,38 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
struct cpsw_priv *priv = dev_id;

cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
writel(0, &priv->wr_regs->rx_en);

cpsw_intr_disable(priv);
if (priv->irq_enabled == true) {
disable_irq_nosync(priv->irqs_table[0]);
priv->irq_enabled = false;
}
napi_schedule(&priv->napi_rx);
return IRQ_HANDLED;
}

static int cpsw_tx_poll(struct napi_struct *napi_tx, int budget)
{
struct cpsw_priv *priv = napi_to_priv(napi_tx);
int num_tx;

if (netif_running(priv->ndev)) {
napi_schedule(&priv->napi);
return IRQ_HANDLED;
num_tx = cpdma_chan_process(priv->txch, budget);
if (num_tx < budget) {
napi_complete(napi_tx);
writel(0xff, &priv->wr_regs->tx_en);
}

priv = cpsw_get_slave_priv(priv, 1);
if (!priv)
return IRQ_NONE;
if (num_tx)
cpsw_dbg(priv, intr, "poll %d tx pkts\n", num_tx);

if (netif_running(priv->ndev)) {
napi_schedule(&priv->napi);
return IRQ_HANDLED;
}
return IRQ_NONE;
return num_tx;
}

static int cpsw_poll(struct napi_struct *napi, int budget)
static int cpsw_rx_poll(struct napi_struct *napi_rx, int budget)
{
struct cpsw_priv *priv = napi_to_priv(napi);
struct cpsw_priv *priv = napi_to_priv(napi_rx);
int num_rx;

num_rx = cpdma_chan_process(priv->rxch, budget);
if (num_rx < budget) {
struct cpsw_priv *prim_cpsw;

napi_complete(napi);
cpsw_intr_enable(priv);
prim_cpsw = cpsw_get_slave_priv(priv, 0);
if (prim_cpsw->irq_enabled == false) {
prim_cpsw->irq_enabled = true;
enable_irq(priv->irqs_table[0]);
}
napi_complete(napi_rx);
writel(0xff, &priv->wr_regs->rx_en);
}

if (num_rx)
Expand Down Expand Up @@ -1230,7 +1220,6 @@ static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv)
static int cpsw_ndo_open(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
struct cpsw_priv *prim_cpsw;
int i, ret;
u32 reg;

Expand Down Expand Up @@ -1260,6 +1249,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
ALE_ALL_PORTS << priv->host_port, 0, 0);

if (!cpsw_common_res_usage_state(priv)) {
struct cpsw_priv *priv_sl0 = cpsw_get_slave_priv(priv, 0);

/* setup tx dma to fixed prio and zero offset */
cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
Expand All @@ -1273,6 +1264,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
/* Enable internal fifo flow control */
writel(0x7, &priv->regs->flow_control);

napi_enable(&priv_sl0->napi_rx);
napi_enable(&priv_sl0->napi_tx);

if (WARN_ON(!priv->data.rx_descs))
priv->data.rx_descs = 128;

Expand Down Expand Up @@ -1311,18 +1305,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpsw_set_coalesce(ndev, &coal);
}

napi_enable(&priv->napi);
cpdma_ctlr_start(priv->dma);
cpsw_intr_enable(priv);

prim_cpsw = cpsw_get_slave_priv(priv, 0);
if (prim_cpsw->irq_enabled == false) {
if ((priv == prim_cpsw) || !netif_running(prim_cpsw->ndev)) {
prim_cpsw->irq_enabled = true;
enable_irq(prim_cpsw->irqs_table[0]);
}
}

if (priv->data.dual_emac)
priv->slaves[priv->emac_port].open_stat = true;
return 0;
Expand All @@ -1341,10 +1326,13 @@ static int cpsw_ndo_stop(struct net_device *ndev)

cpsw_info(priv, ifdown, "shutting down cpsw device\n");
netif_stop_queue(priv->ndev);
napi_disable(&priv->napi);
netif_carrier_off(priv->ndev);

if (cpsw_common_res_usage_state(priv) <= 1) {
struct cpsw_priv *priv_sl0 = cpsw_get_slave_priv(priv, 0);

napi_disable(&priv_sl0->napi_rx);
napi_disable(&priv_sl0->napi_tx);
cpts_unregister(priv->cpts);
cpsw_intr_disable(priv);
cpdma_ctlr_stop(priv->dma);
Expand Down Expand Up @@ -2127,7 +2115,6 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,

ndev->netdev_ops = &cpsw_netdev_ops;
ndev->ethtool_ops = &cpsw_ethtool_ops;
netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);

/* register the network device */
SET_NETDEV_DEV(ndev, &pdev->dev);
Expand Down Expand Up @@ -2169,7 +2156,6 @@ static int cpsw_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
priv->rx_packet_max = max(rx_packet_max, 128);
priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
priv->irq_enabled = true;
if (!priv->cpts) {
dev_err(&pdev->dev, "error allocating cpts\n");
ret = -ENOMEM;
Expand Down Expand Up @@ -2380,7 +2366,8 @@ static int cpsw_probe(struct platform_device *pdev)

ndev->netdev_ops = &cpsw_netdev_ops;
ndev->ethtool_ops = &cpsw_ethtool_ops;
netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
netif_napi_add(ndev, &priv->napi_rx, cpsw_rx_poll, CPSW_POLL_WEIGHT);
netif_napi_add(ndev, &priv->napi_tx, cpsw_tx_poll, CPSW_POLL_WEIGHT);

/* register the network device */
SET_NETDEV_DEV(ndev, &pdev->dev);
Expand Down

0 comments on commit adc4cc9

Please sign in to comment.