Commit adc4cc99 authored by David S. Miller's avatar David S. Miller

Merge branch 'cpsw-next'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 5a9348b5 32a7432c
......@@ -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;
......@@ -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;
};
......@@ -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;
}
......@@ -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;
}
if (netif_running(priv->ndev)) {
napi_schedule(&priv->napi);
napi_schedule(&priv->napi_rx);
return IRQ_HANDLED;
}
}
priv = cpsw_get_slave_priv(priv, 1);
if (!priv)
return IRQ_NONE;
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);
}
return IRQ_NONE;
if (num_tx)
cpsw_dbg(priv, intr, "poll %d tx pkts\n", num_tx);
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)
......@@ -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;
......@@ -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);
......@@ -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;
......@@ -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;
......@@ -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);
......@@ -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);
......@@ -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;
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment