浏览代码

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: David S. Miller <davem@davemloft.net>
David S. Miller 10 年之前
父节点
当前提交
adc4cc99b7
共有 1 个文件被更改,包括 35 次插入48 次删除
  1. 35 48
      drivers/net/ethernet/ti/cpsw.c

+ 35 - 48
drivers/net/ethernet/ti/cpsw.c

@@ -365,7 +365,8 @@ struct cpsw_priv {
 	spinlock_t			lock;
 	spinlock_t			lock;
 	struct platform_device		*pdev;
 	struct platform_device		*pdev;
 	struct net_device		*ndev;
 	struct net_device		*ndev;
-	struct napi_struct		napi;
+	struct napi_struct		napi_rx;
+	struct napi_struct		napi_tx;
 	struct device			*dev;
 	struct device			*dev;
 	struct cpsw_platform_data	data;
 	struct cpsw_platform_data	data;
 	struct cpsw_ss_regs __iomem	*regs;
 	struct cpsw_ss_regs __iomem	*regs;
@@ -389,7 +390,6 @@ struct cpsw_priv {
 	/* snapshot of IRQ numbers */
 	/* snapshot of IRQ numbers */
 	u32 irqs_table[4];
 	u32 irqs_table[4];
 	u32 num_irqs;
 	u32 num_irqs;
-	bool irq_enabled;
 	struct cpts *cpts;
 	struct cpts *cpts;
 	u32 emac_port;
 	u32 emac_port;
 };
 };
@@ -752,13 +752,10 @@ static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id)
 {
 {
 	struct cpsw_priv *priv = dev_id;
 	struct cpsw_priv *priv = dev_id;
 
 
+	writel(0, &priv->wr_regs->tx_en);
 	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
 	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;
 	return IRQ_HANDLED;
 }
 }
 
 
@@ -767,45 +764,38 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
 	struct cpsw_priv *priv = dev_id;
 	struct cpsw_priv *priv = dev_id;
 
 
 	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
 	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;
 	int			num_rx;
 
 
 	num_rx = cpdma_chan_process(priv->rxch, budget);
 	num_rx = cpdma_chan_process(priv->rxch, budget);
 	if (num_rx < 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)
 	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)
 static int cpsw_ndo_open(struct net_device *ndev)
 {
 {
 	struct cpsw_priv *priv = netdev_priv(ndev);
 	struct cpsw_priv *priv = netdev_priv(ndev);
-	struct cpsw_priv *prim_cpsw;
 	int i, ret;
 	int i, ret;
 	u32 reg;
 	u32 reg;
 
 
@@ -1260,6 +1249,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
 				  ALE_ALL_PORTS << priv->host_port, 0, 0);
 				  ALE_ALL_PORTS << priv->host_port, 0, 0);
 
 
 	if (!cpsw_common_res_usage_state(priv)) {
 	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 */
 		/* 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_TX_PRIO_FIXED, 1);
 		cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
 		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 */
 		/* Enable internal fifo flow control */
 		writel(0x7, &priv->regs->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))
 		if (WARN_ON(!priv->data.rx_descs))
 			priv->data.rx_descs = 128;
 			priv->data.rx_descs = 128;
 
 
@@ -1311,18 +1305,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
 		cpsw_set_coalesce(ndev, &coal);
 		cpsw_set_coalesce(ndev, &coal);
 	}
 	}
 
 
-	napi_enable(&priv->napi);
 	cpdma_ctlr_start(priv->dma);
 	cpdma_ctlr_start(priv->dma);
 	cpsw_intr_enable(priv);
 	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)
 	if (priv->data.dual_emac)
 		priv->slaves[priv->emac_port].open_stat = true;
 		priv->slaves[priv->emac_port].open_stat = true;
 	return 0;
 	return 0;
@@ -1341,10 +1326,13 @@ static int cpsw_ndo_stop(struct net_device *ndev)
 
 
 	cpsw_info(priv, ifdown, "shutting down cpsw device\n");
 	cpsw_info(priv, ifdown, "shutting down cpsw device\n");
 	netif_stop_queue(priv->ndev);
 	netif_stop_queue(priv->ndev);
-	napi_disable(&priv->napi);
 	netif_carrier_off(priv->ndev);
 	netif_carrier_off(priv->ndev);
 
 
 	if (cpsw_common_res_usage_state(priv) <= 1) {
 	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);
 		cpts_unregister(priv->cpts);
 		cpsw_intr_disable(priv);
 		cpsw_intr_disable(priv);
 		cpdma_ctlr_stop(priv->dma);
 		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->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
-	netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
 
 
 	/* register the network device */
 	/* register the network device */
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 	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->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
 	priv->rx_packet_max = max(rx_packet_max, 128);
 	priv->rx_packet_max = max(rx_packet_max, 128);
 	priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
 	priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
-	priv->irq_enabled = true;
 	if (!priv->cpts) {
 	if (!priv->cpts) {
 		dev_err(&pdev->dev, "error allocating cpts\n");
 		dev_err(&pdev->dev, "error allocating cpts\n");
 		ret = -ENOMEM;
 		ret = -ENOMEM;
@@ -2380,7 +2366,8 @@ static int cpsw_probe(struct platform_device *pdev)
 
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_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 */
 	/* register the network device */
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);