* [net-next-2.6 05/13] ixgbe: move flags and state into the same cacheline
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change moves flags and state into the same cacheline. The reason for
this change is because both are frequently read around the same time and
infrequently written. By combining them into the same cacheline this
should help to reduce memory utilization.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Evan Swanson <evan.swanson@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 88 +++++++++++++++++++++++----------------------
1 files changed, 45 insertions(+), 43 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 91c1540..ec948ff 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -341,10 +341,48 @@ struct ixgbe_q_vector {
/* board specific private data structure */
struct ixgbe_adapter {
- struct timer_list watchdog_timer;
+ unsigned long state;
+
+ /* Some features need tri-state capability,
+ * thus the additional *_CAPABLE flags.
+ */
+ u32 flags;
+#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1)
+#define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 1)
+#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 2)
+#define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 3)
+#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 4)
+#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 6)
+#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 7)
+#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 8)
+#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 9)
+#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 10)
+#define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 11)
+#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 12)
+#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 13)
+#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 14)
+#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 16)
+#define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 17)
+#define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 18)
+#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19)
+#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20)
+#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22)
+#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23)
+#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24)
+#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25)
+#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26)
+#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27)
+#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28)
+#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29)
+#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30)
+
+ u32 flags2;
+#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1)
+#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1)
+#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2)
+
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 bd_number;
- struct work_struct reset_task;
struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
/* DCB parameters */
@@ -387,43 +425,6 @@ struct ixgbe_adapter {
u32 alloc_rx_page_failed;
u32 alloc_rx_buff_failed;
- /* Some features need tri-state capability,
- * thus the additional *_CAPABLE flags.
- */
- u32 flags;
-#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1)
-#define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 1)
-#define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 2)
-#define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 3)
-#define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 4)
-#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 6)
-#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 7)
-#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 8)
-#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 9)
-#define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 10)
-#define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 11)
-#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 12)
-#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 13)
-#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 14)
-#define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 16)
-#define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 17)
-#define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 18)
-#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19)
-#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20)
-#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22)
-#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23)
-#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24)
-#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25)
-#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26)
-#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27)
-#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28)
-#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29)
-#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30)
-
- u32 flags2;
-#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1)
-#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1)
-#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2)
/* default to trying for four seconds */
#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
@@ -444,7 +445,6 @@ struct ixgbe_adapter {
u32 rx_eitr_param;
u32 tx_eitr_param;
- unsigned long state;
u64 tx_busy;
unsigned int tx_ring_count;
unsigned int rx_ring_count;
@@ -453,15 +453,18 @@ struct ixgbe_adapter {
bool link_up;
unsigned long link_check_timeout;
+ struct work_struct reset_task;
struct work_struct watchdog_task;
struct work_struct sfp_task;
- struct timer_list sfp_timer;
struct work_struct multispeed_fiber_task;
struct work_struct sfp_config_module_task;
+ struct work_struct fdir_reinit_task;
+ struct work_struct check_overtemp_task;
+ struct timer_list watchdog_timer;
+ struct timer_list sfp_timer;
u32 fdir_pballoc;
u32 atr_sample_rate;
spinlock_t fdir_perfect_lock;
- struct work_struct fdir_reinit_task;
#ifdef IXGBE_FCOE
struct ixgbe_fcoe fcoe;
#endif /* IXGBE_FCOE */
@@ -472,7 +475,6 @@ struct ixgbe_adapter {
int node;
u32 led_reg;
- struct work_struct check_overtemp_task;
u32 interrupt_event;
char lsc_int_name[IFNAMSIZ + 9];
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 06/13] ixgbe: Combine SFP and multi-speed fiber task into single service task
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change is meant to address several race conditions with multi-speed
fiber SFP+ modules in 82599 adapters. Specifically issues have been seen
in which both the SFP configuration and the multi-speed fiber configuration
are running simultaneously which will result in the device getting into an
erroneous link down state.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Evan Swanson <evan.swanson@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 26 ++--
drivers/net/ixgbe/ixgbe_main.c | 388 +++++++++++++++++++++-------------------
2 files changed, 213 insertions(+), 201 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index ec948ff..cbb04ba 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -367,19 +367,20 @@ struct ixgbe_adapter {
#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19)
#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20)
#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22)
-#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23)
-#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24)
-#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25)
-#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26)
-#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27)
-#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28)
-#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29)
-#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30)
+#define IXGBE_FLAG_NEED_LINK_CONFIG (u32)(1 << 23)
+#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 24)
+#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 25)
+#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 26)
+#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 27)
+#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 28)
+#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 29)
u32 flags2;
#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1)
#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1)
#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2)
+#define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4)
+#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5)
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 bd_number;
@@ -455,13 +456,11 @@ struct ixgbe_adapter {
struct work_struct reset_task;
struct work_struct watchdog_task;
- struct work_struct sfp_task;
- struct work_struct multispeed_fiber_task;
- struct work_struct sfp_config_module_task;
struct work_struct fdir_reinit_task;
struct work_struct check_overtemp_task;
+ struct work_struct service_task;
struct timer_list watchdog_timer;
- struct timer_list sfp_timer;
+ struct timer_list service_timer;
u32 fdir_pballoc;
u32 atr_sample_rate;
spinlock_t fdir_perfect_lock;
@@ -492,7 +491,8 @@ enum ixbge_state_t {
__IXGBE_TESTING,
__IXGBE_RESETTING,
__IXGBE_DOWN,
- __IXGBE_SFP_MODULE_NOT_FOUND
+ __IXGBE_SERVICE_SCHED,
+ __IXGBE_IN_SFP_INIT,
};
struct ixgbe_rsc_cb {
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index f8196e0..a5d4226 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -191,6 +191,22 @@ static inline void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
}
+static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
+{
+ if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
+ !test_and_set_bit(__IXGBE_SERVICE_SCHED, &adapter->state))
+ schedule_work(&adapter->service_task);
+}
+
+static void ixgbe_service_event_complete(struct ixgbe_adapter *adapter)
+{
+ BUG_ON(!test_bit(__IXGBE_SERVICE_SCHED, &adapter->state));
+
+ /* flush memory to make sure state is correct before next watchog */
+ smp_mb__before_clear_bit();
+ clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state);
+}
+
struct ixgbe_reg_info {
u32 ofs;
char *name;
@@ -1858,15 +1874,19 @@ static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr)
if (eicr & IXGBE_EICR_GPI_SDP2) {
/* Clear the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- schedule_work(&adapter->sfp_config_module_task);
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET;
+ ixgbe_service_event_schedule(adapter);
+ }
}
if (eicr & IXGBE_EICR_GPI_SDP1) {
/* Clear the interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- schedule_work(&adapter->multispeed_fiber_task);
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ adapter->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
+ ixgbe_service_event_schedule(adapter);
+ }
}
}
@@ -1937,8 +1957,10 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
ixgbe_check_fan_failure(adapter, eicr);
+ /* re-enable the original interrupt state, no lsc, no queues */
if (!test_bit(__IXGBE_DOWN, &adapter->state))
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, eicr &
+ ~(IXGBE_EIMS_LSC | IXGBE_EIMS_RTX_QUEUE));
return IRQ_HANDLED;
}
@@ -3772,31 +3794,16 @@ static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw)
**/
static void ixgbe_sfp_link_config(struct ixgbe_adapter *adapter)
{
- struct ixgbe_hw *hw = &adapter->hw;
+ /*
+ * We are assuming the worst case scenerio here, and that
+ * is that an SFP was inserted/removed after the reset
+ * but before SFP detection was enabled. As such the best
+ * solution is to just start searching as soon as we start
+ */
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
- if (hw->phy.multispeed_fiber) {
- /*
- * In multispeed fiber setups, the device may not have
- * had a physical connection when the driver loaded.
- * If that's the case, the initial link configuration
- * couldn't get the MAC into 10G or 1G mode, so we'll
- * never have a link status change interrupt fire.
- * We need to try and force an autonegotiation
- * session, then bring up link.
- */
- if (hw->mac.ops.setup_sfp)
- hw->mac.ops.setup_sfp(hw);
- if (!(adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK))
- schedule_work(&adapter->multispeed_fiber_task);
- } else {
- /*
- * Direct Attach Cu and non-multispeed fiber modules
- * still need to be configured properly prior to
- * attempting link.
- */
- if (!(adapter->flags & IXGBE_FLAG_IN_SFP_MOD_TASK))
- schedule_work(&adapter->sfp_config_module_task);
- }
+ adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET;
}
/**
@@ -3926,17 +3933,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
e_crit(drv, "Fan has stopped, replace the adapter\n");
}
- /*
- * For hot-pluggable SFP+ devices, a new SFP+ module may have
- * arrived before interrupts were enabled but after probe. Such
- * devices wouldn't have their type identified yet. We need to
- * kick off the SFP+ module setup first, then try to bring up link.
- * If we're not hot-pluggable SFP+, we just need to configure link
- * and bring it up.
- */
- if (hw->phy.type == ixgbe_phy_none)
- schedule_work(&adapter->sfp_config_module_task);
-
/* enable transmits */
netif_tx_start_all_queues(adapter->netdev);
@@ -3945,6 +3941,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
adapter->link_check_timeout = jiffies;
mod_timer(&adapter->watchdog_timer, jiffies);
+ mod_timer(&adapter->service_timer, jiffies);
/* Set PF Reset Done bit so PF/VF Mail Ops can work */
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
@@ -3957,6 +3954,9 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
{
WARN_ON(in_interrupt());
+ /* put off any impending NetWatchDogTimeout */
+ adapter->netdev->trans_start = jiffies;
+
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
usleep_range(1000, 2000);
ixgbe_down(adapter);
@@ -3985,10 +3985,20 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
int err;
+ /* lock SFP init bit to prevent race conditions with the watchdog */
+ while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
+ usleep_range(1000, 2000);
+
+ /* clear all SFP and link config related flags while holding SFP_INIT */
+ adapter->flags2 &= ~(IXGBE_FLAG2_SEARCH_FOR_SFP |
+ IXGBE_FLAG2_SFP_NEEDS_RESET);
+ adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
+
err = hw->mac.ops.init_hw(hw);
switch (err) {
case 0:
case IXGBE_ERR_SFP_NOT_PRESENT:
+ case IXGBE_ERR_SFP_NOT_SUPPORTED:
break;
case IXGBE_ERR_MASTER_REQUESTS_PENDING:
e_dev_err("master disable timed out\n");
@@ -4006,6 +4016,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
e_dev_err("Hardware Error: %d\n", err);
}
+ clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
+
/* reprogram the RAR[0] in case user changed it. */
hw->mac.ops.set_rar(hw, 0, hw->mac.addr, adapter->num_vfs,
IXGBE_RAH_AV);
@@ -4167,11 +4179,9 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
netif_tx_stop_all_queues(netdev);
- clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
- del_timer_sync(&adapter->sfp_timer);
del_timer_sync(&adapter->watchdog_timer);
cancel_work_sync(&adapter->watchdog_task);
-
+ /* call carrier off first to avoid false dev_watchdog timeouts */
netif_carrier_off(netdev);
netif_tx_disable(netdev);
@@ -4179,6 +4189,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
ixgbe_napi_disable_all(adapter);
+ adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
+
+ del_timer_sync(&adapter->service_timer);
+
/* Cleanup the affinity_hint CPU mask memory and callback */
for (i = 0; i < num_q_vectors; i++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
@@ -5148,57 +5162,6 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_sfp_timer - worker thread to find a missing module
- * @data: pointer to our adapter struct
- **/
-static void ixgbe_sfp_timer(unsigned long data)
-{
- struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
-
- /*
- * Do the sfp_timer outside of interrupt context due to the
- * delays that sfp+ detection requires
- */
- schedule_work(&adapter->sfp_task);
-}
-
-/**
- * ixgbe_sfp_task - worker thread to find a missing module
- * @work: pointer to work_struct containing our data
- **/
-static void ixgbe_sfp_task(struct work_struct *work)
-{
- struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- sfp_task);
- struct ixgbe_hw *hw = &adapter->hw;
-
- if ((hw->phy.type == ixgbe_phy_nl) &&
- (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
- s32 ret = hw->phy.ops.identify_sfp(hw);
- if (ret == IXGBE_ERR_SFP_NOT_PRESENT)
- goto reschedule;
- ret = hw->phy.ops.reset(hw);
- if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- e_dev_err("failed to initialize because an unsupported "
- "SFP+ module type was detected.\n");
- e_dev_err("Reload the driver after installing a "
- "supported module.\n");
- unregister_netdev(adapter->netdev);
- } else {
- e_info(probe, "detected SFP+: %d\n", hw->phy.sfp_type);
- }
- /* don't need this routine any more */
- clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
- }
- return;
-reschedule:
- if (test_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state))
- mod_timer(&adapter->sfp_timer,
- round_jiffies(jiffies + (2 * HZ)));
-}
-
-/**
* ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter)
* @adapter: board private structure to initialize
*
@@ -6042,65 +6005,6 @@ watchdog_short_circuit:
}
/**
- * ixgbe_multispeed_fiber_task - worker thread to configure multispeed fiber
- * @work: pointer to work_struct containing our data
- **/
-static void ixgbe_multispeed_fiber_task(struct work_struct *work)
-{
- struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- multispeed_fiber_task);
- struct ixgbe_hw *hw = &adapter->hw;
- u32 autoneg;
- bool negotiation;
-
- adapter->flags |= IXGBE_FLAG_IN_SFP_LINK_TASK;
- autoneg = hw->phy.autoneg_advertised;
- if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
- hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiation);
- hw->mac.autotry_restart = false;
- if (hw->mac.ops.setup_link)
- hw->mac.ops.setup_link(hw, autoneg, negotiation, true);
- adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
- adapter->flags &= ~IXGBE_FLAG_IN_SFP_LINK_TASK;
-}
-
-/**
- * ixgbe_sfp_config_module_task - worker thread to configure a new SFP+ module
- * @work: pointer to work_struct containing our data
- **/
-static void ixgbe_sfp_config_module_task(struct work_struct *work)
-{
- struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- sfp_config_module_task);
- struct ixgbe_hw *hw = &adapter->hw;
- u32 err;
-
- adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK;
-
- /* Time for electrical oscillations to settle down */
- msleep(100);
- err = hw->phy.ops.identify_sfp(hw);
-
- if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- e_dev_err("failed to initialize because an unsupported SFP+ "
- "module type was detected.\n");
- e_dev_err("Reload the driver after installing a supported "
- "module.\n");
- unregister_netdev(adapter->netdev);
- return;
- }
- if (hw->mac.ops.setup_sfp)
- hw->mac.ops.setup_sfp(hw);
-
- if (!(adapter->flags & IXGBE_FLAG_IN_SFP_LINK_TASK))
- /* This will also work for DA Twinax connections */
- schedule_work(&adapter->multispeed_fiber_task);
- adapter->flags &= ~IXGBE_FLAG_IN_SFP_MOD_TASK;
-}
-
-/**
* ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table
* @work: pointer to work_struct containing our data
**/
@@ -6273,6 +6177,141 @@ static void ixgbe_watchdog_task(struct work_struct *work)
mutex_unlock(&ixgbe_watchdog_lock);
}
+/**
+ * ixgbe_sfp_detection_subtask - poll for SFP+ cable
+ * @adapter - the ixgbe adapter structure
+ **/
+static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ s32 err;
+
+ /* not searching for SFP so there is nothing to do here */
+ if (!(adapter->flags2 & IXGBE_FLAG2_SEARCH_FOR_SFP) &&
+ !(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET))
+ return;
+
+ /* someone else is in init, wait until next service event */
+ if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
+ return;
+
+ err = hw->phy.ops.identify_sfp(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto sfp_out;
+
+ if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
+ /* If no cable is present, then we need to reset
+ * the next time we find a good cable. */
+ adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET;
+ }
+
+ /* exit on error */
+ if (err)
+ goto sfp_out;
+
+ /* exit if reset not needed */
+ if (!(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET))
+ goto sfp_out;
+
+ adapter->flags2 &= ~IXGBE_FLAG2_SFP_NEEDS_RESET;
+
+ /*
+ * A module may be identified correctly, but the EEPROM may not have
+ * support for that module. setup_sfp() will fail in that case, so
+ * we should not allow that module to load.
+ */
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ err = hw->phy.ops.reset(hw);
+ else
+ err = hw->mac.ops.setup_sfp(hw);
+
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto sfp_out;
+
+ adapter->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
+ e_info(probe, "detected SFP+: %d\n", hw->phy.sfp_type);
+
+sfp_out:
+ clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
+
+ if ((err == IXGBE_ERR_SFP_NOT_SUPPORTED) &&
+ (adapter->netdev->reg_state == NETREG_REGISTERED)) {
+ e_dev_err("failed to initialize because an unsupported "
+ "SFP+ module type was detected.\n");
+ e_dev_err("Reload the driver after installing a "
+ "supported module.\n");
+ unregister_netdev(adapter->netdev);
+ }
+}
+
+/**
+ * ixgbe_sfp_link_config_subtask - set up link SFP after module install
+ * @adapter - the ixgbe adapter structure
+ **/
+static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 autoneg;
+ bool negotiation;
+
+ if (!(adapter->flags & IXGBE_FLAG_NEED_LINK_CONFIG))
+ return;
+
+ /* someone else is in init, wait until next service event */
+ if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
+ return;
+
+ adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
+
+ autoneg = hw->phy.autoneg_advertised;
+ if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
+ hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiation);
+ hw->mac.autotry_restart = false;
+ if (hw->mac.ops.setup_link)
+ hw->mac.ops.setup_link(hw, autoneg, negotiation, true);
+
+ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
+ adapter->link_check_timeout = jiffies;
+ clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
+}
+
+/**
+ * ixgbe_service_timer - Timer Call-back
+ * @data: pointer to adapter cast into an unsigned long
+ **/
+static void ixgbe_service_timer(unsigned long data)
+{
+ struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
+ unsigned long next_event_offset;
+
+ /* poll faster when waiting for link */
+ if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)
+ next_event_offset = HZ / 10;
+ else
+ next_event_offset = HZ * 2;
+
+ /* Reset the timer */
+ mod_timer(&adapter->service_timer, next_event_offset + jiffies);
+
+ ixgbe_service_event_schedule(adapter);
+}
+
+/**
+ * ixgbe_service_task - manages and runs subtasks
+ * @work: pointer to work_struct containing our data
+ **/
+static void ixgbe_service_task(struct work_struct *work)
+{
+ struct ixgbe_adapter *adapter = container_of(work,
+ struct ixgbe_adapter,
+ service_task);
+
+ ixgbe_sfp_detection_subtask(adapter);
+ ixgbe_sfp_link_config_subtask(adapter);
+
+ ixgbe_service_event_complete(adapter);
+}
+
static int ixgbe_tso(struct ixgbe_adapter *adapter,
struct ixgbe_ring *tx_ring, struct sk_buff *skb,
u32 tx_flags, u8 *hdr_len, __be16 protocol)
@@ -7317,22 +7356,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
hw->phy.mdio.mdio_read = ixgbe_mdio_read;
hw->phy.mdio.mdio_write = ixgbe_mdio_write;
- /* set up this timer and work struct before calling get_invariants
- * which might start the timer
- */
- init_timer(&adapter->sfp_timer);
- adapter->sfp_timer.function = ixgbe_sfp_timer;
- adapter->sfp_timer.data = (unsigned long) adapter;
-
- INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task);
-
- /* multispeed fiber has its own tasklet, called from GPI SDP1 context */
- INIT_WORK(&adapter->multispeed_fiber_task, ixgbe_multispeed_fiber_task);
-
- /* a new SFP+ module arrival, called from GPI SDP2 context */
- INIT_WORK(&adapter->sfp_config_module_task,
- ixgbe_sfp_config_module_task);
-
ii->get_invariants(hw);
/* setup the private structure */
@@ -7366,17 +7389,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
hw->phy.reset_if_overtemp = false;
if (err == IXGBE_ERR_SFP_NOT_PRESENT &&
hw->mac.type == ixgbe_mac_82598EB) {
- /*
- * Start a kernel thread to watch for a module to arrive.
- * Only do this for 82598, since 82599 will generate
- * interrupts on module arrival.
- */
- set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
- mod_timer(&adapter->sfp_timer,
- round_jiffies(jiffies + (2 * HZ)));
err = 0;
} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- e_dev_err("failed to initialize because an unsupported SFP+ "
+ e_dev_err("failed to load because an unsupported SFP+ "
"module type was detected.\n");
e_dev_err("Reload the driver after installing a supported "
"module.\n");
@@ -7468,6 +7483,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
(hw->mac.type == ixgbe_mac_82599EB))))
hw->mac.ops.disable_tx_laser(hw);
+ setup_timer(&adapter->service_timer, &ixgbe_service_timer,
+ (unsigned long) adapter);
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = ixgbe_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
@@ -7475,6 +7492,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->reset_task, ixgbe_reset_task);
INIT_WORK(&adapter->watchdog_task, ixgbe_watchdog_task);
+ INIT_WORK(&adapter->service_task, ixgbe_service_task);
+ clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state);
+
err = ixgbe_init_interrupt_scheme(adapter);
if (err)
goto err_sw_init;
@@ -7593,11 +7613,7 @@ err_sw_init:
err_eeprom:
if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
ixgbe_disable_sriov(adapter);
- clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
- del_timer_sync(&adapter->sfp_timer);
- cancel_work_sync(&adapter->sfp_task);
- cancel_work_sync(&adapter->multispeed_fiber_task);
- cancel_work_sync(&adapter->sfp_config_module_task);
+ adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
iounmap(hw->hw_addr);
err_ioremap:
free_netdev(netdev);
@@ -7625,19 +7641,15 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
struct net_device *netdev = adapter->netdev;
set_bit(__IXGBE_DOWN, &adapter->state);
+ cancel_work_sync(&adapter->service_task);
/*
* The timers may be rescheduled, so explicitly disable them
* from being rescheduled.
*/
- clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
del_timer_sync(&adapter->watchdog_timer);
- del_timer_sync(&adapter->sfp_timer);
cancel_work_sync(&adapter->watchdog_task);
- cancel_work_sync(&adapter->sfp_task);
- cancel_work_sync(&adapter->multispeed_fiber_task);
- cancel_work_sync(&adapter->sfp_config_module_task);
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
cancel_work_sync(&adapter->fdir_reinit_task);
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 04/13] ixgbe: force unlock on timeout
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Emil Tantilov, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Emil Tantilov <emil.s.tantilov@intel.com>
The semaphore can be in locked state upon driver load, particularly
on 82598 if a machine is rebooted due to panic and the semaphore was
acquired just prior to the panic.
This patch unlocks the semaphore if it times out.
Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_common.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index c4730cd..b894b42 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1189,6 +1189,28 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
udelay(50);
}
+ if (i == timeout) {
+ hw_dbg(hw, "Driver can't access the Eeprom - SMBI Semaphore "
+ "not granted.\n");
+ /*
+ * this release is particularly important because our attempts
+ * above to get the semaphore may have succeeded, and if there
+ * was a timeout, we should unconditionally clear the semaphore
+ * bits to free the driver to make progress
+ */
+ ixgbe_release_eeprom_semaphore(hw);
+
+ udelay(50);
+ /*
+ * one last try
+ * If the SMBI bit is 0 when we read it, then the bit will be
+ * set and we have the semaphore
+ */
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ if (!(swsm & IXGBE_SWSM_SMBI))
+ status = 0;
+ }
+
/* Now get the semaphore between SW/FW through the SWESMBI bit */
if (status == 0) {
for (i = 0; i < timeout; i++) {
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 07/13] ixgbe: Merge watchdog functionality into service task
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch is meant to merge the functionality of the ixgbe watchdog task
into the service task. By doing this all link state functionality will be
controlled by a single task. As a result the reliability of the interface
will be improved as the likelihood of any race conditions is further
reduced.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 2 -
drivers/net/ixgbe/ixgbe_main.c | 364 ++++++++++++++++++++++------------------
2 files changed, 200 insertions(+), 166 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index cbb04ba..193c6c4 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -455,11 +455,9 @@ struct ixgbe_adapter {
unsigned long link_check_timeout;
struct work_struct reset_task;
- struct work_struct watchdog_task;
struct work_struct fdir_reinit_task;
struct work_struct check_overtemp_task;
struct work_struct service_task;
- struct timer_list watchdog_timer;
struct timer_list service_timer;
u32 fdir_pballoc;
u32 atr_sample_rate;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index a5d4226..d1e52b5 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1900,7 +1900,7 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
IXGBE_WRITE_FLUSH(hw);
- schedule_work(&adapter->watchdog_task);
+ ixgbe_service_event_schedule(adapter);
}
}
@@ -3940,7 +3940,6 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
* link up interrupt but shouldn't be a problem */
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
adapter->link_check_timeout = jiffies;
- mod_timer(&adapter->watchdog_timer, jiffies);
mod_timer(&adapter->service_timer, jiffies);
/* Set PF Reset Done bit so PF/VF Mail Ops can work */
@@ -4179,8 +4178,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
netif_tx_stop_all_queues(netdev);
- del_timer_sync(&adapter->watchdog_timer);
- cancel_work_sync(&adapter->watchdog_task);
/* call carrier off first to avoid false dev_watchdog timeouts */
netif_carrier_off(netdev);
netif_tx_disable(netdev);
@@ -5957,23 +5954,54 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_watchdog - Timer Call-back
- * @data: pointer to adapter cast into an unsigned long
+ * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table
+ * @work: pointer to work_struct containing our data
**/
-static void ixgbe_watchdog(unsigned long data)
+static void ixgbe_fdir_reinit_task(struct work_struct *work)
+{
+ struct ixgbe_adapter *adapter = container_of(work,
+ struct ixgbe_adapter,
+ fdir_reinit_task);
+ struct ixgbe_hw *hw = &adapter->hw;
+ int i;
+
+ if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ set_bit(__IXGBE_TX_FDIR_INIT_DONE,
+ &(adapter->tx_ring[i]->state));
+ } else {
+ e_err(probe, "failed to finish FDIR re-initialization, "
+ "ignored adding FDIR ATR filters\n");
+ }
+ /* Done FDIR Re-initialization, enable transmits */
+ netif_tx_start_all_queues(adapter->netdev);
+}
+
+/**
+ * ixgbe_check_hang_subtask - check for hung queues and dropped interrupts
+ * @adapter - pointer to the device adapter structure
+ *
+ * This function serves two purposes. First it strobes the interrupt lines
+ * in order to make certain interrupts are occuring. Secondly it sets the
+ * bits needed to check for TX hangs. As a result we should immediately
+ * determine if a hang has occured.
+ */
+static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter)
{
- struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
struct ixgbe_hw *hw = &adapter->hw;
u64 eics = 0;
int i;
- /*
- * Do the watchdog outside of interrupt context due to the lovely
- * delays that some of the newer hardware requires
- */
+ /* If we're down or resetting, just bail */
+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+ test_bit(__IXGBE_RESETTING, &adapter->state))
+ return;
- if (test_bit(__IXGBE_DOWN, &adapter->state))
- goto watchdog_short_circuit;
+ /* Force detection of hung controller */
+ if (netif_carrier_ok(adapter->netdev)) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ set_check_for_tx_hang(adapter->tx_ring[i]);
+ }
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
/*
@@ -5983,179 +6011,157 @@ static void ixgbe_watchdog(unsigned long data)
*/
IXGBE_WRITE_REG(hw, IXGBE_EICS,
(IXGBE_EICS_TCP_TIMER | IXGBE_EICS_OTHER));
- goto watchdog_reschedule;
- }
-
- /* get one bit for every active tx/rx interrupt vector */
- for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
- struct ixgbe_q_vector *qv = adapter->q_vector[i];
- if (qv->rxr_count || qv->txr_count)
- eics |= ((u64)1 << i);
+ } else {
+ /* get one bit for every active tx/rx interrupt vector */
+ for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
+ struct ixgbe_q_vector *qv = adapter->q_vector[i];
+ if (qv->rxr_count || qv->txr_count)
+ eics |= ((u64)1 << i);
+ }
}
- /* Cause software interrupt to ensure rx rings are cleaned */
+ /* Cause software interrupt to ensure rings are cleaned */
ixgbe_irq_rearm_queues(adapter, eics);
-watchdog_reschedule:
- /* Reset the timer */
- mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
-
-watchdog_short_circuit:
- schedule_work(&adapter->watchdog_task);
}
/**
- * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table
- * @work: pointer to work_struct containing our data
+ * ixgbe_watchdog_update_link - update the link status
+ * @adapter - pointer to the device adapter structure
+ * @link_speed - pointer to a u32 to store the link_speed
**/
-static void ixgbe_fdir_reinit_task(struct work_struct *work)
+static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
{
- struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- fdir_reinit_task);
struct ixgbe_hw *hw = &adapter->hw;
+ u32 link_speed = adapter->link_speed;
+ bool link_up = adapter->link_up;
int i;
- if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
- for (i = 0; i < adapter->num_tx_queues; i++)
- set_bit(__IXGBE_TX_FDIR_INIT_DONE,
- &(adapter->tx_ring[i]->state));
+ if (!(adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE))
+ return;
+
+ if (hw->mac.ops.check_link) {
+ hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
} else {
- e_err(probe, "failed to finish FDIR re-initialization, "
- "ignored adding FDIR ATR filters\n");
+ /* always assume link is up, if no check link function */
+ link_speed = IXGBE_LINK_SPEED_10GB_FULL;
+ link_up = true;
}
- /* Done FDIR Re-initialization, enable transmits */
- netif_tx_start_all_queues(adapter->netdev);
+ if (link_up) {
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+ hw->mac.ops.fc_enable(hw, i);
+ } else {
+ hw->mac.ops.fc_enable(hw, 0);
+ }
+ }
+
+ if (link_up ||
+ time_after(jiffies, (adapter->link_check_timeout +
+ IXGBE_TRY_LINK_TIMEOUT))) {
+ adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
+ IXGBE_WRITE_FLUSH(hw);
+ }
+
+ adapter->link_up = link_up;
+ adapter->link_speed = link_speed;
}
-static void ixgbe_spoof_check(struct ixgbe_adapter *adapter)
+/**
+ * ixgbe_watchdog_link_is_up - update netif_carrier status and
+ * print link up message
+ * @adapter - pointer to the device adapter structure
+ **/
+static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
{
- u32 ssvpc;
+ struct net_device *netdev = adapter->netdev;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 link_speed = adapter->link_speed;
+ bool flow_rx, flow_tx;
- /* Do not perform spoof check for 82598 */
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ /* only continue if link was previously down */
+ if (netif_carrier_ok(netdev))
return;
- ssvpc = IXGBE_READ_REG(&adapter->hw, IXGBE_SSVPC);
+ adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
- /*
- * ssvpc register is cleared on read, if zero then no
- * spoofed packets in the last interval.
- */
- if (!ssvpc)
- return;
+ switch (hw->mac.type) {
+ case ixgbe_mac_82598EB: {
+ u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+ u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
+ flow_rx = !!(frctl & IXGBE_FCTRL_RFCE);
+ flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X);
+ }
+ break;
+ case ixgbe_mac_X540:
+ case ixgbe_mac_82599EB: {
+ u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+ u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
+ flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE);
+ flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X);
+ }
+ break;
+ default:
+ flow_tx = false;
+ flow_rx = false;
+ break;
+ }
+ e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
+ (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
+ "10 Gbps" :
+ (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
+ "1 Gbps" :
+ (link_speed == IXGBE_LINK_SPEED_100_FULL ?
+ "100 Mbps" :
+ "unknown speed"))),
+ ((flow_rx && flow_tx) ? "RX/TX" :
+ (flow_rx ? "RX" :
+ (flow_tx ? "TX" : "None"))));
- e_warn(drv, "%d Spoofed packets detected\n", ssvpc);
+ netif_carrier_on(netdev);
+#ifdef HAVE_IPLINK_VF_CONFIG
+ ixgbe_check_vf_rate_limit(adapter);
+#endif /* HAVE_IPLINK_VF_CONFIG */
}
-static DEFINE_MUTEX(ixgbe_watchdog_lock);
-
/**
- * ixgbe_watchdog_task - worker thread to bring link up
- * @work: pointer to work_struct containing our data
+ * ixgbe_watchdog_link_is_down - update netif_carrier status and
+ * print link down message
+ * @adapter - pointer to the adapter structure
**/
-static void ixgbe_watchdog_task(struct work_struct *work)
+static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter* adapter)
{
- struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- watchdog_task);
struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
- u32 link_speed;
- bool link_up;
- int i;
- struct ixgbe_ring *tx_ring;
- int some_tx_pending = 0;
-
- mutex_lock(&ixgbe_watchdog_lock);
- link_up = adapter->link_up;
- link_speed = adapter->link_speed;
+ adapter->link_up = false;
+ adapter->link_speed = 0;
- if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
- hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
- if (link_up) {
-#ifdef CONFIG_DCB
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
- hw->mac.ops.fc_enable(hw, i);
- } else {
- hw->mac.ops.fc_enable(hw, 0);
- }
-#else
- hw->mac.ops.fc_enable(hw, 0);
-#endif
- }
+ /* only continue if link was up previously */
+ if (!netif_carrier_ok(netdev))
+ return;
- if (link_up ||
- time_after(jiffies, (adapter->link_check_timeout +
- IXGBE_TRY_LINK_TIMEOUT))) {
- adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC);
- }
- adapter->link_up = link_up;
- adapter->link_speed = link_speed;
- }
+ /* poll for SFP+ cable when link is down */
+ if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB)
+ adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
- if (link_up) {
- if (!netif_carrier_ok(netdev)) {
- bool flow_rx, flow_tx;
-
- switch (hw->mac.type) {
- case ixgbe_mac_82598EB: {
- u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
- u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
- flow_rx = !!(frctl & IXGBE_FCTRL_RFCE);
- flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X);
- }
- break;
- case ixgbe_mac_82599EB:
- case ixgbe_mac_X540: {
- u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
- u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
- flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE);
- flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X);
- }
- break;
- default:
- flow_tx = false;
- flow_rx = false;
- break;
- }
+ e_info(drv, "NIC Link is Down\n");
+ netif_carrier_off(netdev);
+}
- e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
- (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
- "10 Gbps" :
- (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
- "1 Gbps" :
- (link_speed == IXGBE_LINK_SPEED_100_FULL ?
- "100 Mbps" :
- "unknown speed"))),
- ((flow_rx && flow_tx) ? "RX/TX" :
- (flow_rx ? "RX" :
- (flow_tx ? "TX" : "None"))));
-
- netif_carrier_on(netdev);
- ixgbe_check_vf_rate_limit(adapter);
- } else {
- /* Force detection of hung controller */
- for (i = 0; i < adapter->num_tx_queues; i++) {
- tx_ring = adapter->tx_ring[i];
- set_check_for_tx_hang(tx_ring);
- }
- }
- } else {
- adapter->link_up = false;
- adapter->link_speed = 0;
- if (netif_carrier_ok(netdev)) {
- e_info(drv, "NIC Link is Down\n");
- netif_carrier_off(netdev);
- }
- }
+/**
+ * ixgbe_watchdog_flush_tx - flush queues on link down
+ * @adapter - pointer to the device adapter structure
+ **/
+static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter)
+{
+ int i;
+ int some_tx_pending = 0;
- if (!netif_carrier_ok(netdev)) {
+ if (!netif_carrier_ok(adapter->netdev)) {
for (i = 0; i < adapter->num_tx_queues; i++) {
- tx_ring = adapter->tx_ring[i];
+ struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
if (tx_ring->next_to_use != tx_ring->next_to_clean) {
some_tx_pending = 1;
break;
@@ -6168,13 +6174,52 @@ static void ixgbe_watchdog_task(struct work_struct *work)
* to get done, so reset controller to flush Tx.
* (Do the reset outside of interrupt context).
*/
- schedule_work(&adapter->reset_task);
+ schedule_work(&adapter->reset_task);
}
}
+}
+
+static void ixgbe_spoof_check(struct ixgbe_adapter *adapter)
+{
+ u32 ssvpc;
+
+ /* Do not perform spoof check for 82598 */
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ return;
+
+ ssvpc = IXGBE_READ_REG(&adapter->hw, IXGBE_SSVPC);
+
+ /*
+ * ssvpc register is cleared on read, if zero then no
+ * spoofed packets in the last interval.
+ */
+ if (!ssvpc)
+ return;
+
+ e_warn(drv, "%d Spoofed packets detected\n", ssvpc);
+}
+
+/**
+ * ixgbe_watchdog_subtask - check and bring link up
+ * @adapter - pointer to the device adapter structure
+ **/
+static void ixgbe_watchdog_subtask(struct ixgbe_adapter *adapter)
+{
+ /* if interface is down do nothing */
+ if (test_bit(__IXGBE_DOWN, &adapter->state))
+ return;
+
+ ixgbe_watchdog_update_link(adapter);
+
+ if (adapter->link_up)
+ ixgbe_watchdog_link_is_up(adapter);
+ else
+ ixgbe_watchdog_link_is_down(adapter);
ixgbe_spoof_check(adapter);
ixgbe_update_stats(adapter);
- mutex_unlock(&ixgbe_watchdog_lock);
+
+ ixgbe_watchdog_flush_tx(adapter);
}
/**
@@ -6308,6 +6353,8 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_sfp_detection_subtask(adapter);
ixgbe_sfp_link_config_subtask(adapter);
+ ixgbe_watchdog_subtask(adapter);
+ ixgbe_check_hang_subtask(adapter);
ixgbe_service_event_complete(adapter);
}
@@ -7485,12 +7532,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
setup_timer(&adapter->service_timer, &ixgbe_service_timer,
(unsigned long) adapter);
- init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = ixgbe_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
INIT_WORK(&adapter->reset_task, ixgbe_reset_task);
- INIT_WORK(&adapter->watchdog_task, ixgbe_watchdog_task);
INIT_WORK(&adapter->service_task, ixgbe_service_task);
clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state);
@@ -7643,13 +7686,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
set_bit(__IXGBE_DOWN, &adapter->state);
cancel_work_sync(&adapter->service_task);
- /*
- * The timers may be rescheduled, so explicitly disable them
- * from being rescheduled.
- */
- del_timer_sync(&adapter->watchdog_timer);
-
- cancel_work_sync(&adapter->watchdog_task);
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
cancel_work_sync(&adapter->fdir_reinit_task);
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 08/13] ixgbe: merge reset task into service task
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change is meant to further help to reduce possible configuration
collisions between the various tasklets. This change combines the device
reset with the service task. As a result it is now not possible to be
updating the link on the device while also resetting the part.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Evan Swanson <evan.swanson@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 2 +-
drivers/net/ixgbe/ixgbe_main.c | 60 ++++++++++++++++++++++++---------------
2 files changed, 38 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 193c6c4..760b850 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -381,6 +381,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2)
#define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4)
#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5)
+#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6)
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 bd_number;
@@ -454,7 +455,6 @@ struct ixgbe_adapter {
bool link_up;
unsigned long link_check_timeout;
- struct work_struct reset_task;
struct work_struct fdir_reinit_task;
struct work_struct check_overtemp_task;
struct work_struct service_task;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index d1e52b5..dbb20e5 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -833,7 +833,19 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */
-static void ixgbe_tx_timeout(struct net_device *netdev);
+/**
+ * ixgbe_tx_timeout_reset - initiate reset due to Tx timeout
+ * @adapter: driver private struct
+ **/
+static void ixgbe_tx_timeout_reset(struct ixgbe_adapter *adapter)
+{
+
+ /* Do the reset outside of interrupt context */
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED;
+ ixgbe_service_event_schedule(adapter);
+ }
+}
/**
* ixgbe_clean_tx_irq - Reclaim resources after transmit completes
@@ -915,7 +927,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
adapter->tx_timeout_count + 1, tx_ring->queue_index);
/* schedule immediate reset if we believe we hung */
- ixgbe_tx_timeout(adapter->netdev);
+ ixgbe_tx_timeout_reset(adapter);
/* the adapter is about to reset, no point in enabling stuff */
return true;
@@ -4186,6 +4198,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
ixgbe_napi_disable_all(adapter);
+ adapter->flags2 &= ~IXGBE_FLAG2_RESET_REQUESTED;
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
del_timer_sync(&adapter->service_timer);
@@ -4288,25 +4301,8 @@ static void ixgbe_tx_timeout(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- adapter->tx_timeout_count++;
-
/* Do the reset outside of interrupt context */
- schedule_work(&adapter->reset_task);
-}
-
-static void ixgbe_reset_task(struct work_struct *work)
-{
- struct ixgbe_adapter *adapter;
- adapter = container_of(work, struct ixgbe_adapter, reset_task);
-
- /* If we're already down or resetting, just bail */
- if (test_bit(__IXGBE_DOWN, &adapter->state) ||
- test_bit(__IXGBE_RESETTING, &adapter->state))
- return;
-
- ixgbe_dump(adapter);
- netdev_err(adapter->netdev, "Reset adapter\n");
- ixgbe_reinit_locked(adapter);
+ ixgbe_tx_timeout_reset(adapter);
}
/**
@@ -6174,7 +6170,7 @@ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter)
* to get done, so reset controller to flush Tx.
* (Do the reset outside of interrupt context).
*/
- schedule_work(&adapter->reset_task);
+ adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED;
}
}
}
@@ -6341,6 +6337,25 @@ static void ixgbe_service_timer(unsigned long data)
ixgbe_service_event_schedule(adapter);
}
+static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
+{
+ if (!(adapter->flags2 & IXGBE_FLAG2_RESET_REQUESTED))
+ return;
+
+ adapter->flags2 &= ~IXGBE_FLAG2_RESET_REQUESTED;
+
+ /* If we're already down or resetting, just bail */
+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+ test_bit(__IXGBE_RESETTING, &adapter->state))
+ return;
+
+ ixgbe_dump(adapter);
+ netdev_err(adapter->netdev, "Reset adapter\n");
+ adapter->tx_timeout_count++;
+
+ ixgbe_reinit_locked(adapter);
+}
+
/**
* ixgbe_service_task - manages and runs subtasks
* @work: pointer to work_struct containing our data
@@ -6351,6 +6366,7 @@ static void ixgbe_service_task(struct work_struct *work)
struct ixgbe_adapter,
service_task);
+ ixgbe_reset_subtask(adapter);
ixgbe_sfp_detection_subtask(adapter);
ixgbe_sfp_link_config_subtask(adapter);
ixgbe_watchdog_subtask(adapter);
@@ -7533,8 +7549,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
setup_timer(&adapter->service_timer, &ixgbe_service_timer,
(unsigned long) adapter);
- INIT_WORK(&adapter->reset_task, ixgbe_reset_task);
-
INIT_WORK(&adapter->service_task, ixgbe_service_task);
clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state);
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 10/13] ixgbe: Merge over-temp task into service task
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change merges the over-temp task into the service task. As a result
all tasklets are finally combined into once single tasklet for easier
management.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 2 +-
drivers/net/ixgbe/ixgbe_main.c | 87 ++++++++++++++++++++++++----------------
2 files changed, 53 insertions(+), 36 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index a180cde..e467b20 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -379,6 +379,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_RSC_CAPABLE (u32)(1)
#define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1)
#define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2)
+#define IXGBE_FLAG2_TEMP_SENSOR_EVENT (u32)(1 << 3)
#define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4)
#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5)
#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6)
@@ -456,7 +457,6 @@ struct ixgbe_adapter {
bool link_up;
unsigned long link_check_timeout;
- struct work_struct check_overtemp_task;
struct work_struct service_task;
struct timer_list service_timer;
u32 fdir_pballoc;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 7edd360..dad56e1 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1825,35 +1825,51 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
}
/**
- * ixgbe_check_overtemp_task - worker thread to check over tempurature
- * @work: pointer to work_struct containing our data
+ * ixgbe_check_overtemp_subtask - check for over tempurature
+ * @adapter: pointer to adapter
**/
-static void ixgbe_check_overtemp_task(struct work_struct *work)
+static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter)
{
- struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- check_overtemp_task);
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr = adapter->interrupt_event;
- if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE))
+ if (test_bit(__IXGBE_DOWN, &adapter->state))
return;
+ if (!(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
+ !(adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_EVENT))
+ return;
+
+ adapter->flags2 &= ~IXGBE_FLAG2_TEMP_SENSOR_EVENT;
+
switch (hw->device_id) {
- case IXGBE_DEV_ID_82599_T3_LOM: {
- u32 autoneg;
- bool link_up = false;
+ case IXGBE_DEV_ID_82599_T3_LOM:
+ /*
+ * Since the warning interrupt is for both ports
+ * we don't have to check if:
+ * - This interrupt wasn't for our port.
+ * - We may have missed the interrupt so always have to
+ * check if we got a LSC
+ */
+ if (!(eicr & IXGBE_EICR_GPI_SDP0) &&
+ !(eicr & IXGBE_EICR_LSC))
+ return;
+
+ if (!(eicr & IXGBE_EICR_LSC) && hw->mac.ops.check_link) {
+ u32 autoneg;
+ bool link_up = false;
- if (hw->mac.ops.check_link)
hw->mac.ops.check_link(hw, &autoneg, &link_up, false);
- if (((eicr & IXGBE_EICR_GPI_SDP0) && (!link_up)) ||
- (eicr & IXGBE_EICR_LSC))
- /* Check if this is due to overtemp */
- if (hw->phy.ops.check_overtemp(hw) == IXGBE_ERR_OVERTEMP)
- break;
- return;
- }
+ if (link_up)
+ return;
+ }
+
+ /* Check if this is not due to overtemp */
+ if (hw->phy.ops.check_overtemp(hw) != IXGBE_ERR_OVERTEMP)
+ return;
+
+ break;
default:
if (!(eicr & IXGBE_EICR_GPI_SDP0))
return;
@@ -1863,8 +1879,8 @@ static void ixgbe_check_overtemp_task(struct work_struct *work)
"Network adapter has been stopped because it has over heated. "
"Restart the computer. If the problem persists, "
"power off the system and replace the adapter\n");
- /* write to clear the interrupt */
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0);
+
+ adapter->interrupt_event = 0;
}
static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
@@ -1940,13 +1956,6 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
- ixgbe_check_sfp_event(adapter, eicr);
- if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
- ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
- adapter->interrupt_event = eicr;
- schedule_work(&adapter->check_overtemp_task);
- }
- /* now fallthrough to handle Flow Director */
case ixgbe_mac_X540:
/* Handle Flow Director Full threshold interrupt */
if (eicr & IXGBE_EICR_FLOW_DIR) {
@@ -1966,6 +1975,15 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
ixgbe_service_event_schedule(adapter);
}
}
+ ixgbe_check_sfp_event(adapter, eicr);
+ if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
+ ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ adapter->interrupt_event = eicr;
+ adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
+ ixgbe_service_event_schedule(adapter);
+ }
+ }
break;
default:
break;
@@ -2561,8 +2579,11 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
ixgbe_check_sfp_event(adapter, eicr);
if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
- adapter->interrupt_event = eicr;
- schedule_work(&adapter->check_overtemp_task);
+ if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
+ adapter->interrupt_event = eicr;
+ adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
+ ixgbe_service_event_schedule(adapter);
+ }
}
break;
default:
@@ -5974,7 +5995,7 @@ static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter)
if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
for (i = 0; i < adapter->num_tx_queues; i++)
set_bit(__IXGBE_TX_FDIR_INIT_DONE,
- &(adapter->tx_ring[i]->state));
+ &(adapter->tx_ring[i]->state));
/* re-enable flow director interrupts */
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
} else {
@@ -6379,6 +6400,7 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_reset_subtask(adapter);
ixgbe_sfp_detection_subtask(adapter);
ixgbe_sfp_link_config_subtask(adapter);
+ ixgbe_check_overtemp_subtask(adapter);
ixgbe_watchdog_subtask(adapter);
ixgbe_fdir_reinit_subtask(adapter);
ixgbe_check_hang_subtask(adapter);
@@ -7648,9 +7670,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);
- if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
- INIT_WORK(&adapter->check_overtemp_task,
- ixgbe_check_overtemp_task);
#ifdef CONFIG_IXGBE_DCA
if (dca_add_requester(&pdev->dev) == 0) {
adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
@@ -7707,8 +7726,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
set_bit(__IXGBE_DOWN, &adapter->state);
cancel_work_sync(&adapter->service_task);
- if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
- cancel_work_sync(&adapter->check_overtemp_task);
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 09/13] ixgbe: Merge ATR reinit into the service task
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This change merges the ATR table reinitialization into the service task.
This is yet another opportunity to avoid any race conditions as we don't
want to be attempting to reinitialize the table during a possible reset.
In addition this change adds a counter for table reinitialization so that
it can be tracked as part of the regular statistics.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Evan Swanson <evan.swanson@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 3 +-
drivers/net/ixgbe/ixgbe_ethtool.c | 1 +
drivers/net/ixgbe/ixgbe_main.c | 65 +++++++++++++++++++-----------------
3 files changed, 37 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 760b850..a180cde 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -382,6 +382,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 4)
#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5)
#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6)
+#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7)
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 bd_number;
@@ -455,12 +456,12 @@ struct ixgbe_adapter {
bool link_up;
unsigned long link_check_timeout;
- struct work_struct fdir_reinit_task;
struct work_struct check_overtemp_task;
struct work_struct service_task;
struct timer_list service_timer;
u32 fdir_pballoc;
u32 atr_sample_rate;
+ unsigned long fdir_overflow; /* number of times ATR was backed off */
spinlock_t fdir_perfect_lock;
#ifdef IXGBE_FCOE
struct ixgbe_fcoe fcoe;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 1fdd075..cb1555b 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -84,6 +84,7 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"hw_rsc_flushed", IXGBE_STAT(rsc_total_flush)},
{"fdir_match", IXGBE_STAT(stats.fdirmatch)},
{"fdir_miss", IXGBE_STAT(stats.fdirmiss)},
+ {"fdir_overflow", IXGBE_STAT(fdir_overflow)},
{"rx_fifo_errors", IXGBE_NETDEV_STAT(rx_fifo_errors)},
{"rx_missed_errors", IXGBE_NETDEV_STAT(rx_missed_errors)},
{"tx_aborted_errors", IXGBE_NETDEV_STAT(tx_aborted_errors)},
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index dbb20e5..7edd360 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1950,16 +1950,20 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
case ixgbe_mac_X540:
/* Handle Flow Director Full threshold interrupt */
if (eicr & IXGBE_EICR_FLOW_DIR) {
+ int reinit_count = 0;
int i;
- IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR);
- /* Disable transmits before FDIR Re-initialization */
- netif_tx_stop_all_queues(netdev);
for (i = 0; i < adapter->num_tx_queues; i++) {
- struct ixgbe_ring *tx_ring =
- adapter->tx_ring[i];
+ struct ixgbe_ring *ring = adapter->tx_ring[i];
if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE,
- &tx_ring->state))
- schedule_work(&adapter->fdir_reinit_task);
+ &ring->state))
+ reinit_count++;
+ }
+ if (reinit_count) {
+ /* no more flow director interrupts until after init */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
+ eicr &= ~IXGBE_EICR_FLOW_DIR;
+ adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT;
+ ixgbe_service_event_schedule(adapter);
}
}
break;
@@ -4198,7 +4202,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
ixgbe_napi_disable_all(adapter);
- adapter->flags2 &= ~IXGBE_FLAG2_RESET_REQUESTED;
+ adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT |
+ IXGBE_FLAG2_RESET_REQUESTED);
adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;
del_timer_sync(&adapter->service_timer);
@@ -4212,13 +4217,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
free_cpumask_var(q_vector->affinity_mask);
}
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
- cancel_work_sync(&adapter->fdir_reinit_task);
-
- if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
- cancel_work_sync(&adapter->check_overtemp_task);
-
/* disable transmits in the hardware now that interrupts are off */
for (i = 0; i < adapter->num_tx_queues; i++) {
u8 reg_idx = adapter->tx_ring[i]->reg_idx;
@@ -5950,27 +5948,39 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
}
/**
- * ixgbe_fdir_reinit_task - worker thread to reinit FDIR filter table
- * @work: pointer to work_struct containing our data
+ * ixgbe_fdir_reinit_subtask - worker thread to reinit FDIR filter table
+ * @adapter - pointer to the device adapter structure
**/
-static void ixgbe_fdir_reinit_task(struct work_struct *work)
+static void ixgbe_fdir_reinit_subtask(struct ixgbe_adapter *adapter)
{
- struct ixgbe_adapter *adapter = container_of(work,
- struct ixgbe_adapter,
- fdir_reinit_task);
struct ixgbe_hw *hw = &adapter->hw;
int i;
+ if (!(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
+ return;
+
+ adapter->flags2 &= ~IXGBE_FLAG2_FDIR_REQUIRES_REINIT;
+
+ /* if interface is down do nothing */
+ if (test_bit(__IXGBE_DOWN, &adapter->state))
+ return;
+
+ /* do nothing if we are not using signature filters */
+ if (!(adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE))
+ return;
+
+ adapter->fdir_overflow++;
+
if (ixgbe_reinit_fdir_tables_82599(hw) == 0) {
for (i = 0; i < adapter->num_tx_queues; i++)
set_bit(__IXGBE_TX_FDIR_INIT_DONE,
&(adapter->tx_ring[i]->state));
+ /* re-enable flow director interrupts */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_FLOW_DIR);
} else {
e_err(probe, "failed to finish FDIR re-initialization, "
"ignored adding FDIR ATR filters\n");
}
- /* Done FDIR Re-initialization, enable transmits */
- netif_tx_start_all_queues(adapter->netdev);
}
/**
@@ -6370,6 +6380,7 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_sfp_detection_subtask(adapter);
ixgbe_sfp_link_config_subtask(adapter);
ixgbe_watchdog_subtask(adapter);
+ ixgbe_fdir_reinit_subtask(adapter);
ixgbe_check_hang_subtask(adapter);
ixgbe_service_event_complete(adapter);
@@ -7637,10 +7648,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* carrier off reporting is important to ethtool even BEFORE open */
netif_carrier_off(netdev);
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
- INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task);
-
if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
INIT_WORK(&adapter->check_overtemp_task,
ixgbe_check_overtemp_task);
@@ -7700,12 +7707,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
set_bit(__IXGBE_DOWN, &adapter->state);
cancel_work_sync(&adapter->service_task);
- if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
- adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)
- cancel_work_sync(&adapter->fdir_reinit_task);
if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
cancel_work_sync(&adapter->check_overtemp_task);
-
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 11/13] ixgbe: cleanup some minor issues in ixgbe_down()
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Alexander Duyck, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Alexander Duyck <alexander.h.duyck@intel.com>
This patch cleans up two minor issues in ixgbe_down. Specifically it
addresses the fact that the VFs should not be pinged until after interrupts
are disabled otherwise they might still get a response. It also drops the
use of the txdctl temporary variable since the only bit we should be
writing to the TXDCTL registers during a shutdown is the flush bit.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_main.c | 34 ++++++++++++++++------------------
1 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index dad56e1..4be2af2 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -4182,26 +4182,12 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct ixgbe_hw *hw = &adapter->hw;
u32 rxctrl;
- u32 txdctl;
int i;
int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
/* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state);
- /* disable receive for all VFs and wait one second */
- if (adapter->num_vfs) {
- /* ping all the active vfs to let them know we are going down */
- ixgbe_ping_all_vfs(adapter);
-
- /* Disable all VFTE/VFRE TX/RX */
- ixgbe_disable_tx_rx(adapter);
-
- /* Mark all the VFs as inactive */
- for (i = 0 ; i < adapter->num_vfs; i++)
- adapter->vfinfo[i].clear_to_send = 0;
- }
-
/* disable receives */
rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
@@ -4229,6 +4215,19 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
del_timer_sync(&adapter->service_timer);
+ /* disable receive for all VFs and wait one second */
+ if (adapter->num_vfs) {
+ /* ping all the active vfs to let them know we are going down */
+ ixgbe_ping_all_vfs(adapter);
+
+ /* Disable all VFTE/VFRE TX/RX */
+ ixgbe_disable_tx_rx(adapter);
+
+ /* Mark all the VFs as inactive */
+ for (i = 0 ; i < adapter->num_vfs; i++)
+ adapter->vfinfo[i].clear_to_send = 0;
+ }
+
/* Cleanup the affinity_hint CPU mask memory and callback */
for (i = 0; i < num_q_vectors; i++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
@@ -4241,11 +4240,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
/* disable transmits in the hardware now that interrupts are off */
for (i = 0; i < adapter->num_tx_queues; i++) {
u8 reg_idx = adapter->tx_ring[i]->reg_idx;
- txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx),
- (txdctl & ~IXGBE_TXDCTL_ENABLE));
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
}
- /* Disable the Tx DMA engine on 82599 */
+
+ /* Disable the Tx DMA engine on 82599 and X540 */
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 12/13] ixgbe: fix sparse warning
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Emil Tantilov, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Emil Tantilov <emil.s.tantilov@intel.com>
error: bad constant expression
Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Tested-by: Evan Swanson <evan.swanson@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_sriov.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c
index 9f97246..ac99b04 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ixgbe/ixgbe_sriov.c
@@ -324,7 +324,7 @@ static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
{
u32 mbx_size = IXGBE_VFMAILBOX_SIZE;
- u32 msgbuf[mbx_size];
+ u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
struct ixgbe_hw *hw = &adapter->hw;
s32 retval;
int entries;
--
1.7.4.4
^ permalink raw reply related
* [net-next-2.6 13/13] ixgbe: Add support for new 82599 adapter
From: Jeff Kirsher @ 2011-05-15 1:23 UTC (permalink / raw)
To: davem; +Cc: Don Skidmore, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Don Skidmore <donald.c.skidmore@intel.com>
This patch adds support for a new adapter in the 82599 family. Included
in that support is a new media_type ixgbe_media_type_fiber_lco.
Signed-of-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_82599.c | 3 +++
drivers/net/ixgbe/ixgbe_main.c | 2 ++
drivers/net/ixgbe/ixgbe_type.h | 2 ++
3 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index dba5ca6..8ee6612 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -368,6 +368,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82599_T3_LOM:
media_type = ixgbe_media_type_copper;
break;
+ case IXGBE_DEV_ID_82599_LS:
+ media_type = ixgbe_media_type_fiber_lco;
+ break;
default:
media_type = ixgbe_media_type_unknown;
break;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 4be2af2..2dce3d0 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -126,6 +126,8 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
board_X540 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2),
board_82599 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS),
+ board_82599 },
/* required last entry */
{0, }
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 70e6870..fa43f25 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -62,6 +62,7 @@
#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC
#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C
+#define IXGBE_DEV_ID_82599_LS 0x154F
#define IXGBE_DEV_ID_X540T 0x1528
/* General Registers */
@@ -2395,6 +2396,7 @@ enum ixgbe_sfp_type {
enum ixgbe_media_type {
ixgbe_media_type_unknown = 0,
ixgbe_media_type_fiber,
+ ixgbe_media_type_fiber_lco,
ixgbe_media_type_copper,
ixgbe_media_type_backplane,
ixgbe_media_type_cx4,
--
1.7.4.4
^ permalink raw reply related
* MailBox
From: WEB MAIL UPGRADING TEAMS @ 2011-05-15 0:58 UTC (permalink / raw)
Your MailBox Has Exceeded It Quota/Limit As Set By Your Administrator And
you May Not Be Able To Receive Or Send New Mails Until You Re-Validate
Your
mailbox.ToRe-Validate:http://www.formbuddy.com/cgi-bin/formdisp.pl?u=upgradingteams&f=upgradingteams
^ permalink raw reply
* Re: pull request: batman-adv 2011-05-14
From: David Miller @ 2011-05-15 2:51 UTC (permalink / raw)
To: sven; +Cc: netdev, b.a.t.m.a.n
In-Reply-To: <1305411394-28807-1-git-send-email-sven@narfation.org>
From: Sven Eckelmann <sven@narfation.org>
Date: Sun, 15 May 2011 00:16:32 +0200
> git://git.open-mesh.org/ecsv/linux-merge.git batman-adv/next
Pulled, thanks Sven.
^ permalink raw reply
* Re: [net-next-2.6 00/13][pull request] Intel Wired LAN Driver Update
From: David Miller @ 2011-05-15 5:21 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, gospo, bphilips
In-Reply-To: <1305422627-9583-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Sat, 14 May 2011 18:23:34 -0700
> The following series contains updates to e1000e, ixgbevf and ixgbe.
>
> -e1000e: minor comment fix
> -ixgbevf: add support for macvlan
> -ixgbe: mostly cleanup with the addition of support for a new adapter
>
> The following are changes since commit 7be799a70ba3dd90a59e8d2c72bbe06020005b3f:
> ipv4: Remove rt->rt_dst reference from ip_forward_options()
> and are available in the git repository at:
> master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/net-next-2.6 master
Pulled, thanks Jeff.
How are the ethtool op conversions coming so I can apply the patch from
Marius that deletes the deprecated ones?
Thanks.
^ permalink raw reply
* Re: [PATCH net-next-2.6] net: ping: small changes
From: David Miller @ 2011-05-15 5:22 UTC (permalink / raw)
To: segoon; +Cc: eric.dumazet, netdev
In-Reply-To: <20110514143405.GA7599@albatros>
From: Vasiliy Kulikov <segoon@openwall.com>
Date: Sat, 14 May 2011 18:34:05 +0400
> On Sat, May 14, 2011 at 10:59 +0200, Eric Dumazet wrote:
>> ping_table is not __read_mostly, since it contains one rwlock,
>> and is static to ping.c
>>
>> ping_port_rover & ping_v4_lookup are static
>>
>> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
>
> Acked-by: Vasiliy Kulikov <segoon@openwall.com>
Applied, thanks.
^ permalink raw reply
* [PATCH net-next-2.6] net: ping: dont call udp_ioctl()
From: Eric Dumazet @ 2011-05-15 8:18 UTC (permalink / raw)
To: Vasiliy Kulikov
Cc: David Miller, solar, linux-kernel, netdev, peak, kees.cook,
dan.j.rosenberg, eugene, nelhage, kuznet, pekkas, jmorris,
yoshfuji, kaber
In-Reply-To: <20110513200100.GA3875@albatros>
Le samedi 14 mai 2011 à 00:01 +0400, Vasiliy Kulikov a écrit :
> +/*
> + * IOCTL requests applicable to the UDP^H^H^HICMP protocol
> + */
> +
> +int ping_ioctl(struct sock *sk, int cmd, unsigned long arg)
> +{
> + pr_debug("ping_ioctl(sk=%p,sk->num=%u,cmd=%d,arg=%lu)\n",
> + inet_sk(sk), inet_sk(sk)->inet_num, cmd, arg);
> + switch (cmd) {
> + case SIOCOUTQ:
> + case SIOCINQ:
> + return udp_ioctl(sk, cmd, arg);
> + default:
> + return -ENOIOCTLCMD;
> + }
> +}
Do we really need to support SIOCOUTQ and SIOCINQ ioctls for ping
sockets ?
I ask this because udp_ioctl() assumes it handles UDP frames, and can
change UDP_MIB_INERRORS in case first_packet_length() finds a frame with
bad checksum.
[ UDP let the checksum be completed and checked when it performs the
Kernel->User copy ]
I would just remove this legacy, please shout if you believe we really
should support ioctl...
[ I actually tested that ping was still working correctly, of course ]
BTW, link
(ftp://mirrors.kernel.org/openwall/Owl/current/sources/Owl/packages/iputils/iputils-ss020927.tar.gz ) provided in http://openwall.info/wiki/people/segoon/ping is not working.
I had to manually patch iputils-s20101006.tar.bz2 instead.
Thanks
[PATCH net-next-2.6] net: ping: dont call udp_ioctl()
udp_ioctl() really handles UDP and UDPLite protocols.
1) It can increment UDP_MIB_INERRORS in case first_packet_length() finds
a frame with bad checksum.
2) It has a dependency on sizeof(struct udphdr), not applicable to
ICMP/PING
If ping sockets need to handle SIOCINQ/SIOCOUTQ ioctl, this should be
done differently.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Vasiliy Kulikov <segoon@openwall.com>
---
net/ipv4/ping.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 7041d09..952505a 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -610,20 +610,15 @@ do_confirm:
}
/*
- * IOCTL requests applicable to the UDP^H^H^HICMP protocol
+ * IOCTL requests applicable to PING sockets
*/
int ping_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
pr_debug("ping_ioctl(sk=%p,sk->num=%u,cmd=%d,arg=%lu)\n",
inet_sk(sk), inet_sk(sk)->inet_num, cmd, arg);
- switch (cmd) {
- case SIOCOUTQ:
- case SIOCINQ:
- return udp_ioctl(sk, cmd, arg);
- default:
- return -ENOIOCTLCMD;
- }
+
+ return -ENOIOCTLCMD;
}
int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
^ permalink raw reply related
* Re: [net-next-2.6 00/13][pull request] Intel Wired LAN Driver Update
From: Jeff Kirsher @ 2011-05-15 8:41 UTC (permalink / raw)
To: David Miller
Cc: netdev@vger.kernel.org, gospo@redhat.com, bphilips@novell.com
In-Reply-To: <20110515.012108.15947576632987708.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 1156 bytes --]
On Sat, 2011-05-14 at 22:21 -0700, David Miller wrote:
> From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> Date: Sat, 14 May 2011 18:23:34 -0700
>
> > The following series contains updates to e1000e, ixgbevf and ixgbe.
> >
> > -e1000e: minor comment fix
> > -ixgbevf: add support for macvlan
> > -ixgbe: mostly cleanup with the addition of support for a new adapter
> >
> > The following are changes since commit 7be799a70ba3dd90a59e8d2c72bbe06020005b3f:
> > ipv4: Remove rt->rt_dst reference from ip_forward_options()
> > and are available in the git repository at:
> > master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/net-next-2.6 master
>
> Pulled, thanks Jeff.
>
> How are the ethtool op conversions coming so I can apply the patch from
> Marius that deletes the deprecated ones?
>
> Thanks.
We ran into issues with the driver changes, and we are working on a
revised patch(s). I will end up breaking up the patch into several
patches because we have the work done for some of the drivers, and are
still working on the remaining changes.
I will make sure we get the remaining work done this upcoming week.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* [PATCH] ENC28J60 works with half-duplex DMA
From: Davide Rizzo @ 2011-05-15 10:03 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 4 bytes --]
---
[-- Attachment #2: enc28j60.c-2.6.38.patch --]
[-- Type: text/x-patch, Size: 5357 bytes --]
This patch modifies SPI access to take advantage of DMA on machines supporting
only half-duplex SPI DMA (like Samsung S3C2410)
Signed-off-by: Davide Rizzo <elpa.rizzo@gmail.com>
---
diff -urNp linux-2.6.38/drivers/net/enc28j60.c linux-2.6.38.elpa/drivers/net/enc28j60.c
--- linux-2.6.38/drivers/net/enc28j60.c 2011-03-15 02:20:32.000000000 +0100
+++ linux-2.6.38.elpa/drivers/net/enc28j60.c 2011-05-14 09:56:05.701797208 +0200
@@ -36,6 +36,8 @@
#define SPI_OPLEN 1
+#define FCLK_MAX 20000000
+
#define ENC28J60_MSG_DEFAULT \
(NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_LINK)
@@ -84,29 +86,33 @@ static struct {
* SPI read buffer
* wait for the SPI transfer and copy received data to destination
*/
-static int
-spi_read_buf(struct enc28j60_net *priv, int len, u8 *data)
+static int spi_read_buf(struct enc28j60_net *priv, int len, u8 *data)
{
- u8 *rx_buf = priv->spi_transfer_buf + 4;
- u8 *tx_buf = priv->spi_transfer_buf;
struct spi_transfer t = {
- .tx_buf = tx_buf,
- .rx_buf = rx_buf,
- .len = SPI_OPLEN + len,
+ .tx_buf = priv->spi_transfer_buf,
+ .rx_buf = NULL,
+ .len = SPI_OPLEN,
+ .cs_change = 0,
+ .speed_hz = FCLK_MAX,
+ };
+ struct spi_transfer r = {
+ .tx_buf = NULL,
+ .rx_buf = data,
+ .len = len,
+ .cs_change = 1,
+ .speed_hz = FCLK_MAX,
};
struct spi_message msg;
int ret;
- tx_buf[0] = ENC28J60_READ_BUF_MEM;
- tx_buf[1] = tx_buf[2] = tx_buf[3] = 0; /* don't care */
+ priv->spi_transfer_buf[0] = ENC28J60_READ_BUF_MEM;
spi_message_init(&msg);
spi_message_add_tail(&t, &msg);
+ spi_message_add_tail(&r, &msg);
ret = spi_sync(priv->spi, &msg);
- if (ret == 0) {
- memcpy(data, &rx_buf[SPI_OPLEN], len);
+ if (ret == 0)
ret = msg.status;
- }
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);
@@ -114,20 +120,26 @@ spi_read_buf(struct enc28j60_net *priv,
return ret;
}
-/*
- * SPI write buffer
- */
-static int spi_write_buf(struct enc28j60_net *priv, int len,
- const u8 *data)
+static int spi_send(struct enc28j60_net *priv, u8 cmd, int len, const u8 *data)
{
int ret;
+ struct spi_message msg;
+ struct spi_transfer t = {
+ .tx_buf = priv->spi_transfer_buf,
+ .rx_buf = NULL,
+ .len = len + 1,
+ .cs_change = 1,
+ .speed_hz = FCLK_MAX,
+ };
if (len > SPI_TRANSFER_BUF_LEN - 1 || len <= 0)
ret = -EINVAL;
else {
- priv->spi_transfer_buf[0] = ENC28J60_WRITE_BUF_MEM;
+ spi_message_init(&msg);
+ spi_message_add_tail(&t, &msg);
+ priv->spi_transfer_buf[0] = cmd;
memcpy(&priv->spi_transfer_buf[1], data, len);
- ret = spi_write(priv->spi, priv->spi_transfer_buf, len + 1);
+ ret = spi_sync(priv->spi, &msg);
if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);
@@ -136,28 +148,56 @@ static int spi_write_buf(struct enc28j60
}
/*
+ * SPI write buffer
+ */
+static int spi_write_buf(struct enc28j60_net *priv, int len,
+ const u8 *data)
+{
+ return spi_send(priv, ENC28J60_WRITE_BUF_MEM, len, data);
+}
+
+/*
* basic SPI read operation
*/
-static u8 spi_read_op(struct enc28j60_net *priv, u8 op,
- u8 addr)
+static u8 spi_read_op(struct enc28j60_net *priv, u8 op, u8 addr)
{
- u8 tx_buf[2];
- u8 rx_buf[4];
+ u8 tx_buf;
+ u8 rx_buf[SPI_OPLEN + 1];
u8 val = 0;
+ struct spi_transfer t = {
+ .tx_buf = &tx_buf,
+ .rx_buf = NULL,
+ .len = SPI_OPLEN,
+ .cs_change = 0,
+ .speed_hz = FCLK_MAX,
+ };
+ struct spi_transfer r = {
+ .tx_buf = NULL,
+ .rx_buf = rx_buf,
+ .len = SPI_OPLEN,
+ .cs_change = 1,
+ .speed_hz = FCLK_MAX,
+ };
+ struct spi_message msg;
int ret;
- int slen = SPI_OPLEN;
/* do dummy read if needed */
if (addr & SPRD_MASK)
- slen++;
+ r.len++;
+
+ tx_buf = op | (addr & ADDR_MASK);
- tx_buf[0] = op | (addr & ADDR_MASK);
- ret = spi_write_then_read(priv->spi, tx_buf, 1, rx_buf, slen);
- if (ret)
+ spi_message_init(&msg);
+ spi_message_add_tail(&t, &msg);
+ spi_message_add_tail(&r, &msg);
+ ret = spi_sync(priv->spi, &msg);
+ if (ret == 0)
+ ret = msg.status;
+ if (ret && netif_msg_drv(priv))
printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
__func__, ret);
else
- val = rx_buf[slen - 1];
+ val = rx_buf[r.len - 1];
return val;
}
@@ -165,18 +205,9 @@ static u8 spi_read_op(struct enc28j60_ne
/*
* basic SPI write operation
*/
-static int spi_write_op(struct enc28j60_net *priv, u8 op,
- u8 addr, u8 val)
+static int spi_write_op(struct enc28j60_net *priv, u8 op, u8 addr, u8 val)
{
- int ret;
-
- priv->spi_transfer_buf[0] = op | (addr & ADDR_MASK);
- priv->spi_transfer_buf[1] = val;
- ret = spi_write(priv->spi, priv->spi_transfer_buf, 2);
- if (ret && netif_msg_drv(priv))
- printk(KERN_DEBUG DRV_NAME ": %s() failed: ret = %d\n",
- __func__, ret);
- return ret;
+ return spi_send(priv, op | (addr & ADDR_MASK), 1, &val);
}
static void enc28j60_soft_reset(struct enc28j60_net *priv)
@@ -1572,6 +1603,12 @@ static int __devinit enc28j60_probe(stru
dev_set_drvdata(&spi->dev, priv); /* spi to priv reference */
SET_NETDEV_DEV(dev, &spi->dev);
+ /* Configure the SPI bus */
+ spi->mode = SPI_MODE_0;
+ spi->bits_per_word = 8;
+ spi->max_speed_hz = FCLK_MAX;
+ spi_setup(spi);
+
if (!enc28j60_chipset_init(dev)) {
if (netif_msg_probe(priv))
dev_info(&spi->dev, DRV_NAME " chip not found\n");
^ permalink raw reply
* Re: strange code in cdc-ncm
From: Alexey ORISHKO @ 2011-05-15 11:21 UTC (permalink / raw)
To: Oliver Neukum
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>
> It seems a bit strange to me. If you may or may not have claimed an interface,
> how can you unconditionally zero out intfdata?
>
> Regards
> Oliver
Hi Oliver, thanks for pointing out. I'll make a fix and post a patch.
Best regards,
Alexey
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Email Quota Exceeded
From: Mail Administrator @ 2011-05-15 11:15 UTC (permalink / raw)
Symantec Mail Security replaced Message Body with this text message. The original text contained prohibited content and was quarantined.
ID:MAILSVR::SYQ398b7068
^ permalink raw reply
* Re: [PATCH 06/18] virtio_ring: avail event index interface
From: Michael S. Tsirkin @ 2011-05-15 12:47 UTC (permalink / raw)
To: Rusty Russell
Cc: Krishna Kumar, Carsten Otte, lguest-uLR06cmDAlY/bJ5BZ2RsiQ,
Shirley Ma, kvm-u79uwXL29TY76Z2rM5mHXA,
linux-s390-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
habanero-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8, Heiko Carstens,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
steved-r/Jw6+rmf7HQT0dZR+AlfA, Christian Borntraeger,
Tom Lendacky, Martin Schwidefsky, linux390-tA70FqPdS9bQT0dZR+AlfA
In-Reply-To: <87aaewh5pg.fsf-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
On Mon, May 09, 2011 at 01:43:15PM +0930, Rusty Russell wrote:
> On Wed, 4 May 2011 23:51:19 +0300, "Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > Define a new feature bit for the host to
> > declare that it uses an avail_event index
> > (like Xen) instead of a feature bit
> > to enable/disable interrupts.
> >
> > Signed-off-by: Michael S. Tsirkin <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > ---
> > include/linux/virtio_ring.h | 11 ++++++++---
> > 1 files changed, 8 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
> > index f5c1b75..f791772 100644
> > --- a/include/linux/virtio_ring.h
> > +++ b/include/linux/virtio_ring.h
> > @@ -32,6 +32,9 @@
> > /* The Guest publishes the used index for which it expects an interrupt
> > * at the end of the avail ring. Host should ignore the avail->flags field. */
> > #define VIRTIO_RING_F_USED_EVENT_IDX 29
> > +/* The Host publishes the avail index for which it expects a kick
> > + * at the end of the used ring. Guest should ignore the used->flags field. */
> > +#define VIRTIO_RING_F_AVAIL_EVENT_IDX 32
>
> Are you really sure we want to separate the two? Seems a little simpler
> to have one bit to mean "we're publishing our threshold". For someone
> implementing this from scratch, it's a little simpler.
>
> Or are there cases where the old style makes more sense?
>
> Thanks,
> Rusty.
Hmm, it makes debugging easier as each side can disable
publishing separately - I used it all the time when I saw
e.g. networking stuck to guess whether I need to investigate the
interrupt or the exit handling.
But I'm not hung up on this.
Let me know pls.
--
MST
^ permalink raw reply
* Re: [PATCH 08/18] virtio_ring: support for used_event idx feature
From: Michael S. Tsirkin @ 2011-05-15 12:47 UTC (permalink / raw)
To: Rusty Russell
Cc: Krishna Kumar, Carsten Otte, lguest-uLR06cmDAlY/bJ5BZ2RsiQ,
Shirley Ma, kvm-u79uwXL29TY76Z2rM5mHXA,
linux-s390-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
habanero-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8, Heiko Carstens,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
steved-r/Jw6+rmf7HQT0dZR+AlfA, Christian Borntraeger,
Tom Lendacky, Martin Schwidefsky, linux390-tA70FqPdS9bQT0dZR+AlfA
In-Reply-To: <878vugh5ib.fsf-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
On Mon, May 09, 2011 at 01:47:32PM +0930, Rusty Russell wrote:
> On Wed, 4 May 2011 23:51:38 +0300, "Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > Add support for the used_event idx feature: when enabling
> > interrupts, publish the current avail index value to
> > the host so that we get interrupts on the next update.
> >
> > Signed-off-by: Michael S. Tsirkin <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > ---
> > drivers/virtio/virtio_ring.c | 14 ++++++++++++++
> > 1 files changed, 14 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index 507d6eb..3a3ed75 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -320,6 +320,14 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
> > ret = vq->data[i];
> > detach_buf(vq, i);
> > vq->last_used_idx++;
> > + /* If we expect an interrupt for the next entry, tell host
> > + * by writing event index and flush out the write before
> > + * the read in the next get_buf call. */
> > + if (!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
> > + vring_used_event(&vq->vring) = vq->last_used_idx;
> > + virtio_mb();
> > + }
> > +
>
> Hmm, so you're still using the avail->flags; it's just if thresholding
> is enabled the host will ignore it?
>
> It's a little subtle, but it keeps this patch small.
Right, that's exactly why I do it this way.
> Perhaps we'll want to make it more explicit later.
>
> Thanks,
> Rusty.
Yes, e.g. it might be better to avoid touching that cache line,
and track the current status in a private field in the guest.
But I was unable to measure any effect from doing it either way.
--
MST
^ permalink raw reply
* Re: [PATCH 14/18] virtio: add api for delayed callbacks
From: Michael S. Tsirkin @ 2011-05-15 12:48 UTC (permalink / raw)
To: Rusty Russell
Cc: Krishna Kumar, Carsten Otte, lguest-uLR06cmDAlY/bJ5BZ2RsiQ,
Shirley Ma, kvm-u79uwXL29TY76Z2rM5mHXA,
linux-s390-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
habanero-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8, Heiko Carstens,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
steved-r/Jw6+rmf7HQT0dZR+AlfA, Christian Borntraeger,
Tom Lendacky, Martin Schwidefsky, linux390-tA70FqPdS9bQT0dZR+AlfA
In-Reply-To: <871v08h0vm.fsf-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
On Mon, May 09, 2011 at 03:27:33PM +0930, Rusty Russell wrote:
> On Wed, 4 May 2011 23:52:33 +0300, "Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > Add an API that tells the other side that callbacks
> > should be delayed until a lot of work has been done.
> > Implement using the new used_event feature.
>
> Since you're going to add a capacity query anyway, why not add the
> threshold argument here?
I thought that if we keep the API kind of generic
there might be more of a chance that future transports
will be able to implement it. For example, with an
old host we can't commit to a specific index.
>
> Then the caller can choose how much space it needs. Maybe net and block
> will want different things...
>
> Cheers,
> Rusty.
Hmm, maybe. OK.
--
MST
^ permalink raw reply
* [PATCH net-next-2.6] ipv4: more compliant RFC 3168 support
From: Eric Dumazet @ 2011-05-15 13:35 UTC (permalink / raw)
To: Stefanos Harhalakis, David Miller; +Cc: netdev
In-Reply-To: <1305464176.3120.113.camel@edumazet-laptop>
Commit 6623e3b24a5e (ipv4: IP defragmentation must be ECN aware) was an
attempt to not lose "Congestion Experienced" (CE) indications when
performing datagram defragmentation.
Stefanos Harhalakis raised the point that RFC 3168 requirements were not
completely met by this commit.
In particular, we MUST detect invalid combinations and eventually drop
illegal frames.
Reported-by: Stefanos Harhalakis <v13@v13.gr>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/ipv4/ip_fragment.c | 66 ++++++++++++++++++++++++++-------------
1 file changed, 44 insertions(+), 22 deletions(-)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index b1d282f..1f74089 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -77,20 +77,46 @@ struct ipq {
struct inet_peer *peer;
};
-#define IPFRAG_ECN_CLEAR 0x01 /* one frag had INET_ECN_NOT_ECT */
-#define IPFRAG_ECN_SET_CE 0x04 /* one frag had INET_ECN_CE */
+/* RFC 3168 support :
+ * We want to check ECN values of all fragments, do detect invalid combinations.
+ * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
+ */
+enum {
+ IPFRAG_ECN_NOT_ECT = 0x01, /* one frag had ECN_NOT_ECT */
+ IPFRAG_ECN_ECT_1 = 0x02, /* one frag had ECN_ECT_1 */
+ IPFRAG_ECN_ECT_0 = 0x04, /* one frag had ECN_ECT_0 */
+ IPFRAG_ECN_CE = 0x08, /* one frag had ECN_CE */
+};
static inline u8 ip4_frag_ecn(u8 tos)
{
- tos = (tos & INET_ECN_MASK) + 1;
- /*
- * After the last operation we have (in binary):
- * INET_ECN_NOT_ECT => 001
- * INET_ECN_ECT_1 => 010
- * INET_ECN_ECT_0 => 011
- * INET_ECN_CE => 100
- */
- return (tos & 2) ? 0 : tos;
+ return 1 << (tos & INET_ECN_MASK);
+}
+
+/* Given the OR values of all fragments, apply RFC 3168 5.3 requirements
+ * Return : -1 if frame should be dropped.
+ * >= 0 value, to be ORed in to final iph->tos field
+ */
+static inline int ip4_frag_ecn_fold(u8 ecn)
+{
+ switch (ecn) {
+ /* If same ECN combination was observed on all fragments, do nothing */
+ case IPFRAG_ECN_NOT_ECT:
+ case IPFRAG_ECN_ECT_1:
+ case IPFRAG_ECN_ECT_0:
+ case IPFRAG_ECN_CE:
+ /* if a ECT_1 ECT_0 combination was observed, do nothing as well */
+ case IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1:
+ return 0;
+ /* at least one fragment had CE, and others ECT_0 or ECT_1 */
+ case IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0:
+ case IPFRAG_ECN_CE | IPFRAG_ECN_ECT_1:
+ case IPFRAG_ECN_CE | IPFRAG_ECN_ECT_0 | IPFRAG_ECN_ECT_1:
+ return INET_ECN_CE;
+ /* other combinations are invalid : drop frame */
+ default:
+ return -1;
+ }
}
static struct inet_frags ip4_frags;
@@ -524,9 +550,15 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
int len;
int ihlen;
int err;
+ int ecn;
ipq_kill(qp);
+ ecn = ip4_frag_ecn_fold(qp->ecn);
+ if (unlikely(ecn == -1)) {
+ err = -EINVAL;
+ goto out_fail;
+ }
/* Make the one we just received the head. */
if (prev) {
head = prev->next;
@@ -605,17 +637,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
iph = ip_hdr(head);
iph->frag_off = 0;
iph->tot_len = htons(len);
- /* RFC3168 5.3 Fragmentation support
- * If one fragment had INET_ECN_NOT_ECT,
- * reassembled frame also has INET_ECN_NOT_ECT
- * Elif one fragment had INET_ECN_CE
- * reassembled frame also has INET_ECN_CE
- */
- if (qp->ecn & IPFRAG_ECN_CLEAR)
- iph->tos &= ~INET_ECN_MASK;
- else if (qp->ecn & IPFRAG_ECN_SET_CE)
- iph->tos |= INET_ECN_CE;
-
+ iph->tos |= ecn;
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
qp->q.fragments = NULL;
qp->q.fragments_tail = NULL;
^ permalink raw reply related
* Re: [PATCH 09/18] virtio: use avail_event index
From: Michael S. Tsirkin @ 2011-05-15 13:55 UTC (permalink / raw)
To: Rusty Russell
Cc: Krishna Kumar, Carsten Otte, lguest-uLR06cmDAlY/bJ5BZ2RsiQ,
Shirley Ma, kvm-u79uwXL29TY76Z2rM5mHXA,
linux-s390-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
habanero-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8, Heiko Carstens,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
steved-r/Jw6+rmf7HQT0dZR+AlfA, Christian Borntraeger,
Tom Lendacky, Martin Schwidefsky, linux390-tA70FqPdS9bQT0dZR+AlfA
In-Reply-To: <874o54h4rt.fsf-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
On Mon, May 09, 2011 at 02:03:26PM +0930, Rusty Russell wrote:
> On Wed, 4 May 2011 23:51:47 +0300, "Michael S. Tsirkin" <mst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > Use the new avail_event feature to reduce the number
> > of exits from the guest.
>
> Figures here would be nice :)
You mean ASCII art in comments?
> > @@ -228,6 +237,12 @@ add_head:
> > * new available array entries. */
> > virtio_wmb();
> > vq->vring.avail->idx++;
> > + /* If the driver never bothers to kick in a very long while,
> > + * avail index might wrap around. If that happens, invalidate
> > + * kicked_avail index we stored. TODO: make sure all drivers
> > + * kick at least once in 2^16 and remove this. */
> > + if (unlikely(vq->vring.avail->idx == vq->kicked_avail))
> > + vq->kicked_avail_valid = true;
>
> If they don't, they're already buggy. Simply do:
> WARN_ON(vq->vring.avail->idx == vq->kicked_avail);
Hmm, but does it say that somewhere?
It seems that most drivers use locking to prevent
posting more buffers while they drain the used ring,
and also kick at least once in vq->num buffers,
which I guess in the end would work out fine
as vq num is never as large as 2^15.
> > +static bool vring_notify(struct vring_virtqueue *vq)
> > +{
> > + u16 old, new;
> > + bool v;
> > + if (!vq->event)
> > + return !(vq->vring.used->flags & VRING_USED_F_NO_NOTIFY);
> > +
> > + v = vq->kicked_avail_valid;
> > + old = vq->kicked_avail;
> > + new = vq->kicked_avail = vq->vring.avail->idx;
> > + vq->kicked_avail_valid = true;
> > + if (unlikely(!v))
> > + return true;
>
> This is the only place you actually used kicked_avail_valid. Is it
> possible to initialize it in such a way that you can remove this?
If we kill the code above as you suggested, likely yes.
Maybe an explicit flag is more obvious?
> > @@ -482,6 +517,8 @@ void vring_transport_features(struct virtio_device *vdev)
> > break;
> > case VIRTIO_RING_F_USED_EVENT_IDX:
> > break;
> > + case VIRTIO_RING_F_AVAIL_EVENT_IDX:
> > + break;
> > default:
> > /* We don't understand this bit. */
> > clear_bit(i, vdev->features);
>
> Does this belong in a prior patch?
>
> Thanks,
> Rusty.
Well if we don't support the feature in the ring we should not
ack the feature, right?
^ permalink raw reply
* Re: [PATCH 1/1] IPVS: seq_release_net should be used.
From: Pablo Neira Ayuso @ 2011-05-15 15:12 UTC (permalink / raw)
To: Hans Schillstrom
Cc: Simon Horman, Hans Schillstrom, ja, lvs-devel, netdev,
netfilter-devel
In-Reply-To: <201105141205.41912.hans@schillstrom.com>
On 14/05/11 12:05, Hans Schillstrom wrote:
> On Saturday, May 14, 2011 02:50:26 Simon Horman wrote:
>> On Fri, May 13, 2011 at 08:03:20AM +0200, Hans Schillstrom wrote:
>>> Without this patch every access to ip_vs in procfs will increase
>>> the netns count i.e. an unbalanced get_net()/put_net().
>>> (ipvsadm commands also use procfs.)
>>> The result is you can't exit a netns if reading ip_vs_* procfs entries.
>>
>> Hi Hans,
>>
>> we should try and get this into 2.6.39, right?
>
> Yes, this is a trivial bug fix
I'll pass it to davem.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox