Commit 5ef9d78e authored by David S. Miller's avatar David S. Miller

Merge branch 'qcom-emac-various-minor-fixes'

Timur Tabi says:

====================
net: qcom/emac: various minor fixes

A set of patches for 4.15 that clean up some code, apply minors fixes,
and so on.  Some of the code also prepares the driver for a future
version of the EMAC controller.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c7c64bca 740d6f18
...@@ -309,22 +309,12 @@ void emac_mac_mode_config(struct emac_adapter *adpt) ...@@ -309,22 +309,12 @@ void emac_mac_mode_config(struct emac_adapter *adpt)
/* Config descriptor rings */ /* Config descriptor rings */
static void emac_mac_dma_rings_config(struct emac_adapter *adpt) static void emac_mac_dma_rings_config(struct emac_adapter *adpt)
{ {
static const unsigned short tpd_q_offset[] = {
EMAC_DESC_CTRL_8, EMAC_H1TPD_BASE_ADDR_LO,
EMAC_H2TPD_BASE_ADDR_LO, EMAC_H3TPD_BASE_ADDR_LO};
static const unsigned short rfd_q_offset[] = {
EMAC_DESC_CTRL_2, EMAC_DESC_CTRL_10,
EMAC_DESC_CTRL_12, EMAC_DESC_CTRL_13};
static const unsigned short rrd_q_offset[] = {
EMAC_DESC_CTRL_5, EMAC_DESC_CTRL_14,
EMAC_DESC_CTRL_15, EMAC_DESC_CTRL_16};
/* TPD (Transmit Packet Descriptor) */ /* TPD (Transmit Packet Descriptor) */
writel(upper_32_bits(adpt->tx_q.tpd.dma_addr), writel(upper_32_bits(adpt->tx_q.tpd.dma_addr),
adpt->base + EMAC_DESC_CTRL_1); adpt->base + EMAC_DESC_CTRL_1);
writel(lower_32_bits(adpt->tx_q.tpd.dma_addr), writel(lower_32_bits(adpt->tx_q.tpd.dma_addr),
adpt->base + tpd_q_offset[0]); adpt->base + EMAC_DESC_CTRL_8);
writel(adpt->tx_q.tpd.count & TPD_RING_SIZE_BMSK, writel(adpt->tx_q.tpd.count & TPD_RING_SIZE_BMSK,
adpt->base + EMAC_DESC_CTRL_9); adpt->base + EMAC_DESC_CTRL_9);
...@@ -334,9 +324,9 @@ static void emac_mac_dma_rings_config(struct emac_adapter *adpt) ...@@ -334,9 +324,9 @@ static void emac_mac_dma_rings_config(struct emac_adapter *adpt)
adpt->base + EMAC_DESC_CTRL_0); adpt->base + EMAC_DESC_CTRL_0);
writel(lower_32_bits(adpt->rx_q.rfd.dma_addr), writel(lower_32_bits(adpt->rx_q.rfd.dma_addr),
adpt->base + rfd_q_offset[0]); adpt->base + EMAC_DESC_CTRL_2);
writel(lower_32_bits(adpt->rx_q.rrd.dma_addr), writel(lower_32_bits(adpt->rx_q.rrd.dma_addr),
adpt->base + rrd_q_offset[0]); adpt->base + EMAC_DESC_CTRL_5);
writel(adpt->rx_q.rfd.count & RFD_RING_SIZE_BMSK, writel(adpt->rx_q.rfd.count & RFD_RING_SIZE_BMSK,
adpt->base + EMAC_DESC_CTRL_3); adpt->base + EMAC_DESC_CTRL_3);
...@@ -744,6 +734,11 @@ static int emac_rx_descs_alloc(struct emac_adapter *adpt) ...@@ -744,6 +734,11 @@ static int emac_rx_descs_alloc(struct emac_adapter *adpt)
rx_q->rrd.size = rx_q->rrd.count * (adpt->rrd_size * 4); rx_q->rrd.size = rx_q->rrd.count * (adpt->rrd_size * 4);
rx_q->rfd.size = rx_q->rfd.count * (adpt->rfd_size * 4); rx_q->rfd.size = rx_q->rfd.count * (adpt->rfd_size * 4);
/* Check if the RRD and RFD are aligned properly, and if not, adjust. */
if (upper_32_bits(ring_header->dma_addr) !=
upper_32_bits(ring_header->dma_addr + ALIGN(rx_q->rrd.size, 8)))
ring_header->used = ALIGN(rx_q->rrd.size, 8);
rx_q->rrd.dma_addr = ring_header->dma_addr + ring_header->used; rx_q->rrd.dma_addr = ring_header->dma_addr + ring_header->used;
rx_q->rrd.v_addr = ring_header->v_addr + ring_header->used; rx_q->rrd.v_addr = ring_header->v_addr + ring_header->used;
ring_header->used += ALIGN(rx_q->rrd.size, 8); ring_header->used += ALIGN(rx_q->rrd.size, 8);
...@@ -777,11 +772,18 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt) ...@@ -777,11 +772,18 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt)
/* Ring DMA buffer. Each ring may need up to 8 bytes for alignment, /* Ring DMA buffer. Each ring may need up to 8 bytes for alignment,
* hence the additional padding bytes are allocated. * hence the additional padding bytes are allocated.
*
* Also double the memory allocated for the RRD so that we can
* re-align it if necessary. The EMAC has a restriction that the
* upper 32 bits of the base addresses for the RFD and RRD rings
* must be the same. It is extremely unlikely that this is not the
* case, since the rings are only a few KB in size. However, we
* need to check for this anyway, and if the two rings are not
* compliant, then we re-align.
*/ */
ring_header->size = num_tx_descs * (adpt->tpd_size * 4) + ring_header->size = ALIGN(num_tx_descs * (adpt->tpd_size * 4), 8) +
num_rx_descs * (adpt->rfd_size * 4) + ALIGN(num_rx_descs * (adpt->rfd_size * 4), 8) +
num_rx_descs * (adpt->rrd_size * 4) + ALIGN(num_rx_descs * (adpt->rrd_size * 4), 8) * 2;
8 + 2 * 8; /* 8 byte per one Tx and two Rx rings */
ring_header->used = 0; ring_header->used = 0;
ring_header->v_addr = dma_zalloc_coherent(dev, ring_header->size, ring_header->v_addr = dma_zalloc_coherent(dev, ring_header->size,
...@@ -790,26 +792,23 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt) ...@@ -790,26 +792,23 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt)
if (!ring_header->v_addr) if (!ring_header->v_addr)
return -ENOMEM; return -ENOMEM;
ring_header->used = ALIGN(ring_header->dma_addr, 8) -
ring_header->dma_addr;
ret = emac_tx_q_desc_alloc(adpt, &adpt->tx_q);
if (ret) {
netdev_err(adpt->netdev, "error: Tx Queue alloc failed\n");
goto err_alloc_tx;
}
ret = emac_rx_descs_alloc(adpt); ret = emac_rx_descs_alloc(adpt);
if (ret) { if (ret) {
netdev_err(adpt->netdev, "error: Rx Queue alloc failed\n"); netdev_err(adpt->netdev, "error: Rx Queue alloc failed\n");
goto err_alloc_rx; goto err_alloc_rx;
} }
ret = emac_tx_q_desc_alloc(adpt, &adpt->tx_q);
if (ret) {
netdev_err(adpt->netdev, "transmit queue allocation failed\n");
goto err_alloc_tx;
}
return 0; return 0;
err_alloc_rx:
emac_tx_q_bufs_free(adpt);
err_alloc_tx: err_alloc_tx:
emac_rx_q_bufs_free(adpt);
err_alloc_rx:
dma_free_coherent(dev, ring_header->size, dma_free_coherent(dev, ring_header->size,
ring_header->v_addr, ring_header->dma_addr); ring_header->v_addr, ring_header->dma_addr);
......
...@@ -68,10 +68,10 @@ static void emac_sgmii_link_init(struct emac_adapter *adpt) ...@@ -68,10 +68,10 @@ static void emac_sgmii_link_init(struct emac_adapter *adpt)
writel(val, phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2); writel(val, phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2);
} }
static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u32 irq_bits) static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u8 irq_bits)
{ {
struct emac_sgmii *phy = &adpt->phy; struct emac_sgmii *phy = &adpt->phy;
u32 status; u8 status;
writel_relaxed(irq_bits, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR); writel_relaxed(irq_bits, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR);
writel_relaxed(IRQ_GLOBAL_CLEAR, phy->base + EMAC_SGMII_PHY_IRQ_CMD); writel_relaxed(IRQ_GLOBAL_CLEAR, phy->base + EMAC_SGMII_PHY_IRQ_CMD);
...@@ -86,9 +86,8 @@ static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u32 irq_bits) ...@@ -86,9 +86,8 @@ static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u32 irq_bits)
EMAC_SGMII_PHY_INTERRUPT_STATUS, EMAC_SGMII_PHY_INTERRUPT_STATUS,
status, !(status & irq_bits), 1, status, !(status & irq_bits), 1,
SGMII_PHY_IRQ_CLR_WAIT_TIME)) { SGMII_PHY_IRQ_CLR_WAIT_TIME)) {
netdev_err(adpt->netdev, net_err_ratelimited("%s: failed to clear SGMII irq: status:0x%x bits:0x%x\n",
"error: failed clear SGMII irq: status:0x%x bits:0x%x\n", adpt->netdev->name, status, irq_bits);
status, irq_bits);
return -EIO; return -EIO;
} }
...@@ -109,7 +108,7 @@ static irqreturn_t emac_sgmii_interrupt(int irq, void *data) ...@@ -109,7 +108,7 @@ static irqreturn_t emac_sgmii_interrupt(int irq, void *data)
{ {
struct emac_adapter *adpt = data; struct emac_adapter *adpt = data;
struct emac_sgmii *phy = &adpt->phy; struct emac_sgmii *phy = &adpt->phy;
u32 status; u8 status;
status = readl(phy->base + EMAC_SGMII_PHY_INTERRUPT_STATUS); status = readl(phy->base + EMAC_SGMII_PHY_INTERRUPT_STATUS);
status &= SGMII_ISR_MASK; status &= SGMII_ISR_MASK;
...@@ -139,10 +138,8 @@ static irqreturn_t emac_sgmii_interrupt(int irq, void *data) ...@@ -139,10 +138,8 @@ static irqreturn_t emac_sgmii_interrupt(int irq, void *data)
atomic_set(&phy->decode_error_count, 0); atomic_set(&phy->decode_error_count, 0);
} }
if (emac_sgmii_irq_clear(adpt, status)) { if (emac_sgmii_irq_clear(adpt, status))
netdev_warn(adpt->netdev, "failed to clear SGMII interrupt\n");
schedule_work(&adpt->work_thread); schedule_work(&adpt->work_thread);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -148,9 +148,8 @@ static irqreturn_t emac_isr(int _irq, void *data) ...@@ -148,9 +148,8 @@ static irqreturn_t emac_isr(int _irq, void *data)
goto exit; goto exit;
if (status & ISR_ERROR) { if (status & ISR_ERROR) {
netif_warn(adpt, intr, adpt->netdev, net_err_ratelimited("%s: error interrupt 0x%lx\n",
"warning: error irq status 0x%lx\n", adpt->netdev->name, status & ISR_ERROR);
status & ISR_ERROR);
/* reset MAC */ /* reset MAC */
schedule_work(&adpt->work_thread); schedule_work(&adpt->work_thread);
} }
...@@ -169,7 +168,8 @@ static irqreturn_t emac_isr(int _irq, void *data) ...@@ -169,7 +168,8 @@ static irqreturn_t emac_isr(int _irq, void *data)
emac_mac_tx_process(adpt, &adpt->tx_q); emac_mac_tx_process(adpt, &adpt->tx_q);
if (status & ISR_OVER) if (status & ISR_OVER)
net_warn_ratelimited("warning: TX/RX overflow\n"); net_warn_ratelimited("%s: TX/RX overflow interrupt\n",
adpt->netdev->name);
exit: exit:
/* enable the interrupt */ /* enable the interrupt */
...@@ -615,21 +615,12 @@ static int emac_probe(struct platform_device *pdev) ...@@ -615,21 +615,12 @@ static int emac_probe(struct platform_device *pdev)
u32 reg; u32 reg;
int ret; int ret;
/* The EMAC itself is capable of 64-bit DMA, so try that first. */ /* The TPD buffer address is limited to 45 bits. */
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(45));
if (ret) {
/* Some platforms may restrict the EMAC's address bus to less
* then the size of DDR. In this case, we need to try a
* smaller mask. We could try every possible smaller mask,
* but that's overkill. Instead, just fall to 32-bit, which
* should always work.
*/
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) { if (ret) {
dev_err(&pdev->dev, "could not set DMA mask\n"); dev_err(&pdev->dev, "could not set DMA mask\n");
return ret; return ret;
} }
}
netdev = alloc_etherdev(sizeof(struct emac_adapter)); netdev = alloc_etherdev(sizeof(struct emac_adapter));
if (!netdev) if (!netdev)
......
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