summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
diff options
context:
space:
mode:
authorLendacky, Thomas <Thomas.Lendacky@amd.com>2016-02-17 11:49:28 -0600
committerDavid S. Miller <davem@davemloft.net>2016-02-17 15:22:20 -0500
commitced3fcae693b563b20ee8d2dba966760e6b771d4 (patch)
treed41b051a6ee63f4c7157456c5788454246e186ec /drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
parentc3727d61ea73a1df60bacd0b416e01282a94240b (diff)
amd-xgbe: Mask auto-negotiation interrupts in ISR
Currently the auto-negotiation interrupt handling disables the irq instead of masking off the interrupts. This was done because the phy library was originally used to read and write the PCS registers, which could not be performed in interrupt context. Now that the phy library is no longer used to read and write the PCS registers the interrupts can be masked off in the interrupt service routine eliminating the need to call disable_irq/enable_irq. This also requires changing the protection mutex to a spinlock. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/amd/xgbe/xgbe-mdio.c')
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-mdio.c53
1 files changed, 29 insertions, 24 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 446058081866..84c5d296d13e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -6,7 +6,7 @@
*
* License 1: GPLv2
*
- * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
*
* This file is free software; you may copy, redistribute and/or modify
* it under the terms of the GNU General Public License as published by
@@ -56,7 +56,7 @@
*
* License 2: Modified BSD
*
- * Copyright (c) 2014 Advanced Micro Devices, Inc.
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -626,10 +626,22 @@ static irqreturn_t xgbe_an_isr(int irq, void *data)
netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
- /* Interrupt reason must be read and cleared outside of IRQ context */
- disable_irq_nosync(pdata->an_irq);
+ /* Disable AN interrupts */
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+
+ /* Save the interrupt(s) that fired */
+ pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
- queue_work(pdata->an_workqueue, &pdata->an_irq_work);
+ if (pdata->an_int) {
+ /* Clear the interrupt(s) that fired and process them */
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
+
+ queue_work(pdata->an_workqueue, &pdata->an_irq_work);
+ } else {
+ /* Enable AN interrupts */
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK,
+ XGBE_AN_INT_MASK);
+ }
return IRQ_HANDLED;
}
@@ -673,34 +685,26 @@ static void xgbe_an_state_machine(struct work_struct *work)
struct xgbe_prv_data,
an_work);
enum xgbe_an cur_state = pdata->an_state;
- unsigned int int_reg, int_mask;
mutex_lock(&pdata->an_mutex);
- /* Read the interrupt */
- int_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
- if (!int_reg)
+ if (!pdata->an_int)
goto out;
next_int:
- if (int_reg & XGBE_AN_PG_RCV) {
+ if (pdata->an_int & XGBE_AN_PG_RCV) {
pdata->an_state = XGBE_AN_PAGE_RECEIVED;
- int_mask = XGBE_AN_PG_RCV;
- } else if (int_reg & XGBE_AN_INC_LINK) {
+ pdata->an_int &= ~XGBE_AN_PG_RCV;
+ } else if (pdata->an_int & XGBE_AN_INC_LINK) {
pdata->an_state = XGBE_AN_INCOMPAT_LINK;
- int_mask = XGBE_AN_INC_LINK;
- } else if (int_reg & XGBE_AN_INT_CMPLT) {
+ pdata->an_int &= ~XGBE_AN_INC_LINK;
+ } else if (pdata->an_int & XGBE_AN_INT_CMPLT) {
pdata->an_state = XGBE_AN_COMPLETE;
- int_mask = XGBE_AN_INT_CMPLT;
+ pdata->an_int &= ~XGBE_AN_INT_CMPLT;
} else {
pdata->an_state = XGBE_AN_ERROR;
- int_mask = 0;
}
- /* Clear the interrupt to be processed */
- int_reg &= ~int_mask;
- XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, int_reg);
-
pdata->an_result = pdata->an_state;
again:
@@ -740,14 +744,14 @@ again:
}
if (pdata->an_state == XGBE_AN_NO_LINK) {
- int_reg = 0;
+ pdata->an_int = 0;
XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
} else if (pdata->an_state == XGBE_AN_ERROR) {
netdev_err(pdata->netdev,
"error during auto-negotiation, state=%u\n",
cur_state);
- int_reg = 0;
+ pdata->an_int = 0;
XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
}
@@ -765,11 +769,12 @@ again:
if (cur_state != pdata->an_state)
goto again;
- if (int_reg)
+ if (pdata->an_int)
goto next_int;
out:
- enable_irq(pdata->an_irq);
+ /* Enable AN interrupts on the way out */
+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK);
mutex_unlock(&pdata->an_mutex);
}