Commit 9227dc5e authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller

amd-xgbe: Add support for per DMA channel interrupts

This patch provides support for interrupts that are generated by the
Tx/Rx DMA channel pairs of the device.  This allows for Tx and Rx
processing to run across multiple processsors.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 174fd259
...@@ -7,7 +7,10 @@ Required properties: ...@@ -7,7 +7,10 @@ Required properties:
- PCS registers - PCS registers
- interrupt-parent: Should be the phandle for the interrupt controller - interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device that services interrupts for this device
- interrupts: Should contain the amd-xgbe interrupt - interrupts: Should contain the amd-xgbe interrupt(s). The first interrupt
listed is required and is the general device interrupt. If the optional
amd,per-channel-interrupt property is specified, then one additional
interrupt for each DMA channel supported by the device should be specified
- clocks: - clocks:
- DMA clock for the amd-xgbe device (used for calculating the - DMA clock for the amd-xgbe device (used for calculating the
correct Rx interrupt watchdog timer value on a DMA channel correct Rx interrupt watchdog timer value on a DMA channel
...@@ -23,6 +26,9 @@ Optional properties: ...@@ -23,6 +26,9 @@ Optional properties:
- mac-address: mac address to be assigned to the device. Can be overridden - mac-address: mac address to be assigned to the device. Can be overridden
by UEFI. by UEFI.
- dma-coherent: Present if dma operations are coherent - dma-coherent: Present if dma operations are coherent
- amd,per-channel-interrupt: Indicates that Rx and Tx complete will generate
a unique interrupt for each DMA channel - this requires an additional
interrupt be configured for each DMA channel
Example: Example:
xgbe@e0700000 { xgbe@e0700000 {
...@@ -30,7 +36,9 @@ Example: ...@@ -30,7 +36,9 @@ Example:
reg = <0 0xe0700000 0 0x80000>, reg = <0 0xe0700000 0 0x80000>,
<0 0xe0780000 0 0x80000>; <0 0xe0780000 0 0x80000>;
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <0 325 4>; interrupts = <0 325 4>,
<0 326 1>, <0 327 1>, <0 328 1>, <0 329 1>;
amd,per-channel-interrupt;
clocks = <&xgbe_dma_clk>, <&xgbe_ptp_clk>; clocks = <&xgbe_dma_clk>, <&xgbe_ptp_clk>;
clock-names = "dma_clk", "ptp_clk"; clock-names = "dma_clk", "ptp_clk";
phy-handle = <&phy>; phy-handle = <&phy>;
......
...@@ -481,17 +481,21 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) ...@@ -481,17 +481,21 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata)
if (channel->tx_ring) { if (channel->tx_ring) {
/* Enable the following Tx interrupts /* Enable the following Tx interrupts
* TIE - Transmit Interrupt Enable (unless polling) * TIE - Transmit Interrupt Enable (unless using
* per channel interrupts)
*/ */
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); if (!pdata->per_channel_irq)
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
} }
if (channel->rx_ring) { if (channel->rx_ring) {
/* Enable following Rx interrupts /* Enable following Rx interrupts
* RBUE - Receive Buffer Unavailable Enable * RBUE - Receive Buffer Unavailable Enable
* RIE - Receive Interrupt Enable * RIE - Receive Interrupt Enable (unless using
* per channel interrupts)
*/ */
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); if (!pdata->per_channel_irq)
XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
} }
XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier);
......
This diff is collapsed.
...@@ -264,12 +264,18 @@ static int xgbe_probe(struct platform_device *pdev) ...@@ -264,12 +264,18 @@ static int xgbe_probe(struct platform_device *pdev)
pdata->awcache = XGBE_DMA_SYS_AWCACHE; pdata->awcache = XGBE_DMA_SYS_AWCACHE;
} }
/* Check for per channel interrupt support */
if (of_property_read_bool(dev->of_node, XGBE_DMA_IRQS))
pdata->per_channel_irq = 1;
ret = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "platform_get_irq failed\n"); dev_err(dev, "platform_get_irq 0 failed\n");
goto err_io; goto err_io;
} }
netdev->irq = ret; pdata->dev_irq = ret;
netdev->irq = pdata->dev_irq;
netdev->base_addr = (unsigned long)pdata->xgmac_regs; netdev->base_addr = (unsigned long)pdata->xgmac_regs;
/* Set all the function pointers */ /* Set all the function pointers */
......
...@@ -173,6 +173,7 @@ ...@@ -173,6 +173,7 @@
/* Device-tree clock names */ /* Device-tree clock names */
#define XGBE_DMA_CLOCK "dma_clk" #define XGBE_DMA_CLOCK "dma_clk"
#define XGBE_PTP_CLOCK "ptp_clk" #define XGBE_PTP_CLOCK "ptp_clk"
#define XGBE_DMA_IRQS "amd,per-channel-interrupt"
/* Timestamp support - values based on 50MHz PTP clock /* Timestamp support - values based on 50MHz PTP clock
* 50MHz => 20 nsec * 50MHz => 20 nsec
...@@ -359,6 +360,12 @@ struct xgbe_channel { ...@@ -359,6 +360,12 @@ struct xgbe_channel {
unsigned int queue_index; unsigned int queue_index;
void __iomem *dma_regs; void __iomem *dma_regs;
/* Per channel interrupt irq number */
int dma_irq;
/* Netdev related settings */
struct napi_struct napi;
unsigned int saved_ier; unsigned int saved_ier;
unsigned int tx_timer_active; unsigned int tx_timer_active;
...@@ -609,7 +616,8 @@ struct xgbe_prv_data { ...@@ -609,7 +616,8 @@ struct xgbe_prv_data {
/* XPCS indirect addressing mutex */ /* XPCS indirect addressing mutex */
struct mutex xpcs_mutex; struct mutex xpcs_mutex;
int irq_number; int dev_irq;
unsigned int per_channel_irq;
struct xgbe_hw_if hw_if; struct xgbe_hw_if hw_if;
struct xgbe_desc_if desc_if; struct xgbe_desc_if desc_if;
......
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