diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2012-07-16 16:24:00 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-16 23:10:30 -0700 |
commit | b65a372bbc74924b0ce564a3338d9e139367bd3d (patch) | |
tree | 0f18012c05fd76c1c2be0072eb2f4d8b48544a23 /drivers | |
parent | 165f4d1cb3d7a10c5bc8c0fdae63323354f5a225 (diff) |
tg3: Add common function tg3_ape_event_lock()
by refactoring code in tg3_ape_send_event(). The common function will
be used in subsequent patches.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/broadcom/tg3.c | 56 |
1 files changed, 32 insertions, 24 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 45dc6f5c52c..5dda3ced90e 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -731,44 +731,52 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) tg3_ape_write32(tp, gnt + 4 * locknum, bit); } -static void tg3_ape_send_event(struct tg3 *tp, u32 event) +static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us) { - int i; u32 apedata; - /* NCSI does not support APE events */ - if (tg3_flag(tp, APE_HAS_NCSI)) - return; + while (timeout_us) { + if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) + return -EBUSY; + + apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + break; + + tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); + + udelay(10); + timeout_us -= (timeout_us > 10) ? 10 : timeout_us; + } + + return timeout_us ? 0 : -EBUSY; +} + +static int tg3_ape_send_event(struct tg3 *tp, u32 event) +{ + int err; + u32 apedata; apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG); if (apedata != APE_SEG_SIG_MAGIC) - return; + return -EAGAIN; apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); if (!(apedata & APE_FW_STATUS_READY)) - return; + return -EAGAIN; /* Wait for up to 1 millisecond for APE to service previous event. */ - for (i = 0; i < 10; i++) { - if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM)) - return; - - apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS); - - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, - event | APE_EVENT_STATUS_EVENT_PENDING); + err = tg3_ape_event_lock(tp, 1000); + if (err) + return err; - tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); + tg3_ape_write32(tp, TG3_APE_EVENT_STATUS, + event | APE_EVENT_STATUS_EVENT_PENDING); - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - break; + tg3_ape_unlock(tp, TG3_APE_LOCK_MEM); + tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); - udelay(100); - } - - if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) - tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1); + return 0; } static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) |