|
@@ -1019,16 +1019,44 @@ static void tg3_mdio_fini(struct tg3 *tp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* tp->lock is held. */
|
|
|
+static inline void tg3_generate_fw_event(struct tg3 *tp)
|
|
|
+{
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ val = tr32(GRC_RX_CPU_EVENT);
|
|
|
+ val |= GRC_RX_CPU_DRIVER_EVENT;
|
|
|
+ tw32_f(GRC_RX_CPU_EVENT, val);
|
|
|
+
|
|
|
+ tp->last_event_jiffies = jiffies;
|
|
|
+}
|
|
|
+
|
|
|
+#define TG3_FW_EVENT_TIMEOUT_USEC 2500
|
|
|
+
|
|
|
/* tp->lock is held. */
|
|
|
static void tg3_wait_for_event_ack(struct tg3 *tp)
|
|
|
{
|
|
|
int i;
|
|
|
+ unsigned int delay_cnt;
|
|
|
+ long time_remain;
|
|
|
+
|
|
|
+ /* If enough time has passed, no wait is necessary. */
|
|
|
+ time_remain = (long)(tp->last_event_jiffies + 1 +
|
|
|
+ usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
|
|
|
+ (long)jiffies;
|
|
|
+ if (time_remain < 0)
|
|
|
+ return;
|
|
|
|
|
|
- /* Wait for up to 2.5 milliseconds */
|
|
|
- for (i = 0; i < 250000; i++) {
|
|
|
+ /* Check if we can shorten the wait time. */
|
|
|
+ delay_cnt = jiffies_to_usecs(time_remain);
|
|
|
+ if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
|
|
|
+ delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
|
|
|
+ delay_cnt = (delay_cnt >> 3) + 1;
|
|
|
+
|
|
|
+ for (i = 0; i < delay_cnt; i++) {
|
|
|
if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
|
|
|
break;
|
|
|
- udelay(10);
|
|
|
+ udelay(8);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1077,9 +1105,7 @@ static void tg3_ump_link_report(struct tg3 *tp)
|
|
|
val = 0;
|
|
|
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
|
|
|
|
|
|
- val = tr32(GRC_RX_CPU_EVENT);
|
|
|
- val |= GRC_RX_CPU_DRIVER_EVENT;
|
|
|
- tw32_f(GRC_RX_CPU_EVENT, val);
|
|
|
+ tg3_generate_fw_event(tp);
|
|
|
}
|
|
|
|
|
|
static void tg3_link_report(struct tg3 *tp)
|
|
@@ -5953,6 +5979,7 @@ static int tg3_chip_reset(struct tg3 *tp)
|
|
|
tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
|
|
|
if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
|
|
|
tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
|
|
|
+ tp->last_event_jiffies = jiffies;
|
|
|
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
|
|
|
tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
|
|
|
}
|
|
@@ -5966,15 +5993,12 @@ static void tg3_stop_fw(struct tg3 *tp)
|
|
|
{
|
|
|
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
|
|
|
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
|
|
|
- u32 val;
|
|
|
-
|
|
|
/* Wait for RX cpu to ACK the previous event. */
|
|
|
tg3_wait_for_event_ack(tp);
|
|
|
|
|
|
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
|
|
|
- val = tr32(GRC_RX_CPU_EVENT);
|
|
|
- val |= GRC_RX_CPU_DRIVER_EVENT;
|
|
|
- tw32(GRC_RX_CPU_EVENT, val);
|
|
|
+
|
|
|
+ tg3_generate_fw_event(tp);
|
|
|
|
|
|
/* Wait for RX cpu to ACK this event. */
|
|
|
tg3_wait_for_event_ack(tp);
|
|
@@ -7864,8 +7888,6 @@ static void tg3_timer(unsigned long __opaque)
|
|
|
if (!--tp->asf_counter) {
|
|
|
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
|
|
|
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
|
|
|
- u32 val;
|
|
|
-
|
|
|
tg3_wait_for_event_ack(tp);
|
|
|
|
|
|
tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
|
|
@@ -7873,9 +7895,8 @@ static void tg3_timer(unsigned long __opaque)
|
|
|
tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
|
|
|
/* 5 seconds timeout */
|
|
|
tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
|
|
|
- val = tr32(GRC_RX_CPU_EVENT);
|
|
|
- val |= GRC_RX_CPU_DRIVER_EVENT;
|
|
|
- tw32_f(GRC_RX_CPU_EVENT, val);
|
|
|
+
|
|
|
+ tg3_generate_fw_event(tp);
|
|
|
}
|
|
|
tp->asf_counter = tp->asf_multiplier;
|
|
|
}
|