aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_main.c
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/net/ixgbe/ixgbe_main.c
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/net/ixgbe/ixgbe_main.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c129
1 files changed, 86 insertions, 43 deletions
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)