2019-05-19 15:51:43 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-03-07 17:08:43 -08:00
|
|
|
/*
|
|
|
|
* Applied Micro X-Gene SoC Ethernet v2 Driver
|
|
|
|
*
|
|
|
|
* Copyright (c) 2017, Applied Micro Circuits Corporation
|
|
|
|
* Author(s): Iyappan Subramanian <isubramanian@apm.com>
|
|
|
|
* Keyur Chudgar <kchudgar@apm.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
static int xge_get_resources(struct xge_pdata *pdata)
|
|
|
|
{
|
|
|
|
struct platform_device *pdev;
|
|
|
|
struct net_device *ndev;
|
|
|
|
int phy_mode, ret = 0;
|
2017-03-07 17:08:45 -08:00
|
|
|
struct resource *res;
|
|
|
|
struct device *dev;
|
2017-03-07 17:08:43 -08:00
|
|
|
|
|
|
|
pdev = pdata->pdev;
|
|
|
|
dev = &pdev->dev;
|
|
|
|
ndev = pdata->ndev;
|
|
|
|
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
|
if (!res) {
|
|
|
|
dev_err(dev, "Resource enet_csr not defined\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
pdata->resources.base_addr = devm_ioremap(dev, res->start,
|
|
|
|
resource_size(res));
|
|
|
|
if (!pdata->resources.base_addr) {
|
|
|
|
dev_err(dev, "Unable to retrieve ENET Port CSR region\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2021-10-06 18:07:01 -07:00
|
|
|
if (device_get_ethdev_address(dev, ndev))
|
2017-03-07 17:08:43 -08:00
|
|
|
eth_hw_addr_random(ndev);
|
|
|
|
|
|
|
|
memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
|
|
|
|
|
|
|
|
phy_mode = device_get_phy_mode(dev);
|
|
|
|
if (phy_mode < 0) {
|
|
|
|
dev_err(dev, "Unable to get phy-connection-type\n");
|
|
|
|
return phy_mode;
|
|
|
|
}
|
|
|
|
pdata->resources.phy_mode = phy_mode;
|
|
|
|
|
|
|
|
if (pdata->resources.phy_mode != PHY_INTERFACE_MODE_RGMII) {
|
|
|
|
dev_err(dev, "Incorrect phy-connection-type specified\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = platform_get_irq(pdev, 0);
|
2019-07-30 11:15:51 -07:00
|
|
|
if (ret < 0)
|
2017-03-07 17:08:43 -08:00
|
|
|
return ret;
|
|
|
|
pdata->resources.irq = ret;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xge_refill_buffers(struct net_device *ndev, u32 nbuf)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct xge_desc_ring *ring = pdata->rx_ring;
|
|
|
|
const u8 slots = XGENE_ENET_NUM_DESC - 1;
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
struct xge_raw_desc *raw_desc;
|
|
|
|
u64 addr_lo, addr_hi;
|
|
|
|
u8 tail = ring->tail;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
dma_addr_t dma_addr;
|
|
|
|
u16 len;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < nbuf; i++) {
|
|
|
|
raw_desc = &ring->raw_desc[tail];
|
|
|
|
|
|
|
|
len = XGENE_ENET_STD_MTU;
|
|
|
|
skb = netdev_alloc_skb(ndev, len);
|
|
|
|
if (unlikely(!skb))
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
|
|
|
|
if (dma_mapping_error(dev, dma_addr)) {
|
|
|
|
netdev_err(ndev, "DMA mapping error\n");
|
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ring->pkt_info[tail].skb = skb;
|
|
|
|
ring->pkt_info[tail].dma_addr = dma_addr;
|
|
|
|
|
|
|
|
addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
|
|
|
|
addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
|
|
|
|
raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
|
|
|
|
SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
|
|
|
|
SET_BITS(PKT_ADDRH,
|
2017-03-07 17:08:44 -08:00
|
|
|
upper_32_bits(dma_addr)));
|
2017-03-07 17:08:43 -08:00
|
|
|
|
|
|
|
dma_wmb();
|
|
|
|
raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) |
|
|
|
|
SET_BITS(E, 1));
|
|
|
|
tail = (tail + 1) & slots;
|
|
|
|
}
|
|
|
|
|
|
|
|
ring->tail = tail;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xge_init_hw(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = xge_port_reset(ndev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
xge_port_init(ndev);
|
|
|
|
pdata->nbufs = NUM_BUFS;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static irqreturn_t xge_irq(const int irq, void *data)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = data;
|
|
|
|
|
|
|
|
if (napi_schedule_prep(&pdata->napi)) {
|
|
|
|
xge_intr_disable(pdata);
|
|
|
|
__napi_schedule(&pdata->napi);
|
|
|
|
}
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xge_request_irq(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
snprintf(pdata->irq_name, IRQ_ID_SIZE, "%s", ndev->name);
|
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
ret = request_irq(pdata->resources.irq, xge_irq, 0, pdata->irq_name,
|
|
|
|
pdata);
|
2017-03-07 17:08:43 -08:00
|
|
|
if (ret)
|
|
|
|
netdev_err(ndev, "Failed to request irq %s\n", pdata->irq_name);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xge_free_irq(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
free_irq(pdata->resources.irq, pdata);
|
2017-03-07 17:08:43 -08:00
|
|
|
}
|
|
|
|
|
2017-03-07 17:08:44 -08:00
|
|
|
static bool is_tx_slot_available(struct xge_raw_desc *raw_desc)
|
|
|
|
{
|
|
|
|
if (GET_BITS(E, le64_to_cpu(raw_desc->m0)) &&
|
|
|
|
(GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)) == SLOT_EMPTY))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
struct xge_desc_ring *tx_ring;
|
|
|
|
struct xge_raw_desc *raw_desc;
|
2017-03-07 17:08:45 -08:00
|
|
|
static dma_addr_t dma_addr;
|
2017-03-07 17:08:44 -08:00
|
|
|
u64 addr_lo, addr_hi;
|
|
|
|
void *pkt_buf;
|
|
|
|
u8 tail;
|
|
|
|
u16 len;
|
|
|
|
|
|
|
|
tx_ring = pdata->tx_ring;
|
|
|
|
tail = tx_ring->tail;
|
|
|
|
len = skb_headlen(skb);
|
|
|
|
raw_desc = &tx_ring->raw_desc[tail];
|
|
|
|
|
|
|
|
if (!is_tx_slot_available(raw_desc)) {
|
|
|
|
netif_stop_queue(ndev);
|
|
|
|
return NETDEV_TX_BUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Packet buffers should be 64B aligned */
|
cross-tree: phase out dma_zalloc_coherent()
We already need to zero out memory for dma_alloc_coherent(), as such
using dma_zalloc_coherent() is superflous. Phase it out.
This change was generated with the following Coccinelle SmPL patch:
@ replace_dma_zalloc_coherent @
expression dev, size, data, handle, flags;
@@
-dma_zalloc_coherent(dev, size, handle, flags)
+dma_alloc_coherent(dev, size, handle, flags)
Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
[hch: re-ran the script on the latest tree]
Signed-off-by: Christoph Hellwig <hch@lst.de>
2019-01-04 09:23:09 +01:00
|
|
|
pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr,
|
|
|
|
GFP_ATOMIC);
|
2017-03-07 17:08:44 -08:00
|
|
|
if (unlikely(!pkt_buf)) {
|
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
return NETDEV_TX_OK;
|
|
|
|
}
|
|
|
|
memcpy(pkt_buf, skb->data, len);
|
|
|
|
|
|
|
|
addr_hi = GET_BITS(NEXT_DESC_ADDRH, le64_to_cpu(raw_desc->m1));
|
|
|
|
addr_lo = GET_BITS(NEXT_DESC_ADDRL, le64_to_cpu(raw_desc->m1));
|
|
|
|
raw_desc->m1 = cpu_to_le64(SET_BITS(NEXT_DESC_ADDRL, addr_lo) |
|
|
|
|
SET_BITS(NEXT_DESC_ADDRH, addr_hi) |
|
|
|
|
SET_BITS(PKT_ADDRH,
|
|
|
|
upper_32_bits(dma_addr)));
|
|
|
|
|
|
|
|
tx_ring->pkt_info[tail].skb = skb;
|
|
|
|
tx_ring->pkt_info[tail].dma_addr = dma_addr;
|
|
|
|
tx_ring->pkt_info[tail].pkt_buf = pkt_buf;
|
|
|
|
|
|
|
|
dma_wmb();
|
|
|
|
|
|
|
|
raw_desc->m0 = cpu_to_le64(SET_BITS(PKT_ADDRL, dma_addr) |
|
|
|
|
SET_BITS(PKT_SIZE, len) |
|
|
|
|
SET_BITS(E, 0));
|
|
|
|
skb_tx_timestamp(skb);
|
|
|
|
xge_wr_csr(pdata, DMATXCTRL, 1);
|
|
|
|
|
|
|
|
tx_ring->tail = (tail + 1) & (XGENE_ENET_NUM_DESC - 1);
|
|
|
|
|
|
|
|
return NETDEV_TX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool is_tx_hw_done(struct xge_raw_desc *raw_desc)
|
|
|
|
{
|
|
|
|
if (GET_BITS(E, le64_to_cpu(raw_desc->m0)) &&
|
|
|
|
!GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0)))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xge_txc_poll(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
struct xge_desc_ring *tx_ring;
|
|
|
|
struct xge_raw_desc *raw_desc;
|
|
|
|
dma_addr_t dma_addr;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
void *pkt_buf;
|
|
|
|
u32 data;
|
|
|
|
u8 head;
|
|
|
|
|
|
|
|
tx_ring = pdata->tx_ring;
|
|
|
|
head = tx_ring->head;
|
|
|
|
|
|
|
|
data = xge_rd_csr(pdata, DMATXSTATUS);
|
|
|
|
if (!GET_BITS(TXPKTCOUNT, data))
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
raw_desc = &tx_ring->raw_desc[head];
|
|
|
|
|
|
|
|
if (!is_tx_hw_done(raw_desc))
|
|
|
|
break;
|
|
|
|
|
|
|
|
dma_rmb();
|
|
|
|
|
|
|
|
skb = tx_ring->pkt_info[head].skb;
|
|
|
|
dma_addr = tx_ring->pkt_info[head].dma_addr;
|
|
|
|
pkt_buf = tx_ring->pkt_info[head].pkt_buf;
|
|
|
|
pdata->stats.tx_packets++;
|
|
|
|
pdata->stats.tx_bytes += skb->len;
|
|
|
|
dma_free_coherent(dev, XGENE_ENET_STD_MTU, pkt_buf, dma_addr);
|
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
|
|
|
|
/* clear pktstart address and pktsize */
|
|
|
|
raw_desc->m0 = cpu_to_le64(SET_BITS(E, 1) |
|
|
|
|
SET_BITS(PKT_SIZE, SLOT_EMPTY));
|
|
|
|
xge_wr_csr(pdata, DMATXSTATUS, 1);
|
|
|
|
|
|
|
|
head = (head + 1) & (XGENE_ENET_NUM_DESC - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netif_queue_stopped(ndev))
|
|
|
|
netif_wake_queue(ndev);
|
|
|
|
|
|
|
|
tx_ring->head = head;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xge_rx_poll(struct net_device *ndev, unsigned int budget)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
struct xge_desc_ring *rx_ring;
|
|
|
|
struct xge_raw_desc *raw_desc;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
dma_addr_t dma_addr;
|
|
|
|
int processed = 0;
|
|
|
|
u8 head, rx_error;
|
|
|
|
int i, ret;
|
|
|
|
u32 data;
|
|
|
|
u16 len;
|
|
|
|
|
|
|
|
rx_ring = pdata->rx_ring;
|
|
|
|
head = rx_ring->head;
|
|
|
|
|
|
|
|
data = xge_rd_csr(pdata, DMARXSTATUS);
|
|
|
|
if (!GET_BITS(RXPKTCOUNT, data))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0; i < budget; i++) {
|
|
|
|
raw_desc = &rx_ring->raw_desc[head];
|
|
|
|
|
|
|
|
if (GET_BITS(E, le64_to_cpu(raw_desc->m0)))
|
|
|
|
break;
|
|
|
|
|
|
|
|
dma_rmb();
|
|
|
|
|
|
|
|
skb = rx_ring->pkt_info[head].skb;
|
|
|
|
rx_ring->pkt_info[head].skb = NULL;
|
|
|
|
dma_addr = rx_ring->pkt_info[head].dma_addr;
|
|
|
|
len = GET_BITS(PKT_SIZE, le64_to_cpu(raw_desc->m0));
|
|
|
|
dma_unmap_single(dev, dma_addr, XGENE_ENET_STD_MTU,
|
|
|
|
DMA_FROM_DEVICE);
|
|
|
|
|
|
|
|
rx_error = GET_BITS(D, le64_to_cpu(raw_desc->m2));
|
|
|
|
if (unlikely(rx_error)) {
|
|
|
|
pdata->stats.rx_errors++;
|
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_put(skb, len);
|
|
|
|
skb->protocol = eth_type_trans(skb, ndev);
|
|
|
|
|
|
|
|
pdata->stats.rx_packets++;
|
|
|
|
pdata->stats.rx_bytes += len;
|
|
|
|
napi_gro_receive(&pdata->napi, skb);
|
|
|
|
out:
|
|
|
|
ret = xge_refill_buffers(ndev, 1);
|
|
|
|
xge_wr_csr(pdata, DMARXSTATUS, 1);
|
|
|
|
xge_wr_csr(pdata, DMARXCTRL, 1);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
|
|
|
|
head = (head + 1) & (XGENE_ENET_NUM_DESC - 1);
|
|
|
|
processed++;
|
|
|
|
}
|
|
|
|
|
|
|
|
rx_ring->head = head;
|
|
|
|
|
|
|
|
return processed;
|
|
|
|
}
|
|
|
|
|
2017-03-07 17:08:43 -08:00
|
|
|
static void xge_delete_desc_ring(struct net_device *ndev,
|
|
|
|
struct xge_desc_ring *ring)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
u16 size;
|
|
|
|
|
|
|
|
if (!ring)
|
|
|
|
return;
|
|
|
|
|
|
|
|
size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC;
|
|
|
|
if (ring->desc_addr)
|
|
|
|
dma_free_coherent(dev, size, ring->desc_addr, ring->dma_addr);
|
|
|
|
|
|
|
|
kfree(ring->pkt_info);
|
|
|
|
kfree(ring);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xge_free_buffers(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct xge_desc_ring *ring = pdata->rx_ring;
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
dma_addr_t dma_addr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < XGENE_ENET_NUM_DESC; i++) {
|
|
|
|
skb = ring->pkt_info[i].skb;
|
|
|
|
dma_addr = ring->pkt_info[i].dma_addr;
|
|
|
|
|
|
|
|
if (!skb)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dma_unmap_single(dev, dma_addr, XGENE_ENET_STD_MTU,
|
|
|
|
DMA_FROM_DEVICE);
|
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xge_delete_desc_rings(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
|
2017-03-07 17:08:44 -08:00
|
|
|
xge_txc_poll(ndev);
|
2017-03-07 17:08:43 -08:00
|
|
|
xge_delete_desc_ring(ndev, pdata->tx_ring);
|
|
|
|
|
2017-03-07 17:08:44 -08:00
|
|
|
xge_rx_poll(ndev, 64);
|
2017-03-07 17:08:43 -08:00
|
|
|
xge_free_buffers(ndev);
|
|
|
|
xge_delete_desc_ring(ndev, pdata->rx_ring);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct xge_desc_ring *xge_create_desc_ring(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
struct xge_desc_ring *ring;
|
|
|
|
u16 size;
|
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
2017-03-07 17:08:43 -08:00
|
|
|
if (!ring)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ring->ndev = ndev;
|
|
|
|
|
|
|
|
size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC;
|
cross-tree: phase out dma_zalloc_coherent()
We already need to zero out memory for dma_alloc_coherent(), as such
using dma_zalloc_coherent() is superflous. Phase it out.
This change was generated with the following Coccinelle SmPL patch:
@ replace_dma_zalloc_coherent @
expression dev, size, data, handle, flags;
@@
-dma_zalloc_coherent(dev, size, handle, flags)
+dma_alloc_coherent(dev, size, handle, flags)
Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
[hch: re-ran the script on the latest tree]
Signed-off-by: Christoph Hellwig <hch@lst.de>
2019-01-04 09:23:09 +01:00
|
|
|
ring->desc_addr = dma_alloc_coherent(dev, size, &ring->dma_addr,
|
|
|
|
GFP_KERNEL);
|
2017-03-07 17:08:43 -08:00
|
|
|
if (!ring->desc_addr)
|
|
|
|
goto err;
|
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
ring->pkt_info = kcalloc(XGENE_ENET_NUM_DESC, sizeof(*ring->pkt_info),
|
2017-03-07 17:08:43 -08:00
|
|
|
GFP_KERNEL);
|
|
|
|
if (!ring->pkt_info)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
xge_setup_desc(ring);
|
|
|
|
|
|
|
|
return ring;
|
|
|
|
|
|
|
|
err:
|
|
|
|
xge_delete_desc_ring(ndev, ring);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xge_create_desc_rings(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct xge_desc_ring *ring;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* create tx ring */
|
|
|
|
ring = xge_create_desc_ring(ndev);
|
|
|
|
if (!ring)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
pdata->tx_ring = ring;
|
|
|
|
xge_update_tx_desc_addr(pdata);
|
|
|
|
|
|
|
|
/* create rx ring */
|
|
|
|
ring = xge_create_desc_ring(ndev);
|
|
|
|
if (!ring)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
pdata->rx_ring = ring;
|
|
|
|
xge_update_rx_desc_addr(pdata);
|
|
|
|
|
|
|
|
ret = xge_refill_buffers(ndev, XGENE_ENET_NUM_DESC);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
xge_delete_desc_rings(ndev);
|
|
|
|
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xge_open(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = xge_create_desc_rings(ndev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
napi_enable(&pdata->napi);
|
|
|
|
ret = xge_request_irq(ndev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
xge_intr_enable(pdata);
|
|
|
|
xge_wr_csr(pdata, DMARXCTRL, 1);
|
2017-03-21 18:18:02 -07:00
|
|
|
|
|
|
|
phy_start(ndev->phydev);
|
2017-03-07 17:08:43 -08:00
|
|
|
xge_mac_enable(pdata);
|
|
|
|
netif_start_queue(ndev);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int xge_close(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
|
|
|
|
netif_stop_queue(ndev);
|
|
|
|
xge_mac_disable(pdata);
|
2017-03-21 18:18:02 -07:00
|
|
|
phy_stop(ndev->phydev);
|
2017-03-07 17:08:43 -08:00
|
|
|
|
|
|
|
xge_intr_disable(pdata);
|
|
|
|
xge_free_irq(ndev);
|
|
|
|
napi_disable(&pdata->napi);
|
|
|
|
xge_delete_desc_rings(ndev);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-07 17:08:44 -08:00
|
|
|
static int xge_napi(struct napi_struct *napi, const int budget)
|
|
|
|
{
|
|
|
|
struct net_device *ndev = napi->dev;
|
2017-03-07 17:08:45 -08:00
|
|
|
struct xge_pdata *pdata;
|
2017-03-07 17:08:44 -08:00
|
|
|
int processed;
|
|
|
|
|
|
|
|
pdata = netdev_priv(ndev);
|
|
|
|
|
|
|
|
xge_txc_poll(ndev);
|
|
|
|
processed = xge_rx_poll(ndev, budget);
|
|
|
|
|
|
|
|
if (processed < budget) {
|
|
|
|
napi_complete_done(napi, processed);
|
|
|
|
xge_intr_enable(pdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
return processed;
|
|
|
|
}
|
|
|
|
|
2017-03-07 17:08:43 -08:00
|
|
|
static int xge_set_mac_addr(struct net_device *ndev, void *addr)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = eth_mac_addr(ndev, addr);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
xge_mac_set_station_addr(pdata);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-07 17:08:44 -08:00
|
|
|
static bool is_tx_pending(struct xge_raw_desc *raw_desc)
|
|
|
|
{
|
|
|
|
if (!GET_BITS(E, le64_to_cpu(raw_desc->m0)))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xge_free_pending_skb(struct net_device *ndev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct device *dev = &pdata->pdev->dev;
|
|
|
|
struct xge_desc_ring *tx_ring;
|
|
|
|
struct xge_raw_desc *raw_desc;
|
|
|
|
dma_addr_t dma_addr;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
void *pkt_buf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
tx_ring = pdata->tx_ring;
|
|
|
|
|
|
|
|
for (i = 0; i < XGENE_ENET_NUM_DESC; i++) {
|
|
|
|
raw_desc = &tx_ring->raw_desc[i];
|
|
|
|
|
|
|
|
if (!is_tx_pending(raw_desc))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
skb = tx_ring->pkt_info[i].skb;
|
|
|
|
dma_addr = tx_ring->pkt_info[i].dma_addr;
|
|
|
|
pkt_buf = tx_ring->pkt_info[i].pkt_buf;
|
|
|
|
dma_free_coherent(dev, XGENE_ENET_STD_MTU, pkt_buf, dma_addr);
|
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
netdev: pass the stuck queue to the timeout handler
This allows incrementing the correct timeout statistic without any mess.
Down the road, devices can learn to reset just the specific queue.
The patch was generated with the following script:
use strict;
use warnings;
our $^I = '.bak';
my @work = (
["arch/m68k/emu/nfeth.c", "nfeth_tx_timeout"],
["arch/um/drivers/net_kern.c", "uml_net_tx_timeout"],
["arch/um/drivers/vector_kern.c", "vector_net_tx_timeout"],
["arch/xtensa/platforms/iss/network.c", "iss_net_tx_timeout"],
["drivers/char/pcmcia/synclink_cs.c", "hdlcdev_tx_timeout"],
["drivers/infiniband/ulp/ipoib/ipoib_main.c", "ipoib_timeout"],
["drivers/infiniband/ulp/ipoib/ipoib_main.c", "ipoib_timeout"],
["drivers/message/fusion/mptlan.c", "mpt_lan_tx_timeout"],
["drivers/misc/sgi-xp/xpnet.c", "xpnet_dev_tx_timeout"],
["drivers/net/appletalk/cops.c", "cops_timeout"],
["drivers/net/arcnet/arcdevice.h", "arcnet_timeout"],
["drivers/net/arcnet/arcnet.c", "arcnet_timeout"],
["drivers/net/arcnet/com20020.c", "arcnet_timeout"],
["drivers/net/ethernet/3com/3c509.c", "el3_tx_timeout"],
["drivers/net/ethernet/3com/3c515.c", "corkscrew_timeout"],
["drivers/net/ethernet/3com/3c574_cs.c", "el3_tx_timeout"],
["drivers/net/ethernet/3com/3c589_cs.c", "el3_tx_timeout"],
["drivers/net/ethernet/3com/3c59x.c", "vortex_tx_timeout"],
["drivers/net/ethernet/3com/3c59x.c", "vortex_tx_timeout"],
["drivers/net/ethernet/3com/typhoon.c", "typhoon_tx_timeout"],
["drivers/net/ethernet/8390/8390.h", "ei_tx_timeout"],
["drivers/net/ethernet/8390/8390.h", "eip_tx_timeout"],
["drivers/net/ethernet/8390/8390.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/8390p.c", "eip_tx_timeout"],
["drivers/net/ethernet/8390/ax88796.c", "ax_ei_tx_timeout"],
["drivers/net/ethernet/8390/axnet_cs.c", "axnet_tx_timeout"],
["drivers/net/ethernet/8390/etherh.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/hydra.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/mac8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/mcf8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/lib8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/ne2k-pci.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/pcnet_cs.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/smc-ultra.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/wd.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/zorro8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/adaptec/starfire.c", "tx_timeout"],
["drivers/net/ethernet/agere/et131x.c", "et131x_tx_timeout"],
["drivers/net/ethernet/allwinner/sun4i-emac.c", "emac_timeout"],
["drivers/net/ethernet/alteon/acenic.c", "ace_watchdog"],
["drivers/net/ethernet/amazon/ena/ena_netdev.c", "ena_tx_timeout"],
["drivers/net/ethernet/amd/7990.h", "lance_tx_timeout"],
["drivers/net/ethernet/amd/7990.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/a2065.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/am79c961a.c", "am79c961_timeout"],
["drivers/net/ethernet/amd/amd8111e.c", "amd8111e_tx_timeout"],
["drivers/net/ethernet/amd/ariadne.c", "ariadne_tx_timeout"],
["drivers/net/ethernet/amd/atarilance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/au1000_eth.c", "au1000_tx_timeout"],
["drivers/net/ethernet/amd/declance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/lance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/mvme147.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/ni65.c", "ni65_timeout"],
["drivers/net/ethernet/amd/nmclan_cs.c", "mace_tx_timeout"],
["drivers/net/ethernet/amd/pcnet32.c", "pcnet32_tx_timeout"],
["drivers/net/ethernet/amd/sunlance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/xgbe/xgbe-drv.c", "xgbe_tx_timeout"],
["drivers/net/ethernet/apm/xgene-v2/main.c", "xge_timeout"],
["drivers/net/ethernet/apm/xgene/xgene_enet_main.c", "xgene_enet_timeout"],
["drivers/net/ethernet/apple/macmace.c", "mace_tx_timeout"],
["drivers/net/ethernet/atheros/ag71xx.c", "ag71xx_tx_timeout"],
["drivers/net/ethernet/atheros/alx/main.c", "alx_tx_timeout"],
["drivers/net/ethernet/atheros/atl1c/atl1c_main.c", "atl1c_tx_timeout"],
["drivers/net/ethernet/atheros/atl1e/atl1e_main.c", "atl1e_tx_timeout"],
["drivers/net/ethernet/atheros/atlx/atl.c", "atlx_tx_timeout"],
["drivers/net/ethernet/atheros/atlx/atl1.c", "atlx_tx_timeout"],
["drivers/net/ethernet/atheros/atlx/atl2.c", "atl2_tx_timeout"],
["drivers/net/ethernet/broadcom/b44.c", "b44_tx_timeout"],
["drivers/net/ethernet/broadcom/bcmsysport.c", "bcm_sysport_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2.c", "bnx2_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h", "bnx2x_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c", "bnx2x_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c", "bnx2x_tx_timeout"],
["drivers/net/ethernet/broadcom/bnxt/bnxt.c", "bnxt_tx_timeout"],
["drivers/net/ethernet/broadcom/genet/bcmgenet.c", "bcmgenet_timeout"],
["drivers/net/ethernet/broadcom/sb1250-mac.c", "sbmac_tx_timeout"],
["drivers/net/ethernet/broadcom/tg3.c", "tg3_tx_timeout"],
["drivers/net/ethernet/calxeda/xgmac.c", "xgmac_tx_timeout"],
["drivers/net/ethernet/cavium/liquidio/lio_main.c", "liquidio_tx_timeout"],
["drivers/net/ethernet/cavium/liquidio/lio_vf_main.c", "liquidio_tx_timeout"],
["drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c", "lio_vf_rep_tx_timeout"],
["drivers/net/ethernet/cavium/thunder/nicvf_main.c", "nicvf_tx_timeout"],
["drivers/net/ethernet/cirrus/cs89x0.c", "net_timeout"],
["drivers/net/ethernet/cisco/enic/enic_main.c", "enic_tx_timeout"],
["drivers/net/ethernet/cisco/enic/enic_main.c", "enic_tx_timeout"],
["drivers/net/ethernet/cortina/gemini.c", "gmac_tx_timeout"],
["drivers/net/ethernet/davicom/dm9000.c", "dm9000_timeout"],
["drivers/net/ethernet/dec/tulip/de2104x.c", "de_tx_timeout"],
["drivers/net/ethernet/dec/tulip/tulip_core.c", "tulip_tx_timeout"],
["drivers/net/ethernet/dec/tulip/winbond-840.c", "tx_timeout"],
["drivers/net/ethernet/dlink/dl2k.c", "rio_tx_timeout"],
["drivers/net/ethernet/dlink/sundance.c", "tx_timeout"],
["drivers/net/ethernet/emulex/benet/be_main.c", "be_tx_timeout"],
["drivers/net/ethernet/ethoc.c", "ethoc_tx_timeout"],
["drivers/net/ethernet/faraday/ftgmac100.c", "ftgmac100_tx_timeout"],
["drivers/net/ethernet/fealnx.c", "fealnx_tx_timeout"],
["drivers/net/ethernet/freescale/dpaa/dpaa_eth.c", "dpaa_tx_timeout"],
["drivers/net/ethernet/freescale/fec_main.c", "fec_timeout"],
["drivers/net/ethernet/freescale/fec_mpc52xx.c", "mpc52xx_fec_tx_timeout"],
["drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c", "fs_timeout"],
["drivers/net/ethernet/freescale/gianfar.c", "gfar_timeout"],
["drivers/net/ethernet/freescale/ucc_geth.c", "ucc_geth_timeout"],
["drivers/net/ethernet/fujitsu/fmvj18x_cs.c", "fjn_tx_timeout"],
["drivers/net/ethernet/google/gve/gve_main.c", "gve_tx_timeout"],
["drivers/net/ethernet/hisilicon/hip04_eth.c", "hip04_timeout"],
["drivers/net/ethernet/hisilicon/hix5hd2_gmac.c", "hix5hd2_net_timeout"],
["drivers/net/ethernet/hisilicon/hns/hns_enet.c", "hns_nic_net_timeout"],
["drivers/net/ethernet/hisilicon/hns3/hns3_enet.c", "hns3_nic_net_timeout"],
["drivers/net/ethernet/huawei/hinic/hinic_main.c", "hinic_tx_timeout"],
["drivers/net/ethernet/i825xx/82596.c", "i596_tx_timeout"],
["drivers/net/ethernet/i825xx/ether1.c", "ether1_timeout"],
["drivers/net/ethernet/i825xx/lib82596.c", "i596_tx_timeout"],
["drivers/net/ethernet/i825xx/sun3_82586.c", "sun3_82586_timeout"],
["drivers/net/ethernet/ibm/ehea/ehea_main.c", "ehea_tx_watchdog"],
["drivers/net/ethernet/ibm/emac/core.c", "emac_tx_timeout"],
["drivers/net/ethernet/ibm/emac/core.c", "emac_tx_timeout"],
["drivers/net/ethernet/ibm/ibmvnic.c", "ibmvnic_tx_timeout"],
["drivers/net/ethernet/intel/e100.c", "e100_tx_timeout"],
["drivers/net/ethernet/intel/e1000/e1000_main.c", "e1000_tx_timeout"],
["drivers/net/ethernet/intel/e1000e/netdev.c", "e1000_tx_timeout"],
["drivers/net/ethernet/intel/fm10k/fm10k_netdev.c", "fm10k_tx_timeout"],
["drivers/net/ethernet/intel/i40e/i40e_main.c", "i40e_tx_timeout"],
["drivers/net/ethernet/intel/iavf/iavf_main.c", "iavf_tx_timeout"],
["drivers/net/ethernet/intel/ice/ice_main.c", "ice_tx_timeout"],
["drivers/net/ethernet/intel/ice/ice_main.c", "ice_tx_timeout"],
["drivers/net/ethernet/intel/igb/igb_main.c", "igb_tx_timeout"],
["drivers/net/ethernet/intel/igbvf/netdev.c", "igbvf_tx_timeout"],
["drivers/net/ethernet/intel/ixgb/ixgb_main.c", "ixgb_tx_timeout"],
["drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c", "adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev);"],
["drivers/net/ethernet/intel/ixgbe/ixgbe_main.c", "ixgbe_tx_timeout"],
["drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c", "ixgbevf_tx_timeout"],
["drivers/net/ethernet/jme.c", "jme_tx_timeout"],
["drivers/net/ethernet/korina.c", "korina_tx_timeout"],
["drivers/net/ethernet/lantiq_etop.c", "ltq_etop_tx_timeout"],
["drivers/net/ethernet/marvell/mv643xx_eth.c", "mv643xx_eth_tx_timeout"],
["drivers/net/ethernet/marvell/pxa168_eth.c", "pxa168_eth_tx_timeout"],
["drivers/net/ethernet/marvell/skge.c", "skge_tx_timeout"],
["drivers/net/ethernet/marvell/sky2.c", "sky2_tx_timeout"],
["drivers/net/ethernet/marvell/sky2.c", "sky2_tx_timeout"],
["drivers/net/ethernet/mediatek/mtk_eth_soc.c", "mtk_tx_timeout"],
["drivers/net/ethernet/mellanox/mlx4/en_netdev.c", "mlx4_en_tx_timeout"],
["drivers/net/ethernet/mellanox/mlx4/en_netdev.c", "mlx4_en_tx_timeout"],
["drivers/net/ethernet/mellanox/mlx5/core/en_main.c", "mlx5e_tx_timeout"],
["drivers/net/ethernet/micrel/ks8842.c", "ks8842_tx_timeout"],
["drivers/net/ethernet/micrel/ksz884x.c", "netdev_tx_timeout"],
["drivers/net/ethernet/microchip/enc28j60.c", "enc28j60_tx_timeout"],
["drivers/net/ethernet/microchip/encx24j600.c", "encx24j600_tx_timeout"],
["drivers/net/ethernet/natsemi/sonic.h", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/sonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/jazzsonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/macsonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/natsemi.c", "ns_tx_timeout"],
["drivers/net/ethernet/natsemi/ns83820.c", "ns83820_tx_timeout"],
["drivers/net/ethernet/natsemi/xtsonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/neterion/s2io.h", "s2io_tx_watchdog"],
["drivers/net/ethernet/neterion/s2io.c", "s2io_tx_watchdog"],
["drivers/net/ethernet/neterion/vxge/vxge-main.c", "vxge_tx_watchdog"],
["drivers/net/ethernet/netronome/nfp/nfp_net_common.c", "nfp_net_tx_timeout"],
["drivers/net/ethernet/nvidia/forcedeth.c", "nv_tx_timeout"],
["drivers/net/ethernet/nvidia/forcedeth.c", "nv_tx_timeout"],
["drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c", "pch_gbe_tx_timeout"],
["drivers/net/ethernet/packetengines/hamachi.c", "hamachi_tx_timeout"],
["drivers/net/ethernet/packetengines/yellowfin.c", "yellowfin_tx_timeout"],
["drivers/net/ethernet/pensando/ionic/ionic_lif.c", "ionic_tx_timeout"],
["drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c", "netxen_tx_timeout"],
["drivers/net/ethernet/qlogic/qla3xxx.c", "ql3xxx_tx_timeout"],
["drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c", "qlcnic_tx_timeout"],
["drivers/net/ethernet/qualcomm/emac/emac.c", "emac_tx_timeout"],
["drivers/net/ethernet/qualcomm/qca_spi.c", "qcaspi_netdev_tx_timeout"],
["drivers/net/ethernet/qualcomm/qca_uart.c", "qcauart_netdev_tx_timeout"],
["drivers/net/ethernet/rdc/r6040.c", "r6040_tx_timeout"],
["drivers/net/ethernet/realtek/8139cp.c", "cp_tx_timeout"],
["drivers/net/ethernet/realtek/8139too.c", "rtl8139_tx_timeout"],
["drivers/net/ethernet/realtek/atp.c", "tx_timeout"],
["drivers/net/ethernet/realtek/r8169_main.c", "rtl8169_tx_timeout"],
["drivers/net/ethernet/renesas/ravb_main.c", "ravb_tx_timeout"],
["drivers/net/ethernet/renesas/sh_eth.c", "sh_eth_tx_timeout"],
["drivers/net/ethernet/renesas/sh_eth.c", "sh_eth_tx_timeout"],
["drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c", "sxgbe_tx_timeout"],
["drivers/net/ethernet/seeq/ether3.c", "ether3_timeout"],
["drivers/net/ethernet/seeq/sgiseeq.c", "timeout"],
["drivers/net/ethernet/sfc/efx.c", "efx_watchdog"],
["drivers/net/ethernet/sfc/falcon/efx.c", "ef4_watchdog"],
["drivers/net/ethernet/sgi/ioc3-eth.c", "ioc3_timeout"],
["drivers/net/ethernet/sgi/meth.c", "meth_tx_timeout"],
["drivers/net/ethernet/silan/sc92031.c", "sc92031_tx_timeout"],
["drivers/net/ethernet/sis/sis190.c", "sis190_tx_timeout"],
["drivers/net/ethernet/sis/sis900.c", "sis900_tx_timeout"],
["drivers/net/ethernet/smsc/epic100.c", "epic_tx_timeout"],
["drivers/net/ethernet/smsc/smc911x.c", "smc911x_timeout"],
["drivers/net/ethernet/smsc/smc9194.c", "smc_timeout"],
["drivers/net/ethernet/smsc/smc91c92_cs.c", "smc_tx_timeout"],
["drivers/net/ethernet/smsc/smc91x.c", "smc_timeout"],
["drivers/net/ethernet/stmicro/stmmac/stmmac_main.c", "stmmac_tx_timeout"],
["drivers/net/ethernet/sun/cassini.c", "cas_tx_timeout"],
["drivers/net/ethernet/sun/ldmvsw.c", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/sun/niu.c", "niu_tx_timeout"],
["drivers/net/ethernet/sun/sunbmac.c", "bigmac_tx_timeout"],
["drivers/net/ethernet/sun/sungem.c", "gem_tx_timeout"],
["drivers/net/ethernet/sun/sunhme.c", "happy_meal_tx_timeout"],
["drivers/net/ethernet/sun/sunqe.c", "qe_tx_timeout"],
["drivers/net/ethernet/sun/sunvnet.c", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/sun/sunvnet_common.c", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/sun/sunvnet_common.h", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/synopsys/dwc-xlgmac-net.c", "xlgmac_tx_timeout"],
["drivers/net/ethernet/ti/cpmac.c", "cpmac_tx_timeout"],
["drivers/net/ethernet/ti/cpsw.c", "cpsw_ndo_tx_timeout"],
["drivers/net/ethernet/ti/cpsw_priv.c", "cpsw_ndo_tx_timeout"],
["drivers/net/ethernet/ti/cpsw_priv.h", "cpsw_ndo_tx_timeout"],
["drivers/net/ethernet/ti/davinci_emac.c", "emac_dev_tx_timeout"],
["drivers/net/ethernet/ti/netcp_core.c", "netcp_ndo_tx_timeout"],
["drivers/net/ethernet/ti/tlan.c", "tlan_tx_timeout"],
["drivers/net/ethernet/toshiba/ps3_gelic_net.h", "gelic_net_tx_timeout"],
["drivers/net/ethernet/toshiba/ps3_gelic_net.c", "gelic_net_tx_timeout"],
["drivers/net/ethernet/toshiba/ps3_gelic_wireless.c", "gelic_net_tx_timeout"],
["drivers/net/ethernet/toshiba/spider_net.c", "spider_net_tx_timeout"],
["drivers/net/ethernet/toshiba/tc35815.c", "tc35815_tx_timeout"],
["drivers/net/ethernet/via/via-rhine.c", "rhine_tx_timeout"],
["drivers/net/ethernet/wiznet/w5100.c", "w5100_tx_timeout"],
["drivers/net/ethernet/wiznet/w5300.c", "w5300_tx_timeout"],
["drivers/net/ethernet/xilinx/xilinx_emaclite.c", "xemaclite_tx_timeout"],
["drivers/net/ethernet/xircom/xirc2ps_cs.c", "xirc_tx_timeout"],
["drivers/net/fjes/fjes_main.c", "fjes_tx_retry"],
["drivers/net/slip/slip.c", "sl_tx_timeout"],
["include/linux/usb/usbnet.h", "usbnet_tx_timeout"],
["drivers/net/usb/aqc111.c", "usbnet_tx_timeout"],
["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"],
["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"],
["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"],
["drivers/net/usb/ax88172a.c", "usbnet_tx_timeout"],
["drivers/net/usb/ax88179_178a.c", "usbnet_tx_timeout"],
["drivers/net/usb/catc.c", "catc_tx_timeout"],
["drivers/net/usb/cdc_mbim.c", "usbnet_tx_timeout"],
["drivers/net/usb/cdc_ncm.c", "usbnet_tx_timeout"],
["drivers/net/usb/dm9601.c", "usbnet_tx_timeout"],
["drivers/net/usb/hso.c", "hso_net_tx_timeout"],
["drivers/net/usb/int51x1.c", "usbnet_tx_timeout"],
["drivers/net/usb/ipheth.c", "ipheth_tx_timeout"],
["drivers/net/usb/kaweth.c", "kaweth_tx_timeout"],
["drivers/net/usb/lan78xx.c", "lan78xx_tx_timeout"],
["drivers/net/usb/mcs7830.c", "usbnet_tx_timeout"],
["drivers/net/usb/pegasus.c", "pegasus_tx_timeout"],
["drivers/net/usb/qmi_wwan.c", "usbnet_tx_timeout"],
["drivers/net/usb/r8152.c", "rtl8152_tx_timeout"],
["drivers/net/usb/rndis_host.c", "usbnet_tx_timeout"],
["drivers/net/usb/rtl8150.c", "rtl8150_tx_timeout"],
["drivers/net/usb/sierra_net.c", "usbnet_tx_timeout"],
["drivers/net/usb/smsc75xx.c", "usbnet_tx_timeout"],
["drivers/net/usb/smsc95xx.c", "usbnet_tx_timeout"],
["drivers/net/usb/sr9700.c", "usbnet_tx_timeout"],
["drivers/net/usb/sr9800.c", "usbnet_tx_timeout"],
["drivers/net/usb/usbnet.c", "usbnet_tx_timeout"],
["drivers/net/vmxnet3/vmxnet3_drv.c", "vmxnet3_tx_timeout"],
["drivers/net/wan/cosa.c", "cosa_net_timeout"],
["drivers/net/wan/farsync.c", "fst_tx_timeout"],
["drivers/net/wan/fsl_ucc_hdlc.c", "uhdlc_tx_timeout"],
["drivers/net/wan/lmc/lmc_main.c", "lmc_driver_timeout"],
["drivers/net/wan/x25_asy.c", "x25_asy_timeout"],
["drivers/net/wimax/i2400m/netdev.c", "i2400m_tx_timeout"],
["drivers/net/wireless/intel/ipw2x00/ipw2100.c", "ipw2100_tx_timeout"],
["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"],
["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"],
["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"],
["drivers/net/wireless/intersil/orinoco/main.c", "orinoco_tx_timeout"],
["drivers/net/wireless/intersil/orinoco/orinoco_usb.c", "orinoco_tx_timeout"],
["drivers/net/wireless/intersil/orinoco/orinoco.h", "orinoco_tx_timeout"],
["drivers/net/wireless/intersil/prism54/islpci_dev.c", "islpci_eth_tx_timeout"],
["drivers/net/wireless/intersil/prism54/islpci_eth.c", "islpci_eth_tx_timeout"],
["drivers/net/wireless/intersil/prism54/islpci_eth.h", "islpci_eth_tx_timeout"],
["drivers/net/wireless/marvell/mwifiex/main.c", "mwifiex_tx_timeout"],
["drivers/net/wireless/quantenna/qtnfmac/core.c", "qtnf_netdev_tx_timeout"],
["drivers/net/wireless/quantenna/qtnfmac/core.h", "qtnf_netdev_tx_timeout"],
["drivers/net/wireless/rndis_wlan.c", "usbnet_tx_timeout"],
["drivers/net/wireless/wl3501_cs.c", "wl3501_tx_timeout"],
["drivers/net/wireless/zydas/zd1201.c", "zd1201_tx_timeout"],
["drivers/s390/net/qeth_core.h", "qeth_tx_timeout"],
["drivers/s390/net/qeth_core_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l2_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l2_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l3_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l3_main.c", "qeth_tx_timeout"],
["drivers/staging/ks7010/ks_wlan_net.c", "ks_wlan_tx_timeout"],
["drivers/staging/qlge/qlge_main.c", "qlge_tx_timeout"],
["drivers/staging/rtl8192e/rtl8192e/rtl_core.c", "_rtl92e_tx_timeout"],
["drivers/staging/rtl8192u/r8192U_core.c", "tx_timeout"],
["drivers/staging/unisys/visornic/visornic_main.c", "visornic_xmit_timeout"],
["drivers/staging/wlan-ng/p80211netdev.c", "p80211knetdev_tx_timeout"],
["drivers/tty/n_gsm.c", "gsm_mux_net_tx_timeout"],
["drivers/tty/synclink.c", "hdlcdev_tx_timeout"],
["drivers/tty/synclink_gt.c", "hdlcdev_tx_timeout"],
["drivers/tty/synclinkmp.c", "hdlcdev_tx_timeout"],
["net/atm/lec.c", "lec_tx_timeout"],
["net/bluetooth/bnep/netdev.c", "bnep_net_timeout"]
);
for my $p (@work) {
my @pair = @$p;
my $file = $pair[0];
my $func = $pair[1];
print STDERR $file , ": ", $func,"\n";
our @ARGV = ($file);
while (<ARGV>) {
if (m/($func\s*\(struct\s+net_device\s+\*[A-Za-z_]?[A-Za-z-0-9_]*)(\))/) {
print STDERR "found $1+$2 in $file\n";
}
if (s/($func\s*\(struct\s+net_device\s+\*[A-Za-z_]?[A-Za-z-0-9_]*)(\))/$1, unsigned int txqueue$2/) {
print STDERR "$func found in $file\n";
}
print;
}
}
where the list of files and functions is simply from:
git grep ndo_tx_timeout, with manual addition of headers
in the rare cases where the function is from a header,
then manually changing the few places which actually
call ndo_tx_timeout.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Heiner Kallweit <hkallweit1@gmail.com>
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Shannon Nelson <snelson@pensando.io>
Reviewed-by: Martin Habets <mhabets@solarflare.com>
changes from v9:
fixup a forward declaration
changes from v9:
more leftovers from v3 change
changes from v8:
fix up a missing direct call to timeout
rebased on net-next
changes from v7:
fixup leftovers from v3 change
changes from v6:
fix typo in rtl driver
changes from v5:
add missing files (allow any net device argument name)
changes from v4:
add a missing driver header
changes from v3:
change queue # to unsigned
Changes from v2:
added headers
Changes from v1:
Fix errors found by kbuild:
generalize the pattern a bit, to pick up
a couple of instances missed by the previous
version.
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-12-10 09:23:51 -05:00
|
|
|
static void xge_timeout(struct net_device *ndev, unsigned int txqueue)
|
2017-03-07 17:08:43 -08:00
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
|
|
|
|
rtnl_lock();
|
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
if (!netif_running(ndev))
|
|
|
|
goto out;
|
2017-03-07 17:08:43 -08:00
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
netif_stop_queue(ndev);
|
|
|
|
xge_intr_disable(pdata);
|
|
|
|
napi_disable(&pdata->napi);
|
2017-03-07 17:08:43 -08:00
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
xge_wr_csr(pdata, DMATXCTRL, 0);
|
|
|
|
xge_txc_poll(ndev);
|
|
|
|
xge_free_pending_skb(ndev);
|
|
|
|
xge_wr_csr(pdata, DMATXSTATUS, ~0U);
|
2017-03-07 17:08:43 -08:00
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
xge_setup_desc(pdata->tx_ring);
|
|
|
|
xge_update_tx_desc_addr(pdata);
|
|
|
|
xge_mac_init(pdata);
|
|
|
|
|
|
|
|
napi_enable(&pdata->napi);
|
|
|
|
xge_intr_enable(pdata);
|
|
|
|
xge_mac_enable(pdata);
|
|
|
|
netif_start_queue(ndev);
|
2017-03-07 17:08:43 -08:00
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
out:
|
2017-03-07 17:08:43 -08:00
|
|
|
rtnl_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xge_get_stats64(struct net_device *ndev,
|
|
|
|
struct rtnl_link_stats64 *storage)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata = netdev_priv(ndev);
|
|
|
|
struct xge_stats *stats = &pdata->stats;
|
|
|
|
|
|
|
|
storage->tx_packets += stats->tx_packets;
|
|
|
|
storage->tx_bytes += stats->tx_bytes;
|
|
|
|
|
|
|
|
storage->rx_packets += stats->rx_packets;
|
|
|
|
storage->rx_bytes += stats->rx_bytes;
|
2017-03-07 17:08:44 -08:00
|
|
|
storage->rx_errors += stats->rx_errors;
|
2017-03-07 17:08:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct net_device_ops xgene_ndev_ops = {
|
|
|
|
.ndo_open = xge_open,
|
|
|
|
.ndo_stop = xge_close,
|
2017-03-07 17:08:44 -08:00
|
|
|
.ndo_start_xmit = xge_start_xmit,
|
2017-03-07 17:08:43 -08:00
|
|
|
.ndo_set_mac_address = xge_set_mac_addr,
|
|
|
|
.ndo_tx_timeout = xge_timeout,
|
|
|
|
.ndo_get_stats64 = xge_get_stats64,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int xge_probe(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
struct device *dev = &pdev->dev;
|
|
|
|
struct net_device *ndev;
|
|
|
|
struct xge_pdata *pdata;
|
|
|
|
int ret;
|
|
|
|
|
2017-03-21 18:18:05 -07:00
|
|
|
ndev = alloc_etherdev(sizeof(*pdata));
|
2017-03-07 17:08:43 -08:00
|
|
|
if (!ndev)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
pdata = netdev_priv(ndev);
|
|
|
|
|
|
|
|
pdata->pdev = pdev;
|
|
|
|
pdata->ndev = ndev;
|
|
|
|
SET_NETDEV_DEV(ndev, dev);
|
|
|
|
platform_set_drvdata(pdev, pdata);
|
|
|
|
ndev->netdev_ops = &xgene_ndev_ops;
|
|
|
|
|
|
|
|
ndev->features |= NETIF_F_GSO |
|
|
|
|
NETIF_F_GRO;
|
|
|
|
|
|
|
|
ret = xge_get_resources(pdata);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
ndev->hw_features = ndev->features;
|
2017-03-21 18:18:03 -07:00
|
|
|
xge_set_ethtool_ops(ndev);
|
2017-03-07 17:08:43 -08:00
|
|
|
|
|
|
|
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
|
|
|
|
if (ret) {
|
|
|
|
netdev_err(ndev, "No usable DMA configuration\n");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = xge_init_hw(ndev);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
2017-03-21 18:18:02 -07:00
|
|
|
ret = xge_mdio_config(ndev);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
|
|
|
|
2022-09-27 06:27:53 -07:00
|
|
|
netif_napi_add(ndev, &pdata->napi, xge_napi);
|
2017-03-07 17:08:43 -08:00
|
|
|
|
|
|
|
ret = register_netdev(ndev);
|
|
|
|
if (ret) {
|
|
|
|
netdev_err(ndev, "Failed to register netdev\n");
|
2021-08-21 09:35:23 +02:00
|
|
|
goto err_mdio_remove;
|
2017-03-07 17:08:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2021-08-21 09:35:23 +02:00
|
|
|
err_mdio_remove:
|
|
|
|
xge_mdio_remove(ndev);
|
2017-03-07 17:08:43 -08:00
|
|
|
err:
|
|
|
|
free_netdev(ndev);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-09-18 22:41:39 +02:00
|
|
|
static void xge_remove(struct platform_device *pdev)
|
2017-03-07 17:08:43 -08:00
|
|
|
{
|
|
|
|
struct xge_pdata *pdata;
|
|
|
|
struct net_device *ndev;
|
|
|
|
|
|
|
|
pdata = platform_get_drvdata(pdev);
|
|
|
|
ndev = pdata->ndev;
|
|
|
|
|
|
|
|
rtnl_lock();
|
|
|
|
if (netif_running(ndev))
|
|
|
|
dev_close(ndev);
|
|
|
|
rtnl_unlock();
|
|
|
|
|
2017-03-21 18:18:02 -07:00
|
|
|
xge_mdio_remove(ndev);
|
2017-03-07 17:08:43 -08:00
|
|
|
unregister_netdev(ndev);
|
|
|
|
free_netdev(ndev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void xge_shutdown(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
struct xge_pdata *pdata;
|
|
|
|
|
|
|
|
pdata = platform_get_drvdata(pdev);
|
|
|
|
if (!pdata)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!pdata->ndev)
|
|
|
|
return;
|
|
|
|
|
|
|
|
xge_remove(pdev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct acpi_device_id xge_acpi_match[] = {
|
|
|
|
{ "APMC0D80" },
|
|
|
|
{ }
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(acpi, xge_acpi_match);
|
|
|
|
|
|
|
|
static struct platform_driver xge_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = "xgene-enet-v2",
|
2025-02-25 17:33:33 +01:00
|
|
|
.acpi_match_table = xge_acpi_match,
|
2017-03-07 17:08:43 -08:00
|
|
|
},
|
|
|
|
.probe = xge_probe,
|
2024-10-03 12:01:03 +02:00
|
|
|
.remove = xge_remove,
|
2017-03-07 17:08:43 -08:00
|
|
|
.shutdown = xge_shutdown,
|
|
|
|
};
|
|
|
|
module_platform_driver(xge_driver);
|
|
|
|
|
|
|
|
MODULE_DESCRIPTION("APM X-Gene SoC Ethernet v2 driver");
|
|
|
|
MODULE_AUTHOR("Iyappan Subramanian <isubramanian@apm.com>");
|
|
|
|
MODULE_LICENSE("GPL");
|