diff options
| -rw-r--r-- | Documentation/devicetree/bindings/net/amd-xgbe.txt | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 226 | ||||
| -rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-main.c | 10 | ||||
| -rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe.h | 10 |
5 files changed, 219 insertions, 51 deletions
diff --git a/Documentation/devicetree/bindings/net/amd-xgbe.txt b/Documentation/devicetree/bindings/net/amd-xgbe.txt index 41354f730beb..26efd526d16c 100644 --- a/Documentation/devicetree/bindings/net/amd-xgbe.txt +++ b/Documentation/devicetree/bindings/net/amd-xgbe.txt | |||
| @@ -7,7 +7,10 @@ Required properties: | |||
| 7 | - PCS registers | 7 | - PCS registers |
| 8 | - interrupt-parent: Should be the phandle for the interrupt controller | 8 | - interrupt-parent: Should be the phandle for the interrupt controller |
| 9 | that services interrupts for this device | 9 | that services interrupts for this device |
| 10 | - interrupts: Should contain the amd-xgbe interrupt | 10 | - interrupts: Should contain the amd-xgbe interrupt(s). The first interrupt |
| 11 | listed is required and is the general device interrupt. If the optional | ||
| 12 | amd,per-channel-interrupt property is specified, then one additional | ||
| 13 | interrupt for each DMA channel supported by the device should be specified | ||
| 11 | - clocks: | 14 | - clocks: |
| 12 | - DMA clock for the amd-xgbe device (used for calculating the | 15 | - DMA clock for the amd-xgbe device (used for calculating the |
| 13 | correct Rx interrupt watchdog timer value on a DMA channel | 16 | correct Rx interrupt watchdog timer value on a DMA channel |
| @@ -23,6 +26,9 @@ Optional properties: | |||
| 23 | - mac-address: mac address to be assigned to the device. Can be overridden | 26 | - mac-address: mac address to be assigned to the device. Can be overridden |
| 24 | by UEFI. | 27 | by UEFI. |
| 25 | - dma-coherent: Present if dma operations are coherent | 28 | - dma-coherent: Present if dma operations are coherent |
| 29 | - amd,per-channel-interrupt: Indicates that Rx and Tx complete will generate | ||
| 30 | a unique interrupt for each DMA channel - this requires an additional | ||
| 31 | interrupt be configured for each DMA channel | ||
| 26 | 32 | ||
| 27 | Example: | 33 | Example: |
| 28 | xgbe@e0700000 { | 34 | xgbe@e0700000 { |
| @@ -30,7 +36,9 @@ Example: | |||
| 30 | reg = <0 0xe0700000 0 0x80000>, | 36 | reg = <0 0xe0700000 0 0x80000>, |
| 31 | <0 0xe0780000 0 0x80000>; | 37 | <0 0xe0780000 0 0x80000>; |
| 32 | interrupt-parent = <&gic>; | 38 | interrupt-parent = <&gic>; |
| 33 | interrupts = <0 325 4>; | 39 | interrupts = <0 325 4>, |
| 40 | <0 326 1>, <0 327 1>, <0 328 1>, <0 329 1>; | ||
| 41 | amd,per-channel-interrupt; | ||
| 34 | clocks = <&xgbe_dma_clk>, <&xgbe_ptp_clk>; | 42 | clocks = <&xgbe_dma_clk>, <&xgbe_ptp_clk>; |
| 35 | clock-names = "dma_clk", "ptp_clk"; | 43 | clock-names = "dma_clk", "ptp_clk"; |
| 36 | phy-handle = <&phy>; | 44 | phy-handle = <&phy>; |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index b3719f154637..ac3d319ffab3 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c | |||
| @@ -481,17 +481,21 @@ static void xgbe_enable_dma_interrupts(struct xgbe_prv_data *pdata) | |||
| 481 | 481 | ||
| 482 | if (channel->tx_ring) { | 482 | if (channel->tx_ring) { |
| 483 | /* Enable the following Tx interrupts | 483 | /* Enable the following Tx interrupts |
| 484 | * TIE - Transmit Interrupt Enable (unless polling) | 484 | * TIE - Transmit Interrupt Enable (unless using |
| 485 | * per channel interrupts) | ||
| 485 | */ | 486 | */ |
| 486 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); | 487 | if (!pdata->per_channel_irq) |
| 488 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1); | ||
| 487 | } | 489 | } |
| 488 | if (channel->rx_ring) { | 490 | if (channel->rx_ring) { |
| 489 | /* Enable following Rx interrupts | 491 | /* Enable following Rx interrupts |
| 490 | * RBUE - Receive Buffer Unavailable Enable | 492 | * RBUE - Receive Buffer Unavailable Enable |
| 491 | * RIE - Receive Interrupt Enable | 493 | * RIE - Receive Interrupt Enable (unless using |
| 494 | * per channel interrupts) | ||
| 492 | */ | 495 | */ |
| 493 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); | 496 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1); |
| 494 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); | 497 | if (!pdata->per_channel_irq) |
| 498 | XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1); | ||
| 495 | } | 499 | } |
| 496 | 500 | ||
| 497 | XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); | 501 | XGMAC_DMA_IOWRITE(channel, DMA_CH_IER, dma_ch_ier); |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 07e2d216323a..c3533e104c61 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
| @@ -114,6 +114,7 @@ | |||
| 114 | * THE POSSIBILITY OF SUCH DAMAGE. | 114 | * THE POSSIBILITY OF SUCH DAMAGE. |
| 115 | */ | 115 | */ |
| 116 | 116 | ||
| 117 | #include <linux/platform_device.h> | ||
| 117 | #include <linux/spinlock.h> | 118 | #include <linux/spinlock.h> |
| 118 | #include <linux/tcp.h> | 119 | #include <linux/tcp.h> |
| 119 | #include <linux/if_vlan.h> | 120 | #include <linux/if_vlan.h> |
| @@ -126,7 +127,8 @@ | |||
| 126 | #include "xgbe.h" | 127 | #include "xgbe.h" |
| 127 | #include "xgbe-common.h" | 128 | #include "xgbe-common.h" |
| 128 | 129 | ||
| 129 | static int xgbe_poll(struct napi_struct *, int); | 130 | static int xgbe_one_poll(struct napi_struct *, int); |
| 131 | static int xgbe_all_poll(struct napi_struct *, int); | ||
| 130 | static void xgbe_set_rx_mode(struct net_device *); | 132 | static void xgbe_set_rx_mode(struct net_device *); |
| 131 | 133 | ||
| 132 | static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | 134 | static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) |
| @@ -134,6 +136,7 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
| 134 | struct xgbe_channel *channel_mem, *channel; | 136 | struct xgbe_channel *channel_mem, *channel; |
| 135 | struct xgbe_ring *tx_ring, *rx_ring; | 137 | struct xgbe_ring *tx_ring, *rx_ring; |
| 136 | unsigned int count, i; | 138 | unsigned int count, i; |
| 139 | int ret = -ENOMEM; | ||
| 137 | 140 | ||
| 138 | count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); | 141 | count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count); |
| 139 | 142 | ||
| @@ -158,6 +161,19 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
| 158 | channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + | 161 | channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE + |
| 159 | (DMA_CH_INC * i); | 162 | (DMA_CH_INC * i); |
| 160 | 163 | ||
| 164 | if (pdata->per_channel_irq) { | ||
| 165 | /* Get the DMA interrupt (offset 1) */ | ||
| 166 | ret = platform_get_irq(pdata->pdev, i + 1); | ||
| 167 | if (ret < 0) { | ||
| 168 | netdev_err(pdata->netdev, | ||
| 169 | "platform_get_irq %u failed\n", | ||
| 170 | i + 1); | ||
| 171 | goto err_irq; | ||
| 172 | } | ||
| 173 | |||
| 174 | channel->dma_irq = ret; | ||
| 175 | } | ||
| 176 | |||
| 161 | if (i < pdata->tx_ring_count) { | 177 | if (i < pdata->tx_ring_count) { |
| 162 | spin_lock_init(&tx_ring->lock); | 178 | spin_lock_init(&tx_ring->lock); |
| 163 | channel->tx_ring = tx_ring++; | 179 | channel->tx_ring = tx_ring++; |
| @@ -168,9 +184,9 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
| 168 | channel->rx_ring = rx_ring++; | 184 | channel->rx_ring = rx_ring++; |
| 169 | } | 185 | } |
| 170 | 186 | ||
| 171 | DBGPR(" %s - queue_index=%u, dma_regs=%p, tx=%p, rx=%p\n", | 187 | DBGPR(" %s: queue=%u, dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n", |
| 172 | channel->name, channel->queue_index, channel->dma_regs, | 188 | channel->name, channel->queue_index, channel->dma_regs, |
| 173 | channel->tx_ring, channel->rx_ring); | 189 | channel->dma_irq, channel->tx_ring, channel->rx_ring); |
| 174 | } | 190 | } |
| 175 | 191 | ||
| 176 | pdata->channel = channel_mem; | 192 | pdata->channel = channel_mem; |
| @@ -178,6 +194,9 @@ static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) | |||
| 178 | 194 | ||
| 179 | return 0; | 195 | return 0; |
| 180 | 196 | ||
| 197 | err_irq: | ||
| 198 | kfree(rx_ring); | ||
| 199 | |||
| 181 | err_rx_ring: | 200 | err_rx_ring: |
| 182 | kfree(tx_ring); | 201 | kfree(tx_ring); |
| 183 | 202 | ||
| @@ -185,9 +204,7 @@ err_tx_ring: | |||
| 185 | kfree(channel_mem); | 204 | kfree(channel_mem); |
| 186 | 205 | ||
| 187 | err_channel: | 206 | err_channel: |
| 188 | netdev_err(pdata->netdev, "channel allocation failed\n"); | 207 | return ret; |
| 189 | |||
| 190 | return -ENOMEM; | ||
| 191 | } | 208 | } |
| 192 | 209 | ||
| 193 | static void xgbe_free_channels(struct xgbe_prv_data *pdata) | 210 | static void xgbe_free_channels(struct xgbe_prv_data *pdata) |
| @@ -287,11 +304,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) | |||
| 287 | if (!dma_isr) | 304 | if (!dma_isr) |
| 288 | goto isr_done; | 305 | goto isr_done; |
