aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2008-09-11 22:55:32 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-09-24 18:54:49 -0400
commitcf8280ee7be3aaf44d32e389f15c725b850e5e32 (patch)
tree3511ef0b19370597c7bd5fbe43a74d563522adeb /drivers
parentce94bf469edf84228771b58489944cf654aeb496 (diff)
ixgbe: Update watchdog thread to accomodate longerlink_up events
This patch updates the link_up code and watchdog thread so that link_up doesn't cause stack overflows due to long waits in interrupt context. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ixgbe/ixgbe.h6
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c29
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c129
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h3
5 files changed, 118 insertions, 51 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 90b53830196c..2b827a67c9c5 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -309,6 +309,12 @@ struct ixgbe_adapter {
309 u64 lro_aggregated; 309 u64 lro_aggregated;
310 u64 lro_flushed; 310 u64 lro_flushed;
311 u64 lro_no_desc; 311 u64 lro_no_desc;
312
313 u32 link_speed;
314 bool link_up;
315 unsigned long link_check_timeout;
316
317 struct work_struct watchdog_task;
312}; 318};
313 319
314enum ixbge_state_t { 320enum ixbge_state_t {
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index ba09063260d9..1e014bcc72d9 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -47,7 +47,8 @@ static s32 ixgbe_get_copper_link_settings_82598(struct ixgbe_hw *hw,
47static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); 47static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw);
48static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw); 48static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw);
49static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, 49static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed,
50 bool *link_up); 50 bool *link_up,
51 bool link_up_wait_to_complete);
51static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, u32 speed, 52static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, u32 speed,
52 bool autoneg, 53 bool autoneg,
53 bool autoneg_wait_to_complete); 54 bool autoneg_wait_to_complete);
@@ -277,20 +278,36 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
277 * @hw: pointer to hardware structure 278 * @hw: pointer to hardware structure
278 * @speed: pointer to link speed 279 * @speed: pointer to link speed
279 * @link_up: true is link is up, false otherwise 280 * @link_up: true is link is up, false otherwise
281 * @link_up_wait_to_complete: bool used to wait for link up or not
280 * 282 *
281 * Reads the links register to determine if link is up and the current speed 283 * Reads the links register to determine if link is up and the current speed
282 **/ 284 **/
283static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, 285static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed,
284 bool *link_up) 286 bool *link_up,
287 bool link_up_wait_to_complete)
285{ 288{
286 u32 links_reg; 289 u32 links_reg;
290 u32 i;
287 291
288 links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); 292 links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
289 293
290 if (links_reg & IXGBE_LINKS_UP) 294 if (link_up_wait_to_complete) {
291 *link_up = true; 295 for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
292 else 296 if (links_reg & IXGBE_LINKS_UP) {
293 *link_up = false; 297 *link_up = true;
298 break;
299 } else {
300 *link_up = false;
301 }
302 msleep(100);
303 links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
304 }
305 } else {
306 if (links_reg & IXGBE_LINKS_UP)
307 *link_up = true;
308 else
309 *link_up = false;
310 }
294 311
295 if (links_reg & IXGBE_LINKS_SPEED) 312 if (links_reg & IXGBE_LINKS_SPEED)
296 *speed = IXGBE_LINK_SPEED_10GB_FULL; 313 *speed = IXGBE_LINK_SPEED_10GB_FULL;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 61c000e23094..8f0e3f93e6b1 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -130,7 +130,7 @@ static int ixgbe_get_settings(struct net_device *netdev,
130 ecmd->port = PORT_FIBRE; 130 ecmd->port = PORT_FIBRE;
131 } 131 }
132 132
133 adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up); 133 adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up, false);
134 if (link_up) { 134 if (link_up) {
135 ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? 135 ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
136 SPEED_10000 : SPEED_1000; 136 SPEED_10000 : SPEED_1000;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 904819586e2a..036393e5383e 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -902,6 +902,20 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
902 return; 902 return;
903} 903}
904 904
905
906static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
907{
908 struct ixgbe_hw *hw = &adapter->hw;
909
910 adapter->lsc_int++;
911 adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
912 adapter->link_check_timeout = jiffies;
913 if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
914 IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
915 schedule_work(&adapter->watchdog_task);
916 }
917}
918
905static irqreturn_t ixgbe_msix_lsc(int irq, void *data) 919static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
906{ 920{
907 struct net_device *netdev = data; 921 struct net_device *netdev = data;
@@ -909,11 +923,8 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
909 struct ixgbe_hw *hw = &adapter->hw; 923 struct ixgbe_hw *hw = &adapter->hw;
910 u32 eicr = IXGBE_READ_REG(hw, IXGBE_EICR); 924 u32 eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
911 925
912 if (eicr & IXGBE_EICR_LSC) { 926 if (eicr & IXGBE_EICR_LSC)
913 adapter->lsc_int++; 927 ixgbe_check_lsc(adapter);
914 if (!test_bit(__IXGBE_DOWN, &adapter->state))
915 mod_timer(&adapter->watchdog_timer, jiffies);
916 }
917 928
918 if (!test_bit(__IXGBE_DOWN, &adapter->state)) 929 if (!test_bit(__IXGBE_DOWN, &adapter->state))
919 IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); 930 IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
@@ -1237,12 +1248,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
1237 if (!eicr) 1248 if (!eicr)
1238 return IRQ_NONE; /* Not our interrupt */ 1249 return IRQ_NONE; /* Not our interrupt */
1239 1250
1240 if (eicr & IXGBE_EICR_LSC) { 1251 if (eicr & IXGBE_EICR_LSC)
1241 adapter->lsc_int++; 1252 ixgbe_check_lsc(adapter);
1242 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1243 mod_timer(&adapter->watchdog_timer, jiffies);
1244 }
1245
1246 1253
1247 if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) { 1254 if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) {
1248 adapter->tx_ring[0].total_packets = 0; 1255 adapter->tx_ring[0].total_packets = 0;
@@ -1897,6 +1904,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
1897 1904
1898 /* bring the link up in the watchdog, this could race with our first 1905 /* bring the link up in the watchdog, this could race with our first
1899 * link up interrupt but shouldn't be a problem */ 1906 * link up interrupt but shouldn't be a problem */
1907 adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
1908 adapter->link_check_timeout = jiffies;
1900 mod_timer(&adapter->watchdog_timer, jiffies); 1909 mod_timer(&adapter->watchdog_timer, jiffies);
1901 return 0; 1910 return 0;
1902} 1911}
@@ -2098,6 +2107,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
2098 2107
2099 ixgbe_napi_disable_all(adapter); 2108 ixgbe_napi_disable_all(adapter);
2100 del_timer_sync(&adapter->watchdog_timer); 2109 del_timer_sync(&adapter->watchdog_timer);
2110 cancel_work_sync(&adapter->watchdog_task);
2101 2111
2102 netif_carrier_off(netdev); 2112 netif_carrier_off(netdev);
2103 netif_tx_stop_all_queues(netdev); 2113 netif_tx_stop_all_queues(netdev);
@@ -3010,27 +3020,74 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
3010static void ixgbe_watchdog(unsigned long data) 3020static void ixgbe_watchdog(unsigned long data)
3011{ 3021{
3012 struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; 3022 struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
3013 struct net_device *netdev = adapter->netdev; 3023 struct ixgbe_hw *hw = &adapter->hw;
3014 bool link_up; 3024
3015 u32 link_speed = 0; 3025 /* Do the watchdog outside of interrupt context due to the lovely
3026 * delays that some of the newer hardware requires */
3027 if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
3028 /* Cause software interrupt to ensure rx rings are cleaned */
3029 if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
3030 u32 eics =
3031 (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1;
3032 IXGBE_WRITE_REG(hw, IXGBE_EICS, eics);
3033 } else {
3034 /* For legacy and MSI interrupts don't set any bits that
3035 * are enabled for EIAM, because this operation would
3036 * set *both* EIMS and EICS for any bit in EIAM */
3037 IXGBE_WRITE_REG(hw, IXGBE_EICS,
3038 (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
3039 }
3040 /* Reset the timer */
3041 mod_timer(&adapter->watchdog_timer,
3042 round_jiffies(jiffies + 2 * HZ));
3043 }
3016 3044
3017 adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up); 3045 schedule_work(&adapter->watchdog_task);
3046}
3047
3048/**
3049 * ixgbe_watchdog_task - worker thread to bring link up
3050 * @work: pointer to work_struct containing our data
3051 **/
3052static void ixgbe_watchdog_task(struct work_struct *work)
3053{
3054 struct ixgbe_adapter *adapter = container_of(work,
3055 struct ixgbe_adapter,
3056 watchdog_task);
3057 struct net_device *netdev = adapter->netdev;
3058 struct ixgbe_hw *hw = &adapter->hw;
3059 u32 link_speed = adapter->link_speed;
3060 bool link_up = adapter->link_up;
3061
3062 adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
3063
3064 if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
3065 hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
3066 if (link_up ||
3067 time_after(jiffies, (adapter->link_check_timeout +
3068 IXGBE_TRY_LINK_TIMEOUT))) {
3069 IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
3070 adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
3071 }
3072 adapter->link_up = link_up;
3073 adapter->link_speed = link_speed;
3074 }
3018 3075
3019 if (link_up) { 3076 if (link_up) {
3020 if (!netif_carrier_ok(netdev)) { 3077 if (!netif_carrier_ok(netdev)) {
3021 u32 frctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); 3078 u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
3022 u32 rmcs = IXGBE_READ_REG(&adapter->hw, IXGBE_RMCS); 3079 u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
3023#define FLOW_RX (frctl & IXGBE_FCTRL_RFCE) 3080#define FLOW_RX (frctl & IXGBE_FCTRL_RFCE)
3024#define FLOW_TX (rmcs & IXGBE_RMCS_TFCE_802_3X) 3081#define FLOW_TX (rmcs & IXGBE_RMCS_TFCE_802_3X)
3025 DPRINTK(LINK, INFO, "NIC Link is Up %s, " 3082 DPRINTK(LINK, INFO, "NIC Link is Up %s, "
3026 "Flow Control: %s\n", 3083 "Flow Control: %s\n",
3027 (link_speed == IXGBE_LINK_SPEED_10GB_FULL ? 3084 (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
3028 "10 Gbps" : 3085 "10 Gbps" :
3029 (link_speed == IXGBE_LINK_SPEED_1GB_FULL ? 3086 (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
3030 "1 Gbps" : "unknown speed")), 3087 "1 Gbps" : "unknown speed")),
3031 ((FLOW_RX && FLOW_TX) ? "RX/TX" : 3088 ((FLOW_RX && FLOW_TX) ? "RX/TX" :
3032 (FLOW_RX ? "RX" : 3089 (FLOW_RX ? "RX" :
3033 (FLOW_TX ? "TX" : "None")))); 3090 (FLOW_TX ? "TX" : "None"))));
3034 3091
3035 netif_carrier_on(netdev); 3092 netif_carrier_on(netdev);
3036 netif_tx_wake_all_queues(netdev); 3093 netif_tx_wake_all_queues(netdev);
@@ -3039,6 +3096,8 @@ static void ixgbe_watchdog(unsigned long data)
3039 adapter->detect_tx_hung = true; 3096 adapter->detect_tx_hung = true;
3040 } 3097 }
3041 } else { 3098 } else {
3099 adapter->link_up = false;
3100 adapter->link_speed = 0;
3042 if (netif_carrier_ok(netdev)) { 3101 if (netif_carrier_ok(netdev)) {
3043 DPRINTK(LINK, INFO, "NIC Link is Down\n"); 3102 DPRINTK(LINK, INFO, "NIC Link is Down\n");
3044 netif_carrier_off(netdev); 3103 netif_carrier_off(netdev);
@@ -3047,24 +3106,7 @@ static void ixgbe_watchdog(unsigned long data)
3047 } 3106 }
3048 3107
3049 ixgbe_update_stats(adapter); 3108 ixgbe_update_stats(adapter);
3050 3109 adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK;
3051 if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
3052 /* Cause software interrupt to ensure rx rings are cleaned */
3053 if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
3054 u32 eics =
3055 (1 << (adapter->num_msix_vectors - NON_Q_VECTORS)) - 1;
3056 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, eics);
3057 } else {
3058 /* for legacy and MSI interrupts don't set any bits that
3059 * are enabled for EIAM, because this operation would
3060 * set *both* EIMS and EICS for any bit in EIAM */
3061 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS,
3062 (IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
3063 }
3064 /* Reset the timer */
3065 mod_timer(&adapter->watchdog_timer,
3066 round_jiffies(jiffies + 2 * HZ));
3067 }
3068} 3110}
3069 3111
3070static int ixgbe_tso(struct ixgbe_adapter *adapter, 3112static int ixgbe_tso(struct ixgbe_adapter *adapter,
@@ -3707,6 +3749,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
3707 adapter->watchdog_timer.data = (unsigned long)adapter; 3749 adapter->watchdog_timer.data = (unsigned long)adapter;
3708 3750
3709 INIT_WORK(&adapter->reset_task, ixgbe_reset_task); 3751 INIT_WORK(&adapter->reset_task, ixgbe_reset_task);
3752 INIT_WORK(&adapter->watchdog_task, ixgbe_watchdog_task);
3710 3753
3711 err = ixgbe_init_interrupt_scheme(adapter); 3754 err = ixgbe_init_interrupt_scheme(adapter);
3712 if (err) 3755 if (err)
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 3e9c483ad8e6..172f766acdea 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -703,6 +703,7 @@
703#define IXGBE_LINKS_TL_FAULT 0x00001000 703#define IXGBE_LINKS_TL_FAULT 0x00001000
704#define IXGBE_LINKS_SIGNAL 0x00000F00 704#define IXGBE_LINKS_SIGNAL 0x00000F00
705 705
706#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
706#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ 707#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
707 708
708/* SW Semaphore Register bitmasks */ 709/* SW Semaphore Register bitmasks */
@@ -1249,7 +1250,7 @@ struct ixgbe_mac_operations {
1249 s32 (*reset)(struct ixgbe_hw *); 1250 s32 (*reset)(struct ixgbe_hw *);
1250 enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); 1251 enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
1251 s32 (*setup_link)(struct ixgbe_hw *); 1252 s32 (*setup_link)(struct ixgbe_hw *);
1252 s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *); 1253 s32 (*check_link)(struct ixgbe_hw *, u32 *, bool *, bool);
1253 s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool); 1254 s32 (*setup_link_speed)(struct ixgbe_hw *, u32, bool, bool);
1254 s32 (*get_link_settings)(struct ixgbe_hw *, u32 *, bool *); 1255 s32 (*get_link_settings)(struct ixgbe_hw *, u32 *, bool *);
1255}; 1256};