Commit 032b734d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (27 commits)
  sfc: Change falcon_probe_board() to fail for unsupported boards
  sfc: Always close net device at the end of a disabling reset
  sfc: Wait at most 10ms for the MC to finish reading out MAC statistics
  sctp: Fix oops when sending queued ASCONF chunks
  sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
  sctp: per_cpu variables should be in bh_disabled section
  sctp: fix potential reference of a freed pointer
  sctp: avoid irq lock inversion while call sk->sk_data_ready()
  Revert "tcp: bind() fix when many ports are bound"
  net/usb: add sierra_net.c driver
  cdc_ether: fix autosuspend for mbm devices
  bluetooth: handle l2cap_create_connless_pdu() errors
  gianfar: Wait for both RX and TX to stop
  ipheth: potential null dereferences on error path
  smc91c92_cs: spin_unlock_irqrestore before calling smc_interrupt()
  drivers/usb/net/kaweth.c: add device "Allied Telesyn AT-USB10 USB Ethernet Adapter"
  bnx2: Update version to 2.0.9.
  bnx2: Prevent "scheduling while atomic" warning with cnic, bonding and vlan.
  bnx2: Fix lost MSI-X problem on 5709 NICs.
  cxgb3: Wait longer for control packets on initialization
  ...
parents 3fb938b2 e41c11ee
......@@ -58,8 +58,8 @@
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
#define DRV_MODULE_VERSION "2.0.8"
#define DRV_MODULE_RELDATE "Feb 15, 2010"
#define DRV_MODULE_VERSION "2.0.9"
#define DRV_MODULE_RELDATE "April 27, 2010"
#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j6.fw"
#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-5.0.0.j3.fw"
#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-5.0.0.j9.fw"
......@@ -651,9 +651,10 @@ bnx2_napi_enable(struct bnx2 *bp)
}
static void
bnx2_netif_stop(struct bnx2 *bp)
bnx2_netif_stop(struct bnx2 *bp, bool stop_cnic)
{
bnx2_cnic_stop(bp);
if (stop_cnic)
bnx2_cnic_stop(bp);
if (netif_running(bp->dev)) {
int i;
......@@ -671,14 +672,15 @@ bnx2_netif_stop(struct bnx2 *bp)
}
static void
bnx2_netif_start(struct bnx2 *bp)
bnx2_netif_start(struct bnx2 *bp, bool start_cnic)
{
if (atomic_dec_and_test(&bp->intr_sem)) {
if (netif_running(bp->dev)) {
netif_tx_wake_all_queues(bp->dev);
bnx2_napi_enable(bp);
bnx2_enable_int(bp);
bnx2_cnic_start(bp);
if (start_cnic)
bnx2_cnic_start(bp);
}
}
}
......@@ -4759,8 +4761,12 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
rc = bnx2_alloc_bad_rbuf(bp);
}
if (bp->flags & BNX2_FLAG_USING_MSIX)
if (bp->flags & BNX2_FLAG_USING_MSIX) {
bnx2_setup_msix_tbl(bp);
/* Prevent MSIX table reads and write from timing out */
REG_WR(bp, BNX2_MISC_ECO_HW_CTL,
BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN);
}
return rc;
}
......@@ -6273,12 +6279,12 @@ bnx2_reset_task(struct work_struct *work)
return;
}
bnx2_netif_stop(bp);
bnx2_netif_stop(bp, true);
bnx2_init_nic(bp, 1);
atomic_set(&bp->intr_sem, 1);
bnx2_netif_start(bp);
bnx2_netif_start(bp, true);
rtnl_unlock();
}
......@@ -6320,7 +6326,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
struct bnx2 *bp = netdev_priv(dev);
if (netif_running(dev))
bnx2_netif_stop(bp);
bnx2_netif_stop(bp, false);
bp->vlgrp = vlgrp;
......@@ -6331,7 +6337,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
bnx2_netif_start(bp);
bnx2_netif_start(bp, false);
}
#endif
......@@ -7051,9 +7057,9 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
if (netif_running(bp->dev)) {
bnx2_netif_stop(bp);
bnx2_netif_stop(bp, true);
bnx2_init_nic(bp, 0);
bnx2_netif_start(bp);
bnx2_netif_start(bp, true);
}
return 0;
......@@ -7083,7 +7089,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
/* Reset will erase chipset stats; save them */
bnx2_save_stats(bp);
bnx2_netif_stop(bp);
bnx2_netif_stop(bp, true);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
......@@ -7111,7 +7117,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
bnx2_setup_cnic_irq_info(bp);
mutex_unlock(&bp->cnic_lock);
#endif
bnx2_netif_start(bp);
bnx2_netif_start(bp, true);
}
return 0;
}
......@@ -7364,7 +7370,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
if (etest->flags & ETH_TEST_FL_OFFLINE) {
int i;
bnx2_netif_stop(bp);
bnx2_netif_stop(bp, true);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG);
bnx2_free_skbs(bp);
......@@ -7383,7 +7389,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
bnx2_shutdown_chip(bp);
else {
bnx2_init_nic(bp, 1);
bnx2_netif_start(bp);
bnx2_netif_start(bp, true);
}
/* wait for link up */
......@@ -8377,7 +8383,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
flush_scheduled_work();
bnx2_netif_stop(bp);
bnx2_netif_stop(bp, true);
netif_device_detach(dev);
del_timer_sync(&bp->timer);
bnx2_shutdown_chip(bp);
......@@ -8399,7 +8405,7 @@ bnx2_resume(struct pci_dev *pdev)
bnx2_set_power_state(bp, PCI_D0);
netif_device_attach(dev);
bnx2_init_nic(bp, 1);
bnx2_netif_start(bp);
bnx2_netif_start(bp, true);
return 0;
}
......@@ -8426,7 +8432,7 @@ static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,
}
if (netif_running(dev)) {
bnx2_netif_stop(bp);
bnx2_netif_stop(bp, true);
del_timer_sync(&bp->timer);
bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
}
......@@ -8483,7 +8489,7 @@ static void bnx2_io_resume(struct pci_dev *pdev)
rtnl_lock();
if (netif_running(dev))
bnx2_netif_start(bp);
bnx2_netif_start(bp, true);
netif_device_attach(dev);
rtnl_unlock();
......
......@@ -439,7 +439,7 @@ static void free_irq_resources(struct adapter *adapter)
static int await_mgmt_replies(struct adapter *adap, unsigned long init_cnt,
unsigned long n)
{
int attempts = 5;
int attempts = 10;
while (adap->sge.qs[0].rspq.offload_pkts < init_cnt + n) {
if (!--attempts)
......
......@@ -336,7 +336,6 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
static int global_quad_port_a; /* global port a indication */
struct pci_dev *pdev = adapter->pdev;
u16 eeprom_data = 0;
int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1;
s32 rc;
......@@ -387,16 +386,15 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)
adapter->flags &= ~FLAG_HAS_WOL;
break;
case e1000_82573:
case e1000_82574:
case e1000_82583:
/* Disable ASPM L0s due to hardware errata */
e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L0S);
if (pdev->device == E1000_DEV_ID_82573L) {
if (e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1,
&eeprom_data) < 0)
break;
if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) {
adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
adapter->max_hw_frame_size = DEFAULT_JUMBO;
}
adapter->flags |= FLAG_HAS_JUMBO_FRAMES;
adapter->max_hw_frame_size = DEFAULT_JUMBO;
}
break;
default:
......@@ -1792,6 +1790,7 @@ struct e1000_info e1000_82571_info = {
| FLAG_RESET_OVERWRITES_LAA /* errata */
| FLAG_TARC_SPEED_MODE_BIT /* errata */
| FLAG_APME_CHECK_PORT_B,
.flags2 = FLAG2_DISABLE_ASPM_L1, /* errata 13 */
.pba = 38,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
......@@ -1809,6 +1808,7 @@ struct e1000_info e1000_82572_info = {
| FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_TARC_SPEED_MODE_BIT, /* errata */
.flags2 = FLAG2_DISABLE_ASPM_L1, /* errata 13 */
.pba = 38,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
......@@ -1820,13 +1820,11 @@ struct e1000_info e1000_82572_info = {
struct e1000_info e1000_82573_info = {
.mac = e1000_82573,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
| FLAG_RX_CSUM_ENABLED
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
| FLAG_HAS_ERT
| FLAG_HAS_SWSM_ON_LOAD,
.pba = 20,
.max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN,
......
......@@ -37,6 +37,7 @@
#include <linux/io.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/pci-aspm.h>
#include "hw.h"
......@@ -374,7 +375,7 @@ struct e1000_adapter {
struct e1000_info {
enum e1000_mac_type mac;
unsigned int flags;
unsigned int flags2;
unsigned int flags2;
u32 pba;
u32 max_hw_frame_size;
s32 (*get_variants)(struct e1000_adapter *);
......@@ -421,6 +422,7 @@ struct e1000_info {
#define FLAG2_CRC_STRIPPING (1 << 0)
#define FLAG2_HAS_PHY_WAKEUP (1 << 1)
#define FLAG2_IS_DISCARDING (1 << 2)
#define FLAG2_DISABLE_ASPM_L1 (1 << 3)
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
......@@ -461,6 +463,7 @@ extern void e1000e_update_stats(struct e1000_adapter *adapter);
extern bool e1000e_has_link(struct e1000_adapter *adapter);
extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
extern unsigned int copybreak;
......
......@@ -4283,6 +4283,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
/* 82573 Errata 17 */
if (((adapter->hw.mac.type == e1000_82573) ||
(adapter->hw.mac.type == e1000_82574)) &&
(max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) {
adapter->flags2 |= FLAG2_DISABLE_ASPM_L1;
e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1);
}
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
msleep(1);
/* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */
......@@ -4605,29 +4613,39 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
}
}
static void e1000e_disable_l1aspm(struct pci_dev *pdev)
#ifdef CONFIG_PCIEASPM
static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
{
pci_disable_link_state(pdev, state);
}
#else
static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
{
int pos;
u16 val;
u16 reg16;
/*
* 82573 workaround - disable L1 ASPM on mobile chipsets
*
* L1 ASPM on various mobile (ich7) chipsets do not behave properly
* resulting in lost data or garbage information on the pci-e link
* level. This could result in (false) bad EEPROM checksum errors,
* long ping times (up to 2s) or even a system freeze/hang.
*
* Unfortunately this feature saves about 1W power consumption when
* active.
* Both device and parent should have the same ASPM setting.
* Disable ASPM in downstream component first and then upstream.
*/
pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val);
if (val & 0x2) {
dev_warn(&pdev->dev, "Disabling L1 ASPM\n");
val &= ~0x2;
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val);
}
pos = pci_pcie_cap(pdev);
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
reg16 &= ~state;
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
pos = pci_pcie_cap(pdev->bus->self);
pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, &reg16);
reg16 &= ~state;
pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16);
}
#endif
void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
{
dev_info(&pdev->dev, "Disabling ASPM %s %s\n",
(state & PCIE_LINK_STATE_L0S) ? "L0s" : "",
(state & PCIE_LINK_STATE_L1) ? "L1" : "");
__e1000e_disable_aspm(pdev, state);
}
#ifdef CONFIG_PM
......@@ -4653,7 +4671,8 @@ static int e1000_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
pci_save_state(pdev);
e1000e_disable_l1aspm(pdev);
if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
err = pci_enable_device_mem(pdev);
if (err) {
......@@ -4795,7 +4814,8 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
int err;
pci_ers_result_t result;
e1000e_disable_l1aspm(pdev);
if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
err = pci_enable_device_mem(pdev);
if (err) {
dev_err(&pdev->dev,
......@@ -4889,13 +4909,6 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
dev_warn(&adapter->pdev->dev,
"Warning: detected DSPD enabled in EEPROM\n");
}
ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf);
if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) {
/* ASPM enable */
dev_warn(&adapter->pdev->dev,
"Warning: detected ASPM enabled in EEPROM\n");
}
}
static const struct net_device_ops e1000e_netdev_ops = {
......@@ -4944,7 +4957,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
u16 eeprom_data = 0;
u16 eeprom_apme_mask = E1000_EEPROM_APME;
e1000e_disable_l1aspm(pdev);
if (ei->flags2 & FLAG2_DISABLE_ASPM_L1)
e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
err = pci_enable_device_mem(pdev);
if (err)
......
......@@ -1511,9 +1511,9 @@ static void gfar_halt_nodisable(struct net_device *dev)
tempval |= (DMACTRL_GRS | DMACTRL_GTS);
gfar_write(&regs->dmactrl, tempval);
while (!(gfar_read(&regs->ievent) &
(IEVENT_GRSC | IEVENT_GTSC)))
cpu_relax();
spin_event_timeout(((gfar_read(&regs->ievent) &
(IEVENT_GRSC | IEVENT_GTSC)) ==
(IEVENT_GRSC | IEVENT_GTSC)), -1, 0);
}
}
......
......@@ -39,6 +39,8 @@
#define IXGBE_82599_MC_TBL_SIZE 128
#define IXGBE_82599_VFT_TBL_SIZE 128
void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
......@@ -69,8 +71,14 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
if (hw->phy.multispeed_fiber) {
/* Set up dual speed SFP+ support */
mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
mac->ops.disable_tx_laser =
&ixgbe_disable_tx_laser_multispeed_fiber;
mac->ops.enable_tx_laser =
&ixgbe_enable_tx_laser_multispeed_fiber;
mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber;
} else {
mac->ops.disable_tx_laser = NULL;
mac->ops.enable_tx_laser = NULL;
mac->ops.flap_tx_laser = NULL;
if ((mac->ops.get_media_type(hw) ==
ixgbe_media_type_backplane) &&
......@@ -415,6 +423,44 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
return status;
}
/**
* ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
* @hw: pointer to hardware structure
*
* The base drivers may require better control over SFP+ module
* PHY states. This includes selectively shutting down the Tx
* laser on the PHY, effectively halting physical link.
**/
void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
/* Disable tx laser; allow 100us to go dark per spec */
esdp_reg |= IXGBE_ESDP_SDP3;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
IXGBE_WRITE_FLUSH(hw);
udelay(100);
}
/**
* ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser
* @hw: pointer to hardware structure
*
* The base drivers may require better control over SFP+ module
* PHY states. This includes selectively turning on the Tx
* laser on the PHY, effectively starting physical link.
**/
void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
/* Enable tx laser; allow 100ms to light up */
esdp_reg &= ~IXGBE_ESDP_SDP3;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
IXGBE_WRITE_FLUSH(hw);
msleep(100);
}
/**
* ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser
* @hw: pointer to hardware structure
......@@ -429,23 +475,11 @@ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
**/
void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
{
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n");
if (hw->mac.autotry_restart) {
/* Disable tx laser; allow 100us to go dark per spec */
esdp_reg |= IXGBE_ESDP_SDP3;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
IXGBE_WRITE_FLUSH(hw);
udelay(100);
/* Enable tx laser; allow 100ms to light up */
esdp_reg &= ~IXGBE_ESDP_SDP3;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
IXGBE_WRITE_FLUSH(hw);
msleep(100);
ixgbe_disable_tx_laser_multispeed_fiber(hw);
ixgbe_enable_tx_laser_multispeed_fiber(hw);
hw->mac.autotry_restart = false;
}
}
......
......@@ -2982,6 +2982,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
else
ixgbe_configure_msi_and_legacy(adapter);
/* enable the optics */
if (hw->phy.multispeed_fiber)
hw->mac.ops.enable_tx_laser(hw);
clear_bit(__IXGBE_DOWN, &adapter->state);
ixgbe_napi_enable_all(adapter);
......@@ -3243,6 +3247,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
/* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state);
/* power down the optics */
if (hw->phy.multispeed_fiber)
hw->mac.ops.disable_tx_laser(hw);
/* 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 */
......@@ -6253,6 +6261,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
goto err_eeprom;
}
/* power down the optics */
if (hw->phy.multispeed_fiber)
hw->mac.ops.disable_tx_laser(hw);
init_timer(&adapter->watchdog_timer);
adapter->watchdog_timer.function = &ixgbe_watchdog;
adapter->watchdog_timer.data = (unsigned long)adapter;
......@@ -6400,16 +6412,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
del_timer_sync(&adapter->sfp_timer);
cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->sfp_task);
if (adapter->hw.phy.multispeed_fiber) {
struct ixgbe_hw *hw = &adapter->hw;
/*
* Restart clause 37 autoneg, disable and re-enable
* the tx laser, to clear & alert the link partner
* that it needs to restart autotry
*/
hw->mac.autotry_restart = true;
hw->mac.ops.flap_tx_laser(hw);
}
cancel_work_sync(&adapter->multispeed_fiber_task);
cancel_work_sync(&adapter->sfp_config_module_task);
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE ||
......
......@@ -2398,6 +2398,8 @@ struct ixgbe_mac_operations {
s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
/* Link */
void (*disable_tx_laser)(struct ixgbe_hw *);
void (*enable_tx_laser)(struct ixgbe_hw *);
void (*flap_tx_laser)(struct ixgbe_hw *);
s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool);
s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool);
......
......@@ -1804,23 +1804,30 @@ static void media_check(u_long arg)
SMC_SELECT_BANK(1);
media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1;
SMC_SELECT_BANK(saved_bank);
spin_unlock_irqrestore(&smc->lock, flags);
/* Check for pending interrupt with watchdog flag set: with
this, we can limp along even if the interrupt is blocked */
if (smc->watchdog++ && ((i>>8) & i)) {
if (!smc->fast_poll)
printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
local_irq_save(flags);
smc_interrupt(dev->irq, dev);
local_irq_restore(flags);
smc->fast_poll = HZ;
}
if (smc->fast_poll) {
smc->fast_poll--;
smc->media.expires = jiffies + HZ/100;
add_timer(&smc->media);
SMC_SELECT_BANK(saved_bank);
spin_unlock_irqrestore(&smc->lock, flags);
return;
}
spin_lock_irqsave(&smc->lock, flags);
saved_bank = inw(ioaddr + BANK_SELECT);
if (smc->cfg & CFG_MII_SELECT) {
if (smc->mii_if.phy_id < 0)
goto reschedule;
......@@ -1978,15 +1985,16 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
unsigned int ioaddr = dev->base_addr;
u16 saved_bank = inw(ioaddr + BANK_SELECT);
int ret;
unsigned long flags;
spin_lock_irq(&smc->lock);
spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3);
if (smc->cfg & CFG_MII_SELECT)
ret = mii_ethtool_gset(&smc->mii_if, ecmd);
else
ret = smc_netdev_get_ecmd(dev, ecmd);
SMC_SELECT_BANK(saved_bank);
spin_unlock_irq(&smc->lock);
spin_unlock_irqrestore(&smc->lock, flags);
return ret;
}
......@@ -1996,15 +2004,16 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
unsigned int ioaddr = dev->base_addr;
u16 saved_bank = inw(ioaddr + BANK_SELECT);
int ret;
unsigned long flags;
spin_lock_irq(&smc->lock);
spin_lock_irqsave(&smc->lock, flags);
SMC_SELECT_BANK(3);
if (smc->cfg & CFG_MII_SELECT)
ret = mii_ethtool_sset(&smc->mii_if, ecmd);
else
ret = smc_netdev_set_ecmd(dev, ecmd);
SMC_SELECT_BANK(saved_bank);
spin_unlock_irq(&smc->lock);
spin_unlock_irqrestore(&smc->lock, flags);
return ret;
}
......@@ -2014,12 +2023,13 @@ static u32 smc_get_link(struct net_device *dev)
unsigned int ioaddr = dev->base_addr;