Commit 58eaa8ab authored by Gerhard Engleder's avatar Gerhard Engleder Committed by David S. Miller

tsnep: Move interrupt from device to queue

For multiple queues multiple interrupts shall be used. Therefore, rework
global interrupt to per queue interrupt.

Every interrupt name shall contain interface name and queue information.
To get a valid interface name, the interrupt request needs to by done
during open like in other drivers. Additionally, this allows the removal
of some initialisation checks in the interrupt handler.
Signed-off-by: default avatarGerhard Engleder <gerhard@engleder-embedded.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 60e1b494
...@@ -55,6 +55,7 @@ struct tsnep_tx_entry { ...@@ -55,6 +55,7 @@ struct tsnep_tx_entry {
struct tsnep_tx { struct tsnep_tx {
struct tsnep_adapter *adapter; struct tsnep_adapter *adapter;
void __iomem *addr; void __iomem *addr;
int queue_index;
void *page[TSNEP_RING_PAGE_COUNT]; void *page[TSNEP_RING_PAGE_COUNT];
dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT]; dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT];
...@@ -105,12 +106,14 @@ struct tsnep_rx { ...@@ -105,12 +106,14 @@ struct tsnep_rx {
struct tsnep_queue { struct tsnep_queue {
struct tsnep_adapter *adapter; struct tsnep_adapter *adapter;
char name[IFNAMSIZ + 9];
struct tsnep_tx *tx; struct tsnep_tx *tx;
struct tsnep_rx *rx; struct tsnep_rx *rx;
struct napi_struct napi; struct napi_struct napi;
int irq;
u32 irq_mask; u32 irq_mask;
}; };
...@@ -126,7 +129,6 @@ struct tsnep_adapter { ...@@ -126,7 +129,6 @@ struct tsnep_adapter {
struct platform_device *pdev; struct platform_device *pdev;
struct device *dmadev; struct device *dmadev;
void __iomem *addr; void __iomem *addr;
int irq;
bool gate_control; bool gate_control;
/* gate control lock */ /* gate control lock */
......
...@@ -60,18 +60,25 @@ static irqreturn_t tsnep_irq(int irq, void *arg) ...@@ -60,18 +60,25 @@ static irqreturn_t tsnep_irq(int irq, void *arg)
iowrite32(active, adapter->addr + ECM_INT_ACKNOWLEDGE); iowrite32(active, adapter->addr + ECM_INT_ACKNOWLEDGE);
/* handle link interrupt */ /* handle link interrupt */
if ((active & ECM_INT_LINK) != 0) { if ((active & ECM_INT_LINK) != 0)
if (adapter->netdev->phydev)
phy_mac_interrupt(adapter->netdev->phydev); phy_mac_interrupt(adapter->netdev->phydev);
}
/* handle TX/RX queue 0 interrupt */ /* handle TX/RX queue 0 interrupt */
if ((active & adapter->queue[0].irq_mask) != 0) { if ((active & adapter->queue[0].irq_mask) != 0) {
if (adapter->netdev) {
tsnep_disable_irq(adapter, adapter->queue[0].irq_mask); tsnep_disable_irq(adapter, adapter->queue[0].irq_mask);
napi_schedule(&adapter->queue[0].napi); napi_schedule(&adapter->queue[0].napi);
} }
}
return IRQ_HANDLED;
}
static irqreturn_t tsnep_irq_txrx(int irq, void *arg)
{
struct tsnep_queue *queue = arg;
/* handle TX/RX queue interrupt */
tsnep_disable_irq(queue->adapter, queue->irq_mask);
napi_schedule(&queue->napi);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -536,7 +543,7 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget) ...@@ -536,7 +543,7 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
} }
static int tsnep_tx_open(struct tsnep_adapter *adapter, void __iomem *addr, static int tsnep_tx_open(struct tsnep_adapter *adapter, void __iomem *addr,
struct tsnep_tx *tx) int queue_index, struct tsnep_tx *tx)
{ {
dma_addr_t dma; dma_addr_t dma;
int retval; int retval;
...@@ -544,6 +551,7 @@ static int tsnep_tx_open(struct tsnep_adapter *adapter, void __iomem *addr, ...@@ -544,6 +551,7 @@ static int tsnep_tx_open(struct tsnep_adapter *adapter, void __iomem *addr,
memset(tx, 0, sizeof(*tx)); memset(tx, 0, sizeof(*tx));
tx->adapter = adapter; tx->adapter = adapter;
tx->addr = addr; tx->addr = addr;
tx->queue_index = queue_index;
retval = tsnep_tx_ring_init(tx); retval = tsnep_tx_ring_init(tx);
if (retval) if (retval)
...@@ -854,6 +862,56 @@ static int tsnep_poll(struct napi_struct *napi, int budget) ...@@ -854,6 +862,56 @@ static int tsnep_poll(struct napi_struct *napi, int budget)
return min(done, budget - 1); return min(done, budget - 1);
} }
static int tsnep_request_irq(struct tsnep_queue *queue, bool first)
{
const char *name = netdev_name(queue->adapter->netdev);
irq_handler_t handler;
void *dev;
int retval;
if (first) {
sprintf(queue->name, "%s-mac", name);
handler = tsnep_irq;
dev = queue->adapter;
} else {
if (queue->tx && queue->rx)
sprintf(queue->name, "%s-txrx-%d", name,
queue->rx->queue_index);
else if (queue->tx)
sprintf(queue->name, "%s-tx-%d", name,
queue->tx->queue_index);
else
sprintf(queue->name, "%s-rx-%d", name,
queue->rx->queue_index);
handler = tsnep_irq_txrx;
dev = queue;
}
retval = request_irq(queue->irq, handler, 0, queue->name, dev);
if (retval) {
/* if name is empty, then interrupt won't be freed */
memset(queue->name, 0, sizeof(queue->name));
}
return retval;
}
static void tsnep_free_irq(struct tsnep_queue *queue, bool first)
{
void *dev;
if (!strlen(queue->name))
return;
if (first)
dev = queue->adapter;
else
dev = queue;
free_irq(queue->irq, dev);
memset(queue->name, 0, sizeof(queue->name));
}
static int tsnep_netdev_open(struct net_device *netdev) static int tsnep_netdev_open(struct net_device *netdev)
{ {
struct tsnep_adapter *adapter = netdev_priv(netdev); struct tsnep_adapter *adapter = netdev_priv(netdev);
...@@ -863,15 +921,11 @@ static int tsnep_netdev_open(struct net_device *netdev) ...@@ -863,15 +921,11 @@ static int tsnep_netdev_open(struct net_device *netdev)
int rx_queue_index = 0; int rx_queue_index = 0;
int retval; int retval;
retval = tsnep_phy_open(adapter);
if (retval)
return retval;
for (i = 0; i < adapter->num_queues; i++) { for (i = 0; i < adapter->num_queues; i++) {
adapter->queue[i].adapter = adapter; adapter->queue[i].adapter = adapter;
if (adapter->queue[i].tx) { if (adapter->queue[i].tx) {
addr = adapter->addr + TSNEP_QUEUE(tx_queue_index); addr = adapter->addr + TSNEP_QUEUE(tx_queue_index);
retval = tsnep_tx_open(adapter, addr, retval = tsnep_tx_open(adapter, addr, tx_queue_index,
adapter->queue[i].tx); adapter->queue[i].tx);
if (retval) if (retval)
goto failed; goto failed;
...@@ -886,6 +940,14 @@ static int tsnep_netdev_open(struct net_device *netdev) ...@@ -886,6 +940,14 @@ static int tsnep_netdev_open(struct net_device *netdev)
goto failed; goto failed;
rx_queue_index++; rx_queue_index++;
} }
retval = tsnep_request_irq(&adapter->queue[i], i == 0);
if (retval) {
netif_err(adapter, drv, adapter->netdev,
"can't get assigned irq %d.\n",
adapter->queue[i].irq);
goto failed;
}
} }
retval = netif_set_real_num_tx_queues(adapter->netdev, retval = netif_set_real_num_tx_queues(adapter->netdev,
...@@ -897,6 +959,11 @@ static int tsnep_netdev_open(struct net_device *netdev) ...@@ -897,6 +959,11 @@ static int tsnep_netdev_open(struct net_device *netdev)
if (retval) if (retval)
goto failed; goto failed;
tsnep_enable_irq(adapter, ECM_INT_LINK);
retval = tsnep_phy_open(adapter);
if (retval)
goto phy_failed;
for (i = 0; i < adapter->num_queues; i++) { for (i = 0; i < adapter->num_queues; i++) {
netif_napi_add(adapter->netdev, &adapter->queue[i].napi, netif_napi_add(adapter->netdev, &adapter->queue[i].napi,
tsnep_poll); tsnep_poll);
...@@ -907,14 +974,18 @@ static int tsnep_netdev_open(struct net_device *netdev) ...@@ -907,14 +974,18 @@ static int tsnep_netdev_open(struct net_device *netdev)
return 0; return 0;
phy_failed:
tsnep_disable_irq(adapter, ECM_INT_LINK);
tsnep_phy_close(adapter);
failed: failed:
for (i = 0; i < adapter->num_queues; i++) { for (i = 0; i < adapter->num_queues; i++) {
tsnep_free_irq(&adapter->queue[i], i == 0);
if (adapter->queue[i].rx) if (adapter->queue[i].rx)
tsnep_rx_close(adapter->queue[i].rx); tsnep_rx_close(adapter->queue[i].rx);
if (adapter->queue[i].tx) if (adapter->queue[i].tx)
tsnep_tx_close(adapter->queue[i].tx); tsnep_tx_close(adapter->queue[i].tx);
} }
tsnep_phy_close(adapter);
return retval; return retval;
} }
...@@ -923,20 +994,23 @@ static int tsnep_netdev_close(struct net_device *netdev) ...@@ -923,20 +994,23 @@ static int tsnep_netdev_close(struct net_device *netdev)
struct tsnep_adapter *adapter = netdev_priv(netdev); struct tsnep_adapter *adapter = netdev_priv(netdev);
int i; int i;
tsnep_disable_irq(adapter, ECM_INT_LINK);
tsnep_phy_close(adapter);
for (i = 0; i < adapter->num_queues; i++) { for (i = 0; i < adapter->num_queues; i++) {
tsnep_disable_irq(adapter, adapter->queue[i].irq_mask); tsnep_disable_irq(adapter, adapter->queue[i].irq_mask);
napi_disable(&adapter->queue[i].napi); napi_disable(&adapter->queue[i].napi);
netif_napi_del(&adapter->queue[i].napi); netif_napi_del(&adapter->queue[i].napi);
tsnep_free_irq(&adapter->queue[i], i == 0);
if (adapter->queue[i].rx) if (adapter->queue[i].rx)
tsnep_rx_close(adapter->queue[i].rx); tsnep_rx_close(adapter->queue[i].rx);
if (adapter->queue[i].tx) if (adapter->queue[i].tx)
tsnep_tx_close(adapter->queue[i].tx); tsnep_tx_close(adapter->queue[i].tx);
} }
tsnep_phy_close(adapter);
return 0; return 0;
} }
...@@ -1225,10 +1299,8 @@ static int tsnep_probe(struct platform_device *pdev) ...@@ -1225,10 +1299,8 @@ static int tsnep_probe(struct platform_device *pdev)
adapter->addr = devm_ioremap_resource(&pdev->dev, io); adapter->addr = devm_ioremap_resource(&pdev->dev, io);
if (IS_ERR(adapter->addr)) if (IS_ERR(adapter->addr))
return PTR_ERR(adapter->addr); return PTR_ERR(adapter->addr);
adapter->irq = platform_get_irq(pdev, 0);
netdev->mem_start = io->start; netdev->mem_start = io->start;
netdev->mem_end = io->end; netdev->mem_end = io->end;
netdev->irq = adapter->irq;
type = ioread32(adapter->addr + ECM_TYPE); type = ioread32(adapter->addr + ECM_TYPE);
revision = (type & ECM_REVISION_MASK) >> ECM_REVISION_SHIFT; revision = (type & ECM_REVISION_MASK) >> ECM_REVISION_SHIFT;
...@@ -1238,10 +1310,14 @@ static int tsnep_probe(struct platform_device *pdev) ...@@ -1238,10 +1310,14 @@ static int tsnep_probe(struct platform_device *pdev)
adapter->num_tx_queues = TSNEP_QUEUES; adapter->num_tx_queues = TSNEP_QUEUES;
adapter->num_rx_queues = TSNEP_QUEUES; adapter->num_rx_queues = TSNEP_QUEUES;
adapter->num_queues = TSNEP_QUEUES; adapter->num_queues = TSNEP_QUEUES;
adapter->queue[0].irq = platform_get_irq(pdev, 0);
adapter->queue[0].tx = &adapter->tx[0]; adapter->queue[0].tx = &adapter->tx[0];
adapter->queue[0].rx = &adapter->rx[0]; adapter->queue[0].rx = &adapter->rx[0];
adapter->queue[0].irq_mask = ECM_INT_TX_0 | ECM_INT_RX_0; adapter->queue[0].irq_mask = ECM_INT_TX_0 | ECM_INT_RX_0;
netdev->irq = adapter->queue[0].irq;
tsnep_disable_irq(adapter, ECM_INT_ALL);
retval = dma_set_mask_and_coherent(&adapter->pdev->dev, retval = dma_set_mask_and_coherent(&adapter->pdev->dev,
DMA_BIT_MASK(64)); DMA_BIT_MASK(64));
if (retval) { if (retval) {
...@@ -1249,19 +1325,9 @@ static int tsnep_probe(struct platform_device *pdev) ...@@ -1249,19 +1325,9 @@ static int tsnep_probe(struct platform_device *pdev)
return retval; return retval;
} }
tsnep_disable_irq(adapter, ECM_INT_ALL);
retval = devm_request_irq(&adapter->pdev->dev, adapter->irq, tsnep_irq,
0, TSNEP, adapter);
if (retval != 0) {
dev_err(&adapter->pdev->dev, "can't get assigned irq %d.\n",
adapter->irq);
return retval;
}
tsnep_enable_irq(adapter, ECM_INT_LINK);
retval = tsnep_mac_init(adapter); retval = tsnep_mac_init(adapter);
if (retval) if (retval)
goto mac_init_failed; return retval;
retval = tsnep_mdio_init(adapter); retval = tsnep_mdio_init(adapter);
if (retval) if (retval)
...@@ -1307,8 +1373,6 @@ static int tsnep_probe(struct platform_device *pdev) ...@@ -1307,8 +1373,6 @@ static int tsnep_probe(struct platform_device *pdev)
if (adapter->mdiobus) if (adapter->mdiobus)
mdiobus_unregister(adapter->mdiobus); mdiobus_unregister(adapter->mdiobus);
mdio_init_failed: mdio_init_failed:
mac_init_failed:
tsnep_disable_irq(adapter, ECM_INT_ALL);
return retval; return retval;
} }
......
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