aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2008-08-15 17:10:04 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-15 17:10:04 -0400
commit4ba526ced990f4d61ee8d65fe8a6f0745e8e455c (patch)
tree8b20fe7ea098ff1f6d04282adc82b779e403e02b
parentbc7959b2cbb57393b625b423c73e6fd07610257f (diff)
tg3: Fix firmware event timeouts
The git commit 7c5026aa9b81dd45df8d3f4e0be73e485976a8b6 ("tg3: Add link state reporting to UMP firmware") introduced code that waits for previous firmware events to be serviced before attempting to submit a new event. Unfortunately that patch contained a bug that cause the driver to wait 2.5 seconds, rather than 2.5 milliseconds as intended. This patch fixes that bug. This bug revealed that not all firmware versions service driver events though. Since we do not know which versions of the firmware do and don't service these events, the driver needs some way to minimize the effects of the delay. This patch solves the problem by recording a jiffies timestamp when it submits an event to the hardware. If the jiffies counter shows that 2.5 milliseconds have already passed, a wait is not needed and the driver can proceed to submit a new event. 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>
-rw-r--r--drivers/net/tg3.c53
-rw-r--r--drivers/net/tg3.h3
2 files changed, 40 insertions, 16 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index e952b91ca2ac..c26011eaa2be 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1020,15 +1020,43 @@ static void tg3_mdio_fini(struct tg3 *tp)
1020} 1020}
1021 1021
1022/* tp->lock is held. */ 1022/* tp->lock is held. */
1023static inline void tg3_generate_fw_event(struct tg3 *tp)
1024{
1025 u32 val;
1026
1027 val = tr32(GRC_RX_CPU_EVENT);
1028 val |= GRC_RX_CPU_DRIVER_EVENT;
1029 tw32_f(GRC_RX_CPU_EVENT, val);
1030
1031 tp->last_event_jiffies = jiffies;
1032}
1033
1034#define TG3_FW_EVENT_TIMEOUT_USEC 2500
1035
1036/* tp->lock is held. */
1023static void tg3_wait_for_event_ack(struct tg3 *tp) 1037static void tg3_wait_for_event_ack(struct tg3 *tp)
1024{ 1038{
1025 int i; 1039 int i;
1040 unsigned int delay_cnt;
1041 long time_remain;
1042
1043 /* If enough time has passed, no wait is necessary. */
1044 time_remain = (long)(tp->last_event_jiffies + 1 +
1045 usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
1046 (long)jiffies;
1047 if (time_remain < 0)
1048 return;
1026 1049
1027 /* Wait for up to 2.5 milliseconds */ 1050 /* Check if we can shorten the wait time. */
1028 for (i = 0; i < 250000; i++) { 1051 delay_cnt = jiffies_to_usecs(time_remain);
1052 if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
1053 delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
1054 delay_cnt = (delay_cnt >> 3) + 1;
1055
1056 for (i = 0; i < delay_cnt; i++) {
1029 if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) 1057 if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
1030 break; 1058 break;
1031 udelay(10); 1059 udelay(8);
1032 } 1060 }
1033} 1061}
1034 1062
@@ -1077,9 +1105,7 @@ static void tg3_ump_link_report(struct tg3 *tp)
1077 val = 0; 1105 val = 0;
1078 tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); 1106 tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
1079 1107
1080 val = tr32(GRC_RX_CPU_EVENT); 1108 tg3_generate_fw_event(tp);
1081 val |= GRC_RX_CPU_DRIVER_EVENT;
1082 tw32_f(GRC_RX_CPU_EVENT, val);
1083} 1109}
1084 1110
1085static void tg3_link_report(struct tg3 *tp) 1111static void tg3_link_report(struct tg3 *tp)
@@ -5953,6 +5979,7 @@ static int tg3_chip_reset(struct tg3 *tp)
5953 tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); 5979 tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
5954 if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { 5980 if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
5955 tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; 5981 tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
5982 tp->last_event_jiffies = jiffies;
5956 if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) 5983 if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
5957 tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; 5984 tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
5958 } 5985 }
@@ -5966,15 +5993,12 @@ static void tg3_stop_fw(struct tg3 *tp)
5966{ 5993{
5967 if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && 5994 if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
5968 !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { 5995 !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
5969 u32 val;
5970
5971 /* Wait for RX cpu to ACK the previous event. */ 5996 /* Wait for RX cpu to ACK the previous event. */
5972 tg3_wait_for_event_ack(tp); 5997 tg3_wait_for_event_ack(tp);
5973 5998
5974 tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW); 5999 tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
5975 val = tr32(GRC_RX_CPU_EVENT); 6000
5976 val |= GRC_RX_CPU_DRIVER_EVENT; 6001 tg3_generate_fw_event(tp);
5977 tw32(GRC_RX_CPU_EVENT, val);
5978 6002
5979 /* Wait for RX cpu to ACK this event. */ 6003 /* Wait for RX cpu to ACK this event. */
5980 tg3_wait_for_event_ack(tp); 6004 tg3_wait_for_event_ack(tp);
@@ -7864,8 +7888,6 @@ static void tg3_timer(unsigned long __opaque)
7864 if (!--tp->asf_counter) { 7888 if (!--tp->asf_counter) {
7865 if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && 7889 if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
7866 !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { 7890 !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
7867 u32 val;
7868
7869 tg3_wait_for_event_ack(tp); 7891 tg3_wait_for_event_ack(tp);
7870 7892
7871 tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, 7893 tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX,
@@ -7873,9 +7895,8 @@ static void tg3_timer(unsigned long __opaque)
7873 tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); 7895 tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
7874 /* 5 seconds timeout */ 7896 /* 5 seconds timeout */
7875 tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); 7897 tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5);
7876 val = tr32(GRC_RX_CPU_EVENT); 7898
7877 val |= GRC_RX_CPU_DRIVER_EVENT; 7899 tg3_generate_fw_event(tp);
7878 tw32_f(GRC_RX_CPU_EVENT, val);
7879 } 7900 }
7880 tp->asf_counter = tp->asf_multiplier; 7901 tp->asf_counter = tp->asf_multiplier;
7881 } 7902 }
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 377234947e4f..f5b8cab8d4b5 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2432,7 +2432,10 @@ struct tg3 {
2432 struct tg3_ethtool_stats estats; 2432 struct tg3_ethtool_stats estats;
2433 struct tg3_ethtool_stats estats_prev; 2433 struct tg3_ethtool_stats estats_prev;
2434 2434
2435 union {
2435 unsigned long phy_crc_errors; 2436 unsigned long phy_crc_errors;
2437 unsigned long last_event_jiffies;
2438 };
2436 2439
2437 u32 rx_offset; 2440 u32 rx_offset;
2438 u32 tg3_flags; 2441 u32 tg3_flags;