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: (39 commits)
  Revert "p54: Use SKB list handling helpers instead of by-hand code."
  sctp: fix warning at inet_sock_destruct() while release sctp socket
  tun/tap: Fix crashes if open() /dev/net/tun and then poll() it.
  dsa: fix 88e6xxx statistics counter snapshotting
  forcedeth: Fix NAPI race.
  drivers/net/smsc911x.c: Fix resource size off by 1 error
  pcnet_cs: add new id
  bnx2x: Fix the maximal values of coalescing timeouts.
  bnx2x: Disable HC coalescing when setting timeout to zero.
  tun: Fix device unregister race
  be2net: fix spurious interrupt handling in intx mode
  e1000e: disable K1 at 1000Mbps for 82577/82578
  e1000e: delay second read of PHY_STATUS register on failure of first read
  e1000e: prevent NVM corruption on sectors larger than 4K
  e1000e: do not write SmartSpeed register bits on parts without support
  e1000e: delay after LCD reset and proper checks for PHY configuration done
  e1000e: PHY loopback broken on 82578
  ixgbe: Not allow 8259x unsupported wol options change from ethtool
  ixgbe: fix inconsistent SFP/SFP+ failure results.
  ixgbe: fix regression on some 82598 adapters
  ...
This commit is contained in:
Linus Torvalds 2009-07-06 16:46:57 -07:00
commit eeaecb8619
35 changed files with 659 additions and 260 deletions

View File

@ -294,32 +294,33 @@ struct reply_t gigaset_tab_cid[] =
{RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}},
{RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}},
{RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}},
{RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"},
{RSP_OK, 607,607, -1, 608,-1}, {RSP_OK, 607,607, -1, 608,-1},
//{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 608, 0, {ACT_ERROR}},//DELETE
{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}},
{RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}},
{RSP_ZVLS, 608,608, 17, -1,-1, {ACT_DEBUG}},
{RSP_ZCTP, 609,609, -1, -1,-1, {ACT_DEBUG}},
{RSP_ZCPN, 609,609, -1, -1,-1, {ACT_DEBUG}},
{RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}},
{EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}},
/* dialing */ /* optional dialing responses */
{RSP_ZCTP, 650,650, -1, -1,-1, {ACT_DEBUG}}, {EV_BC_OPEN, 650,650, -1, 651,-1},
{RSP_ZCPN, 650,650, -1, -1,-1, {ACT_DEBUG}}, {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}},
{RSP_ZSAU, 650,650,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* some devices don't send this */ {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}},
{RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}},
{RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}},
/* connection established */ /* connect */
{RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}},
{RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, //FIXME -> DLE1 {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT,
ACT_NOTIFY_BC_UP}},
{EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, //FIXME new constate + timeout {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}},
{RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT,
ACT_NOTIFY_BC_UP}},
{EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}},
/* remote hangup */ /* remote hangup */
{RSP_ZSAU, 650,650,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}},
{RSP_ZSAU, 750,750,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
{RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
/* hangup */ /* hangup */
@ -358,7 +359,8 @@ struct reply_t gigaset_tab_cid[] =
{RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}},
{RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}},
{EV_TIMEOUT, 750,750, -1, 0, 0, {ACT_CONNTIMEOUT}}, {EV_BC_OPEN, 750,750, -1, 751,-1},
{EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}},
/* B channel closed (general case) */ /* B channel closed (general case) */
{EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
@ -876,12 +878,6 @@ static void bchannel_down(struct bc_state *bcs)
static void bchannel_up(struct bc_state *bcs) static void bchannel_up(struct bc_state *bcs)
{ {
if (!(bcs->chstate & CHS_D_UP)) {
dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__);
bcs->chstate |= CHS_D_UP;
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
}
if (bcs->chstate & CHS_B_UP) { if (bcs->chstate & CHS_B_UP) {
dev_notice(bcs->cs->dev, "%s: B channel already up\n", dev_notice(bcs->cs->dev, "%s: B channel already up\n",
__func__); __func__);

View File

@ -174,12 +174,6 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
pr_err("invalid size %d\n", size); pr_err("invalid size %d\n", size);
return -EINVAL; return -EINVAL;
} }
src = iwb->read;
if (unlikely(limit >= BAS_OUTBUFSIZE + BAS_OUTBUFPAD ||
(read < src && limit >= src))) {
pr_err("isoc write buffer frame reservation violated\n");
return -EFAULT;
}
#endif #endif
if (read < write) { if (read < write) {

View File

@ -55,6 +55,10 @@
#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ #define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */
#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 #define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26
/********* ISR0 Register offset **********/
#define CEV_ISR0_OFFSET 0xC18
#define CEV_ISR_SIZE 4
/********* Event Q door bell *************/ /********* Event Q door bell *************/
#define DB_EQ_OFFSET DB_CQ_OFFSET #define DB_EQ_OFFSET DB_CQ_OFFSET
#define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ #define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */

View File

@ -1274,15 +1274,17 @@ static irqreturn_t be_intx(int irq, void *dev)
{ {
struct be_adapter *adapter = dev; struct be_adapter *adapter = dev;
struct be_ctrl_info *ctrl = &adapter->ctrl; struct be_ctrl_info *ctrl = &adapter->ctrl;
int rx, tx; int isr;
tx = event_handle(ctrl, &adapter->tx_eq); isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
rx = event_handle(ctrl, &adapter->rx_eq); ctrl->pci_func * CEV_ISR_SIZE);
if (!isr)
return IRQ_NONE;
if (rx || tx) event_handle(ctrl, &adapter->tx_eq);
return IRQ_HANDLED; event_handle(ctrl, &adapter->rx_eq);
else
return IRQ_NONE; return IRQ_HANDLED;
} }
static irqreturn_t be_msix_rx(int irq, void *dev) static irqreturn_t be_msix_rx(int irq, void *dev)

View File

@ -902,6 +902,8 @@ struct bnx2x {
u16 rx_quick_cons_trip; u16 rx_quick_cons_trip;
u16 rx_ticks_int; u16 rx_ticks_int;
u16 rx_ticks; u16 rx_ticks;
/* Maximal coalescing timeout in us */
#define BNX2X_MAX_COALESCE_TOUT (0xf0*12)
u32 lin_cnt; u32 lin_cnt;

View File

@ -4434,7 +4434,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp)
REG_WR16(bp, BAR_USTRORM_INTMEM + REG_WR16(bp, BAR_USTRORM_INTMEM +
USTORM_SB_HC_DISABLE_OFFSET(port, sb_id, USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
U_SB_ETH_RX_CQ_INDEX), U_SB_ETH_RX_CQ_INDEX),
bp->rx_ticks ? 0 : 1); (bp->rx_ticks/12) ? 0 : 1);
/* HC_INDEX_C_ETH_TX_CQ_CONS */ /* HC_INDEX_C_ETH_TX_CQ_CONS */
REG_WR8(bp, BAR_CSTRORM_INTMEM + REG_WR8(bp, BAR_CSTRORM_INTMEM +
@ -4444,7 +4444,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp)
REG_WR16(bp, BAR_CSTRORM_INTMEM + REG_WR16(bp, BAR_CSTRORM_INTMEM +
CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id, CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
C_SB_ETH_TX_CQ_INDEX), C_SB_ETH_TX_CQ_INDEX),
bp->tx_ticks ? 0 : 1); (bp->tx_ticks/12) ? 0 : 1);
} }
} }
@ -9069,12 +9069,12 @@ static int bnx2x_set_coalesce(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev); struct bnx2x *bp = netdev_priv(dev);
bp->rx_ticks = (u16) coal->rx_coalesce_usecs; bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
if (bp->rx_ticks > 3000) if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT)
bp->rx_ticks = 3000; bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT;
bp->tx_ticks = (u16) coal->tx_coalesce_usecs; bp->tx_ticks = (u16) coal->tx_coalesce_usecs;
if (bp->tx_ticks > 0x3000) if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT)
bp->tx_ticks = 0x3000; bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT;
if (netif_running(dev)) if (netif_running(dev))
bnx2x_update_coalesce(bp); bnx2x_update_coalesce(bp);

View File

@ -238,6 +238,7 @@
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */
#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */
#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
/* Constants used to interpret the masked PCI-X bus speed. */ /* Constants used to interpret the masked PCI-X bus speed. */
@ -575,6 +576,8 @@
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
#define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */
/* NVM Control */ /* NVM Control */
#define E1000_EECD_SK 0x00000001 /* NVM Clock */ #define E1000_EECD_SK 0x00000001 /* NVM Clock */
#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */

View File

@ -215,6 +215,7 @@ enum e1e_registers {
E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_SWSM = 0x05B50, /* SW Semaphore */
E1000_FWSM = 0x05B54, /* FW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */
E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */
E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */
E1000_HICR = 0x08F00, /* Host Interface Control */ E1000_HICR = 0x08F00, /* Host Interface Control */
}; };
@ -302,6 +303,9 @@ enum e1e_registers {
#define E1000_KMRNCTRLSTA_REN 0x00200000 #define E1000_KMRNCTRLSTA_REN 0x00200000
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E
#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */

View File

@ -338,6 +338,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
{ {
struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_nvm_info *nvm = &hw->nvm;
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
union ich8_hws_flash_status hsfsts;
u32 gfpreg; u32 gfpreg;
u32 sector_base_addr; u32 sector_base_addr;
u32 sector_end_addr; u32 sector_end_addr;
@ -374,6 +375,20 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
/* Adjust to word count */ /* Adjust to word count */
nvm->flash_bank_size /= sizeof(u16); nvm->flash_bank_size /= sizeof(u16);
/*
* Make sure the flash bank size does not overwrite the 4k
* sector ranges. We may have 64k allotted to us but we only care
* about the first 2 4k sectors. Therefore, if we have anything less
* than 64k set in the HSFSTS register, we will reduce the bank size
* down to 4k and let the rest remain unused. If berasesz == 3, then
* we are working in 64k mode. Otherwise we are not.
*/
if (nvm->flash_bank_size > E1000_ICH8_SHADOW_RAM_WORDS) {
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
if (hsfsts.hsf_status.berasesz != 3)
nvm->flash_bank_size = E1000_ICH8_SHADOW_RAM_WORDS;
}
nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS;
/* Clear shadow ram */ /* Clear shadow ram */
@ -446,6 +461,95 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
return 0; return 0;
} }
/**
* e1000_check_for_copper_link_ich8lan - Check for link (Copper)
* @hw: pointer to the HW structure
*
* Checks to see of the link status of the hardware has changed. If a
* change in link status has been detected, then we read the PHY registers
* to get the current speed/duplex if link exists.
**/
static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
s32 ret_val;
bool link;
/*
* We only want to go out to the PHY registers to see if Auto-Neg
* has completed and/or if our link status has changed. The
* get_link_status flag is set upon receiving a Link Status
* Change or Rx Sequence Error interrupt.
*/
if (!mac->get_link_status) {
ret_val = 0;
goto out;
}
if (hw->mac.type == e1000_pchlan) {
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_K1_CONFIG,
E1000_KMRNCTRLSTA_K1_ENABLE);
if (ret_val)
goto out;
}
/*
* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
* of the PHY.
*/
ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
if (ret_val)
goto out;
if (!link)
goto out; /* No link detected */
mac->get_link_status = false;
if (hw->phy.type == e1000_phy_82578) {
ret_val = e1000_link_stall_workaround_hv(hw);
if (ret_val)
goto out;
}
/*
* Check if there was DownShift, must be checked
* immediately after link-up
*/
e1000e_check_downshift(hw);
/*
* If we are forcing speed/duplex, then we simply return since
* we have already determined whether we have link or not.
*/
if (!mac->autoneg) {
ret_val = -E1000_ERR_CONFIG;
goto out;
}
/*
* Auto-Neg is enabled. Auto Speed Detection takes care
* of MAC speed/duplex configuration. So we only need to
* configure Collision Distance in the MAC.
*/
e1000e_config_collision_dist(hw);
/*
* Configure Flow Control now that Auto-Neg has completed.
* First, we need to restore the desired flow control
* settings because we may have had to re-autoneg with a
* different link partner.
*/
ret_val = e1000e_config_fc_after_link_up(hw);
if (ret_val)
hw_dbg(hw, "Error configuring flow control\n");
out:
return ret_val;
}
static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
@ -693,6 +797,38 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
return ret_val; return ret_val;
} }
/**
* e1000_lan_init_done_ich8lan - Check for PHY config completion
* @hw: pointer to the HW structure
*
* Check the appropriate indication the MAC has finished configuring the
* PHY after a software reset.
**/
static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
{
u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT;
/* Wait for basic configuration completes before proceeding */
do {
data = er32(STATUS);
data &= E1000_STATUS_LAN_INIT_DONE;
udelay(100);
} while ((!data) && --loop);
/*
* If basic configuration is incomplete before the above loop
* count reaches 0, loading the configuration from NVM will
* leave the PHY in a bad state possibly resulting in no link.
*/
if (loop == 0)
hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n");
/* Clear the Init Done bit for the next init event */
data = er32(STATUS);
data &= ~E1000_STATUS_LAN_INIT_DONE;
ew32(STATUS, data);
}
/** /**
* e1000_phy_hw_reset_ich8lan - Performs a PHY reset * e1000_phy_hw_reset_ich8lan - Performs a PHY reset
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
@ -707,13 +843,15 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
u32 i; u32 i;
u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;
s32 ret_val; s32 ret_val;
u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT;
u16 word_addr, reg_data, reg_addr, phy_page = 0; u16 word_addr, reg_data, reg_addr, phy_page = 0;
ret_val = e1000e_phy_hw_reset_generic(hw); ret_val = e1000e_phy_hw_reset_generic(hw);
if (ret_val) if (ret_val)
return ret_val; return ret_val;
/* Allow time for h/w to get to a quiescent state after reset */
mdelay(10);
if (hw->mac.type == e1000_pchlan) { if (hw->mac.type == e1000_pchlan) {
ret_val = e1000_hv_phy_workarounds_ich8lan(hw); ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
if (ret_val) if (ret_val)
@ -741,26 +879,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
if (!(data & sw_cfg_mask)) if (!(data & sw_cfg_mask))
return 0; return 0;
/* Wait for basic configuration completes before proceeding*/ /* Wait for basic configuration completes before proceeding */
do { e1000_lan_init_done_ich8lan(hw);
data = er32(STATUS);
data &= E1000_STATUS_LAN_INIT_DONE;
udelay(100);
} while ((!data) && --loop);
/*
* If basic configuration is incomplete before the above loop
* count reaches 0, loading the configuration from NVM will
* leave the PHY in a bad state possibly resulting in no link.
*/
if (loop == 0) {
hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n");
}
/* Clear the Init Done bit for the next init event */
data = er32(STATUS);
data &= ~E1000_STATUS_LAN_INIT_DONE;
ew32(STATUS, data);
/* /*
* Make sure HW does not configure LCD from PHY * Make sure HW does not configure LCD from PHY
@ -961,12 +1081,14 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
ew32(PHY_CTRL, phy_ctrl); ew32(PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
return 0;
/* /*
* Call gig speed drop workaround on LPLU before accessing * Call gig speed drop workaround on LPLU before accessing
* any PHY registers * any PHY registers
*/ */
if ((hw->mac.type == e1000_ich8lan) && if (hw->mac.type == e1000_ich8lan)
(hw->phy.type == e1000_phy_igp_3))
e1000e_gig_downshift_workaround_ich8lan(hw); e1000e_gig_downshift_workaround_ich8lan(hw);
/* When LPLU is enabled, we should disable SmartSpeed */ /* When LPLU is enabled, we should disable SmartSpeed */
@ -979,6 +1101,9 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
ew32(PHY_CTRL, phy_ctrl); ew32(PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
return 0;
/* /*
* LPLU and SmartSpeed are mutually exclusive. LPLU is used * LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most * during Dx states where the power conservation is most
@ -1038,6 +1163,10 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
if (!active) { if (!active) {
phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
ew32(PHY_CTRL, phy_ctrl); ew32(PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
return 0;
/* /*
* LPLU and SmartSpeed are mutually exclusive. LPLU is used * LPLU and SmartSpeed are mutually exclusive. LPLU is used
* during Dx states where the power conservation is most * during Dx states where the power conservation is most
@ -1073,12 +1202,14 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
ew32(PHY_CTRL, phy_ctrl); ew32(PHY_CTRL, phy_ctrl);
if (phy->type != e1000_phy_igp_3)
return 0;
/* /*
* Call gig speed drop workaround on LPLU before accessing * Call gig speed drop workaround on LPLU before accessing
* any PHY registers * any PHY registers
*/ */
if ((hw->mac.type == e1000_ich8lan) && if (hw->mac.type == e1000_ich8lan)
(hw->phy.type == e1000_phy_igp_3))
e1000e_gig_downshift_workaround_ich8lan(hw); e1000e_gig_downshift_workaround_ich8lan(hw);
/* When LPLU is enabled, we should disable SmartSpeed */ /* When LPLU is enabled, we should disable SmartSpeed */
@ -1905,7 +2036,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
break; break;
case 1: case 1:
sector_size = ICH_FLASH_SEG_SIZE_4K; sector_size = ICH_FLASH_SEG_SIZE_4K;
iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K; iteration = 1;
break; break;
case 2: case 2:
if (hw->mac.type == e1000_ich9lan) { if (hw->mac.type == e1000_ich9lan) {
@ -1917,7 +2048,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
break; break;
case 3: case 3:
sector_size = ICH_FLASH_SEG_SIZE_64K; sector_size = ICH_FLASH_SEG_SIZE_64K;
iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K; iteration = 1;
break; break;
default: default:
return -E1000_ERR_NVM; return -E1000_ERR_NVM;
@ -2143,6 +2274,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ctrl = er32(CTRL); ctrl = er32(CTRL);
if (!e1000_check_reset_block(hw)) { if (!e1000_check_reset_block(hw)) {
/* Clear PHY Reset Asserted bit */
if (hw->mac.type >= e1000_pchlan) {
u32 status = er32(STATUS);
ew32(STATUS, status & ~E1000_STATUS_PHYRA);
}
/* /*
* PHY HW reset requires MAC CORE reset at the same * PHY HW reset requires MAC CORE reset at the same
* time to make sure the interface between MAC and the * time to make sure the interface between MAC and the
@ -2156,22 +2293,33 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ew32(CTRL, (ctrl | E1000_CTRL_RST)); ew32(CTRL, (ctrl | E1000_CTRL_RST));
msleep(20); msleep(20);
if (!ret_val) { if (!ret_val)
/* release the swflag because it is not reset by
* hardware reset
*/
e1000_release_swflag_ich8lan(hw); e1000_release_swflag_ich8lan(hw);
if (ctrl & E1000_CTRL_PHY_RST)
ret_val = hw->phy.ops.get_cfg_done(hw);
if (hw->mac.type >= e1000_ich10lan) {
e1000_lan_init_done_ich8lan(hw);
} else {
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val) {
/*
* When auto config read does not complete, do not
* return with an error. This can happen in situations
* where there is no eeprom and prevents getting link.
*/
hw_dbg(hw, "Auto Read Done did not complete\n");
}
} }
ret_val = e1000e_get_auto_rd_done(hw); /*
if (ret_val) { * For PCH, this write will make sure that any noise
/* * will be detected as a CRC error and be dropped rather than show up
* When auto config read does not complete, do not * as a bad packet to the DMA engine.
* return with an error. This can happen in situations */
* where there is no eeprom and prevents getting link. if (hw->mac.type == e1000_pchlan)
*/ ew32(CRC_OFFSET, 0x65656565);
hw_dbg(hw, "Auto Read Done did not complete\n");
}
ew32(IMC, 0xffffffff); ew32(IMC, 0xffffffff);
icr = er32(ICR); icr = er32(ICR);
@ -2222,6 +2370,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
for (i = 0; i < mac->mta_reg_count; i++) for (i = 0; i < mac->mta_reg_count; i++)
E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
/*
* The 82578 Rx buffer will stall if wakeup is enabled in host and
* the ME. Reading the BM_WUC register will clear the host wakeup bit.
* Reset the phy after disabling host wakeup to reset the Rx buffer.
*/
if (hw->phy.type == e1000_phy_82578) {
hw->phy.ops.read_phy_reg(hw, BM_WUC, &i);
ret_val = e1000_phy_hw_reset_ich8lan(hw);
if (ret_val)
return ret_val;
}
/* Setup link and flow control */ /* Setup link and flow control */
ret_val = e1000_setup_link_ich8lan(hw); ret_val = e1000_setup_link_ich8lan(hw);
@ -2253,16 +2413,6 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
ctrl_ext |= E1000_CTRL_EXT_RO_DIS; ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
ew32(CTRL_EXT, ctrl_ext); ew32(CTRL_EXT, ctrl_ext);
/*
* The 82578 Rx buffer will stall if wakeup is enabled in host and
* the ME. Reading the BM_WUC register will clear the host wakeup bit.
* Reset the phy after disabling host wakeup to reset the Rx buffer.
*/
if (hw->phy.type == e1000_phy_82578) {
e1e_rphy(hw, BM_WUC, &i);
e1000e_phy_hw_reset_generic(hw);
}
/* /*
* Clear all of the statistics registers (clear on read). It is * Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link * important that we do this after we have tried to establish link
@ -2485,6 +2635,14 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
if (ret_val) if (ret_val)
return ret_val; return ret_val;
if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_K1_CONFIG,
E1000_KMRNCTRLSTA_K1_DISABLE);
if (ret_val)
return ret_val;
}
if ((hw->mac.type == e1000_ich8lan) && if ((hw->mac.type == e1000_ich8lan) &&
(hw->phy.type == e1000_phy_igp_3) && (hw->phy.type == e1000_phy_igp_3) &&
(*speed == SPEED_1000)) { (*speed == SPEED_1000)) {
@ -2850,6 +3008,16 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
{ {
u32 bank = 0; u32 bank = 0;
if (hw->mac.type >= e1000_pchlan) {
u32 status = er32(STATUS);
if (status & E1000_STATUS_PHYRA)
ew32(STATUS, status & ~E1000_STATUS_PHYRA);
else
hw_dbg(hw,
"PHY Reset Asserted not set - needs delay\n");
}
e1000e_get_cfg_done(hw); e1000e_get_cfg_done(hw);
/* If EEPROM is not marked present, init the IGP 3 PHY manually */ /* If EEPROM is not marked present, init the IGP 3 PHY manually */
@ -2921,7 +3089,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
static struct e1000_mac_operations ich8_mac_ops = { static struct e1000_mac_operations ich8_mac_ops = {
.id_led_init = e1000e_id_led_init, .id_led_init = e1000e_id_led_init,
.check_mng_mode = e1000_check_mng_mode_ich8lan, .check_mng_mode = e1000_check_mng_mode_ich8lan,
.check_for_link = e1000e_check_for_copper_link, .check_for_link = e1000_check_for_copper_link_ich8lan,
/* cleanup_led dependent on mac type */ /* cleanup_led dependent on mac type */
.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan,
.get_bus_info = e1000_get_bus_info_ich8lan, .get_bus_info = e1000_get_bus_info_ich8lan,

View File

@ -378,12 +378,6 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
mac->get_link_status = 0; mac->get_link_status = 0;
if (hw->phy.type == e1000_phy_82578) {
ret_val = e1000_link_stall_workaround_hv(hw);
if (ret_val)
return ret_val;
}
/* /*
* Check if there was DownShift, must be checked * Check if there was DownShift, must be checked
* immediately after link-up * immediately after link-up

View File

@ -1531,7 +1531,12 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
*/ */
ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
if (ret_val) if (ret_val)
break; /*
* If the first read fails, another entity may have
* ownership of the resources, wait and try again to
* see if they have relinquished the resources yet.
*/
udelay(usec_interval);
ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status); ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
if (ret_val) if (ret_val)
break; break;
@ -2737,6 +2742,11 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
if (hw->phy.type != e1000_phy_82578) if (hw->phy.type != e1000_phy_82578)
goto out; goto out;
/* Do not apply workaround if in PHY loopback bit 14 set */
hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &data);
if (data & PHY_CONTROL_LB)
goto out;
/* check if link is up and at 1Gbps */ /* check if link is up and at 1Gbps */
ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data); ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data);
if (ret_val) if (ret_val)

View File

@ -3514,11 +3514,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
nv_msi_workaround(np); nv_msi_workaround(np);
#ifdef CONFIG_FORCEDETH_NAPI #ifdef CONFIG_FORCEDETH_NAPI
napi_schedule(&np->napi); if (napi_schedule_prep(&np->napi)) {
/*
/* Disable furthur irq's * Disable further irq's (msix not enabled with napi)
(msix not enabled with napi) */ */
writel(0, base + NvRegIrqMask); writel(0, base + NvRegIrqMask);
__napi_schedule(&np->napi);
}
#else #else
do do
@ -3615,12 +3617,13 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
nv_msi_workaround(np); nv_msi_workaround(np);
#ifdef CONFIG_FORCEDETH_NAPI #ifdef CONFIG_FORCEDETH_NAPI
napi_schedule(&np->napi); if (napi_schedule_prep(&np->napi)) {
/*
/* Disable furthur irq's * Disable further irq's (msix not enabled with napi)
(msix not enabled with napi) */ */
writel(0, base + NvRegIrqMask); writel(0, base + NvRegIrqMask);
__napi_schedule(&np->napi);
}
#else #else
do do
{ {

View File

@ -1830,7 +1830,6 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter,
break; break;
default: default:
wol->supported = 0; wol->supported = 0;
retval = 0;
} }
return retval; return retval;

View File

@ -2697,19 +2697,23 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
/* /*
* For hot-pluggable SFP+ devices, a new SFP+ module may have * For hot-pluggable SFP+ devices, a new SFP+ module may have
* arrived before interrupts were enabled. We need to kick off * arrived before interrupts were enabled but after probe. Such
* the SFP+ module setup first, then try to bring up link. * 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 * If we're not hot-pluggable SFP+, we just need to configure link
* and bring it up. * and bring it up.
*/ */
err = hw->phy.ops.identify(hw); if (hw->phy.type == ixgbe_phy_unknown) {
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { err = hw->phy.ops.identify(hw);
dev_err(&adapter->pdev->dev, "failed to initialize because " if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
"an unsupported SFP+ module type was detected.\n" /*
"Reload the driver after installing a supported " * Take the device down and schedule the sfp tasklet
"module.\n"); * which will unregister_netdev and log it.
ixgbe_down(adapter); */
return err; ixgbe_down(adapter);
schedule_work(&adapter->sfp_config_module_task);
return err;
}
} }
if (ixgbe_is_sfp(hw)) { if (ixgbe_is_sfp(hw)) {
@ -3724,7 +3728,7 @@ static void ixgbe_sfp_task(struct work_struct *work)
if ((hw->phy.type == ixgbe_phy_nl) && if ((hw->phy.type == ixgbe_phy_nl) &&
(hw->phy.sfp_type == ixgbe_sfp_type_not_present)) { (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
s32 ret = hw->phy.ops.identify_sfp(hw); s32 ret = hw->phy.ops.identify_sfp(hw);
if (ret) if (ret == IXGBE_ERR_SFP_NOT_PRESENT)
goto reschedule; goto reschedule;
ret = hw->phy.ops.reset(hw); ret = hw->phy.ops.reset(hw);
if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) { if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
@ -4534,13 +4538,17 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work)
u32 err; u32 err;
adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK; adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK;
/* Time for electrical oscillations to settle down */
msleep(100);
err = hw->phy.ops.identify_sfp(hw); err = hw->phy.ops.identify_sfp(hw);
if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
dev_err(&adapter->pdev->dev, "failed to initialize because " dev_err(&adapter->pdev->dev, "failed to initialize because "
"an unsupported SFP+ module type was detected.\n" "an unsupported SFP+ module type was detected.\n"
"Reload the driver after installing a supported " "Reload the driver after installing a supported "
"module.\n"); "module.\n");
ixgbe_down(adapter); unregister_netdev(adapter->netdev);
return; return;
} }
hw->mac.ops.setup_sfp(hw); hw->mac.ops.setup_sfp(hw);

View File

@ -60,6 +60,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
if (hw->phy.type == ixgbe_phy_unknown) { if (hw->phy.type == ixgbe_phy_unknown) {
for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
hw->phy.mdio.prtad = phy_addr;
if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) { if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) {
ixgbe_get_phy_id(hw); ixgbe_get_phy_id(hw);
hw->phy.type = hw->phy.type =
@ -68,6 +69,8 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
break; break;
} }
} }
/* clear value if nothing found */
hw->phy.mdio.prtad = 0;
} else { } else {
status = 0; status = 0;
} }

View File

@ -60,7 +60,18 @@
#define _NETXEN_NIC_LINUX_SUBVERSION 30 #define _NETXEN_NIC_LINUX_SUBVERSION 30
#define NETXEN_NIC_LINUX_VERSIONID "4.0.30" #define NETXEN_NIC_LINUX_VERSIONID "4.0.30"
#define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c))
#define _major(v) (((v) >> 24) & 0xff)
#define _minor(v) (((v) >> 16) & 0xff)
#define _build(v) ((v) & 0xffff)
/* version in image has weird encoding:
* 7:0 - major
* 15:8 - minor
* 31:16 - build (little endian)
*/
#define NETXEN_DECODE_VERSION(v) \
NETXEN_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16))
#define NETXEN_NUM_FLASH_SECTORS (64) #define NETXEN_NUM_FLASH_SECTORS (64)
#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024) #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
@ -614,6 +625,7 @@ struct netxen_new_user_info {
#define NX_P2_MN_ROMIMAGE 0 #define NX_P2_MN_ROMIMAGE 0
#define NX_P3_CT_ROMIMAGE 1 #define NX_P3_CT_ROMIMAGE 1
#define NX_P3_MN_ROMIMAGE 2 #define NX_P3_MN_ROMIMAGE 2
#define NX_FLASH_ROMIMAGE 3
#define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */
@ -1243,7 +1255,7 @@ struct netxen_adapter {
u32 resv3; u32 resv3;
u8 has_link_events; u8 has_link_events;
u8 resv1; u8 fw_type;
u16 tx_context_id; u16 tx_context_id;
u16 mtu; u16 mtu;
u16 is_up; u16 is_up;
@ -1387,6 +1399,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter);
int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
int netxen_load_firmware(struct netxen_adapter *adapter); int netxen_load_firmware(struct netxen_adapter *adapter);
int netxen_need_fw_reset(struct netxen_adapter *adapter);
void netxen_request_firmware(struct netxen_adapter *adapter); void netxen_request_firmware(struct netxen_adapter *adapter);
void netxen_release_firmware(struct netxen_adapter *adapter); void netxen_release_firmware(struct netxen_adapter *adapter);
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);

View File

@ -853,6 +853,7 @@ enum {
#define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c))
#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14)
#define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0))
#define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200)

View File

@ -683,12 +683,85 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
return 0; return 0;
} }
int
netxen_need_fw_reset(struct netxen_adapter *adapter)
{
u32 count, old_count;
u32 val, version, major, minor, build;
int i, timeout;
u8 fw_type;
/* NX2031 firmware doesn't support heartbit */
if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
return 1;
/* last attempt had failed */
if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
return 1;
old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
for (i = 0; i < 10; i++) {
timeout = msleep_interruptible(200);
if (timeout) {
NXWR32(adapter, CRB_CMDPEG_STATE,
PHAN_INITIALIZE_FAILED);
return -EINTR;
}
count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
if (count != old_count)
break;
}
/* firmware is dead */
if (count == old_count)
return 1;
/* check if we have got newer or different file firmware */
if (adapter->fw) {
const struct firmware *fw = adapter->fw;
val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
version = NETXEN_DECODE_VERSION(val);
major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
if (version > NETXEN_VERSION_CODE(major, minor, build))
return 1;
if (version == NETXEN_VERSION_CODE(major, minor, build)) {
val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL);
fw_type = (val & 0x4) ?
NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE;
if (adapter->fw_type != fw_type)
return 1;
}
}
return 0;
}
static char *fw_name[] = {
"nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash",
};
int int
netxen_load_firmware(struct netxen_adapter *adapter) netxen_load_firmware(struct netxen_adapter *adapter)
{ {
u64 *ptr64; u64 *ptr64;
u32 i, flashaddr, size; u32 i, flashaddr, size;
const struct firmware *fw = adapter->fw; const struct firmware *fw = adapter->fw;
struct pci_dev *pdev = adapter->pdev;
dev_info(&pdev->dev, "loading firmware from %s\n",
fw_name[adapter->fw_type]);
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);
@ -756,7 +829,7 @@ static int
netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
{ {
__le32 val; __le32 val;
u32 major, minor, build, ver, min_ver, bios; u32 ver, min_ver, bios;
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
const struct firmware *fw = adapter->fw; const struct firmware *fw = adapter->fw;
@ -768,21 +841,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
return -EINVAL; return -EINVAL;
val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
major = (__force u32)val & 0xff;
minor = ((__force u32)val >> 8) & 0xff;
build = (__force u32)val >> 16;
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
min_ver = NETXEN_VERSION_CODE(4, 0, 216); min_ver = NETXEN_VERSION_CODE(4, 0, 216);
else else
min_ver = NETXEN_VERSION_CODE(3, 4, 216); min_ver = NETXEN_VERSION_CODE(3, 4, 216);
ver = NETXEN_VERSION_CODE(major, minor, build); ver = NETXEN_DECODE_VERSION(val);
if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"%s: firmware version %d.%d.%d unsupported\n", "%s: firmware version %d.%d.%d unsupported\n",
fwname, major, minor, build); fwname, _major(ver), _minor(ver), _build(ver));
return -EINVAL; return -EINVAL;
} }
@ -798,22 +868,21 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
if (netxen_rom_fast_read(adapter, if (netxen_rom_fast_read(adapter,
NX_FW_VERSION_OFFSET, (int *)&val)) NX_FW_VERSION_OFFSET, (int *)&val))
return -EIO; return -EIO;
major = (__force u32)val & 0xff; val = NETXEN_DECODE_VERSION(val);
minor = ((__force u32)val >> 8) & 0xff; if (val > ver) {
build = (__force u32)val >> 16; dev_info(&pdev->dev, "%s: firmware is older than flash\n",
if (NETXEN_VERSION_CODE(major, minor, build) > ver) fwname);
return -EINVAL; return -EINVAL;
}
NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
return 0; return 0;
} }
static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" };
void netxen_request_firmware(struct netxen_adapter *adapter) void netxen_request_firmware(struct netxen_adapter *adapter)
{ {
u32 capability, flashed_ver; u32 capability, flashed_ver;
int fw_type; u8 fw_type;
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
int rc = 0; int rc = 0;
@ -830,6 +899,8 @@ request_mn:
netxen_rom_fast_read(adapter, netxen_rom_fast_read(adapter,
NX_FW_VERSION_OFFSET, (int *)&flashed_ver); NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
if (capability & NX_PEG_TUNE_MN_PRESENT) { if (capability & NX_PEG_TUNE_MN_PRESENT) {
@ -838,6 +909,10 @@ request_mn:
} }
} }
fw_type = NX_FLASH_ROMIMAGE;
adapter->fw = NULL;
goto done;
request_fw: request_fw:
rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
if (rc != 0) { if (rc != 0) {
@ -846,6 +921,7 @@ request_fw:
goto request_mn; goto request_mn;
} }
fw_type = NX_FLASH_ROMIMAGE;
adapter->fw = NULL; adapter->fw = NULL;
goto done; goto done;
} }
@ -859,16 +935,13 @@ request_fw:
goto request_mn; goto request_mn;
} }
fw_type = NX_FLASH_ROMIMAGE;
adapter->fw = NULL; adapter->fw = NULL;
goto done; goto done;
} }
done: done:
if (adapter->fw) adapter->fw_type = fw_type;
dev_info(&pdev->dev, "loading firmware from file %s\n",
fw_name[fw_type]);
else
dev_info(&pdev->dev, "loading firmware from flash\n");
} }

View File

@ -718,6 +718,10 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
if (request_fw) if (request_fw)
netxen_request_firmware(adapter); netxen_request_firmware(adapter);
err = netxen_need_fw_reset(adapter);
if (err <= 0)
return err;
if (first_boot != 0x55555555) { if (first_boot != 0x55555555) {
NXWR32(adapter, CRB_CMDPEG_STATE, 0); NXWR32(adapter, CRB_CMDPEG_STATE, 0);
netxen_pinit_from_rom(adapter, 0); netxen_pinit_from_rom(adapter, 0);

View File

@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),

View File

@ -928,13 +928,32 @@ static void phy_state_machine(struct work_struct *work)
* Otherwise, it's 0, and we're * Otherwise, it's 0, and we're
* still waiting for AN */ * still waiting for AN */
if (err > 0) { if (err > 0) {
phydev->state = PHY_RUNNING; err = phy_read_status(phydev);
if (err)
break;
if (phydev->link) {
phydev->state = PHY_RUNNING;
netif_carrier_on(phydev->attached_dev);
} else
phydev->state = PHY_NOLINK;
phydev->adjust_link(phydev->attached_dev);
} else { } else {
phydev->state = PHY_AN; phydev->state = PHY_AN;
phydev->link_timeout = PHY_AN_TIMEOUT; phydev->link_timeout = PHY_AN_TIMEOUT;
} }
} else } else {
phydev->state = PHY_RUNNING; err = phy_read_status(phydev);
if (err)
break;
if (phydev->link) {
phydev->state = PHY_RUNNING;
netif_carrier_on(phydev->attached_dev);
} else
phydev->state = PHY_NOLINK;
phydev->adjust_link(phydev->attached_dev);
}
break; break;
} }

View File

@ -1607,6 +1607,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev);
int ql_cam_route_initialize(struct ql_adapter *qdev); int ql_cam_route_initialize(struct ql_adapter *qdev);
int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
int ql_mb_about_fw(struct ql_adapter *qdev); int ql_mb_about_fw(struct ql_adapter *qdev);
void ql_link_on(struct ql_adapter *qdev);
void ql_link_off(struct ql_adapter *qdev);
#if 1 #if 1
#define QL_ALL_DUMP #define QL_ALL_DUMP

View File

@ -59,7 +59,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
cqicb->pkt_delay = cqicb->pkt_delay =
cpu_to_le16(qdev->tx_max_coalesced_frames); cpu_to_le16(qdev->tx_max_coalesced_frames);
cqicb->flags = FLAGS_LI; cqicb->flags = FLAGS_LI;
status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb),
CFG_LCQ, rx_ring->cq_id); CFG_LCQ, rx_ring->cq_id);
if (status) { if (status) {
QPRINTK(qdev, IFUP, ERR, QPRINTK(qdev, IFUP, ERR,
@ -82,7 +82,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
cqicb->pkt_delay = cqicb->pkt_delay =
cpu_to_le16(qdev->rx_max_coalesced_frames); cpu_to_le16(qdev->rx_max_coalesced_frames);
cqicb->flags = FLAGS_LI; cqicb->flags = FLAGS_LI;
status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb),
CFG_LCQ, rx_ring->cq_id); CFG_LCQ, rx_ring->cq_id);
if (status) { if (status) {
QPRINTK(qdev, IFUP, ERR, QPRINTK(qdev, IFUP, ERR,

View File

@ -214,6 +214,10 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
return -ENOMEM; return -ENOMEM;
} }
status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
if (status)
return status;
status = ql_wait_cfg(qdev, bit); status = ql_wait_cfg(qdev, bit);
if (status) { if (status) {
QPRINTK(qdev, IFUP, ERR, QPRINTK(qdev, IFUP, ERR,
@ -221,12 +225,8 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
goto exit; goto exit;
} }
status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
if (status)
goto exit;
ql_write32(qdev, ICB_L, (u32) map); ql_write32(qdev, ICB_L, (u32) map);
ql_write32(qdev, ICB_H, (u32) (map >> 32)); ql_write32(qdev, ICB_H, (u32) (map >> 32));
ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */
mask = CFG_Q_MASK | (bit << 16); mask = CFG_Q_MASK | (bit << 16);
value = bit | (q_id << CFG_Q_SHIFT); value = bit | (q_id << CFG_Q_SHIFT);
@ -237,6 +237,7 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
*/ */
status = ql_wait_cfg(qdev, bit); status = ql_wait_cfg(qdev, bit);
exit: exit:
ql_sem_unlock(qdev, SEM_ICB_MASK); /* does flush too */
pci_unmap_single(qdev->pdev, map, size, direction); pci_unmap_single(qdev->pdev, map, size, direction);
return status; return status;
} }
@ -412,6 +413,57 @@ exit:
return status; return status;
} }
/* Set or clear MAC address in hardware. We sometimes
* have to clear it to prevent wrong frame routing
* especially in a bonding environment.
*/
static int ql_set_mac_addr(struct ql_adapter *qdev, int set)
{
int status;
char zero_mac_addr[ETH_ALEN];
char *addr;
if (set) {
addr = &qdev->ndev->dev_addr[0];
QPRINTK(qdev, IFUP, DEBUG,
"Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n",
addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5]);
} else {
memset(zero_mac_addr, 0, ETH_ALEN);
addr = &zero_mac_addr[0];
QPRINTK(qdev, IFUP, DEBUG,
"Clearing MAC address on %s\n",
qdev->ndev->name);
}
status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
if (status)
return status;
status = ql_set_mac_addr_reg(qdev, (u8 *) addr,
MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
if (status)
QPRINTK(qdev, IFUP, ERR, "Failed to init mac "
"address.\n");
return status;
}
void ql_link_on(struct ql_adapter *qdev)
{
QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n",
qdev->ndev->name);
netif_carrier_on(qdev->ndev);
ql_set_mac_addr(qdev, 1);
}
void ql_link_off(struct ql_adapter *qdev)
{
QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n",
qdev->ndev->name);
netif_carrier_off(qdev->ndev);
ql_set_mac_addr(qdev, 0);
}
/* Get a specific frame routing value from the CAM. /* Get a specific frame routing value from the CAM.
* Used for debug and reg dump. * Used for debug and reg dump.
*/ */
@ -1628,7 +1680,7 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev,
tx_ring = &qdev->tx_ring[mac_rsp->txq_idx]; tx_ring = &qdev->tx_ring[mac_rsp->txq_idx];
tx_ring_desc = &tx_ring->q[mac_rsp->tid]; tx_ring_desc = &tx_ring->q[mac_rsp->tid];
ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt); ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt);
qdev->stats.tx_bytes += tx_ring_desc->map_cnt; qdev->stats.tx_bytes += (tx_ring_desc->skb)->len;
qdev->stats.tx_packets++; qdev->stats.tx_packets++;
dev_kfree_skb(tx_ring_desc->skb); dev_kfree_skb(tx_ring_desc->skb);
tx_ring_desc->skb = NULL; tx_ring_desc->skb = NULL;
@ -1660,13 +1712,13 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev,
/* Fire up a handler to reset the MPI processor. */ /* Fire up a handler to reset the MPI processor. */
void ql_queue_fw_error(struct ql_adapter *qdev) void ql_queue_fw_error(struct ql_adapter *qdev)
{ {
netif_carrier_off(qdev->ndev); ql_link_off(qdev);
queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0);
} }
void ql_queue_asic_error(struct ql_adapter *qdev) void ql_queue_asic_error(struct ql_adapter *qdev)
{ {
netif_carrier_off(qdev->ndev); ql_link_off(qdev);
ql_disable_interrupts(qdev); ql_disable_interrupts(qdev);
/* Clear adapter up bit to signal the recovery /* Clear adapter up bit to signal the recovery
* process that it shouldn't kill the reset worker * process that it shouldn't kill the reset worker
@ -2104,7 +2156,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev)
} }
tx_ring_desc = &tx_ring->q[tx_ring->prod_idx]; tx_ring_desc = &tx_ring->q[tx_ring->prod_idx];
mac_iocb_ptr = tx_ring_desc->queue_entry; mac_iocb_ptr = tx_ring_desc->queue_entry;
memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr)); memset((void *)mac_iocb_ptr, 0, sizeof(*mac_iocb_ptr));
mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB; mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB;
mac_iocb_ptr->tid = tx_ring_desc->index; mac_iocb_ptr->tid = tx_ring_desc->index;
@ -2743,7 +2795,7 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
ql_init_tx_ring(qdev, tx_ring); ql_init_tx_ring(qdev, tx_ring);
err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ, err = ql_write_cfg(qdev, wqicb, sizeof(*wqicb), CFG_LRQ,
(u16) tx_ring->wq_id); (u16) tx_ring->wq_id);
if (err) { if (err) {
QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n");
@ -3008,7 +3060,7 @@ static int ql_start_rss(struct ql_adapter *qdev)
int i; int i;
u8 *hash_id = (u8 *) ricb->hash_cq_id; u8 *hash_id = (u8 *) ricb->hash_cq_id;
memset((void *)ricb, 0, sizeof(ricb)); memset((void *)ricb, 0, sizeof(*ricb));
ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K; ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K;
ricb->flags = ricb->flags =
@ -3030,7 +3082,7 @@ static int ql_start_rss(struct ql_adapter *qdev)
QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n");
status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0); status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0);
if (status) { if (status) {
QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n");
return status; return status;
@ -3039,25 +3091,40 @@ static int ql_start_rss(struct ql_adapter *qdev)
return status; return status;
} }
static int ql_clear_routing_entries(struct ql_adapter *qdev)
{
int i, status = 0;
status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
if (status)
return status;
/* Clear all the entries in the routing table. */
for (i = 0; i < 16; i++) {
status = ql_set_routing_reg(qdev, i, 0, 0);
if (status) {
QPRINTK(qdev, IFUP, ERR,
"Failed to init routing register for CAM "
"packets.\n");
break;
}
}
ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
return status;
}
/* Initialize the frame-to-queue routing. */ /* Initialize the frame-to-queue routing. */
static int ql_route_initialize(struct ql_adapter *qdev) static int ql_route_initialize(struct ql_adapter *qdev)
{ {
int status = 0; int status = 0;
int i;
status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
if (status) if (status)
return status; return status;
/* Clear all the entries in the routing table. */ /* Clear all the entries in the routing table. */
for (i = 0; i < 16; i++) { status = ql_clear_routing_entries(qdev);
status = ql_set_routing_reg(qdev, i, 0, 0); if (status)
if (status) { goto exit;
QPRINTK(qdev, IFUP, ERR,
"Failed to init routing register for CAM packets.\n");
goto exit;
}
}
status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1); status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1);
if (status) { if (status) {
@ -3096,14 +3163,15 @@ exit:
int ql_cam_route_initialize(struct ql_adapter *qdev) int ql_cam_route_initialize(struct ql_adapter *qdev)
{ {
int status; int status, set;
status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); /* If check if the link is up and use to
if (status) * determine if we are setting or clearing
return status; * the MAC address in the CAM.
status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, */
MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); set = ql_read32(qdev, STS);
ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); set &= qdev->port_link_up;
status = ql_set_mac_addr(qdev, set);
if (status) { if (status) {
QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n");
return status; return status;
@ -3210,9 +3278,17 @@ static int ql_adapter_reset(struct ql_adapter *qdev)
{ {
u32 value; u32 value;
int status = 0; int status = 0;
unsigned long end_jiffies = jiffies + unsigned long end_jiffies;
max((unsigned long)1, usecs_to_jiffies(30));
/* Clear all the entries in the routing table. */
status = ql_clear_routing_entries(qdev);
if (status) {
QPRINTK(qdev, IFUP, ERR, "Failed to clear routing bits.\n");
return status;
}
end_jiffies = jiffies +
max((unsigned long)1, usecs_to_jiffies(30));
ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR);
do { do {
@ -3252,7 +3328,7 @@ static int ql_adapter_down(struct ql_adapter *qdev)
int i, status = 0; int i, status = 0;
struct rx_ring *rx_ring; struct rx_ring *rx_ring;
netif_carrier_off(qdev->ndev); ql_link_off(qdev);
/* Don't kill the reset worker thread if we /* Don't kill the reset worker thread if we
* are in the process of recovery. * are in the process of recovery.
@ -3319,8 +3395,12 @@ static int ql_adapter_up(struct ql_adapter *qdev)
} }
set_bit(QL_ADAPTER_UP, &qdev->flags); set_bit(QL_ADAPTER_UP, &qdev->flags);
ql_alloc_rx_buffers(qdev); ql_alloc_rx_buffers(qdev);
if ((ql_read32(qdev, STS) & qdev->port_init)) /* If the port is initialized and the
netif_carrier_on(qdev->ndev); * link is up the turn on the carrier.
*/
if ((ql_read32(qdev, STS) & qdev->port_init) &&
(ql_read32(qdev, STS) & qdev->port_link_up))
ql_link_on(qdev);
ql_enable_interrupts(qdev); ql_enable_interrupts(qdev);
ql_enable_all_completion_interrupts(qdev); ql_enable_all_completion_interrupts(qdev);
netif_tx_start_all_queues(qdev->ndev); netif_tx_start_all_queues(qdev->ndev);
@ -3346,11 +3426,6 @@ static int ql_get_adapter_resources(struct ql_adapter *qdev)
return -ENOMEM; return -ENOMEM;
} }
status = ql_request_irq(qdev); status = ql_request_irq(qdev);
if (status)
goto err_irq;
return status;
err_irq:
ql_free_mem_resources(qdev);
return status; return status;
} }
@ -3414,7 +3489,7 @@ static int ql_configure_rings(struct ql_adapter *qdev)
for (i = 0; i < qdev->tx_ring_count; i++) { for (i = 0; i < qdev->tx_ring_count; i++) {
tx_ring = &qdev->tx_ring[i]; tx_ring = &qdev->tx_ring[i];
memset((void *)tx_ring, 0, sizeof(tx_ring)); memset((void *)tx_ring, 0, sizeof(*tx_ring));
tx_ring->qdev = qdev; tx_ring->qdev = qdev;
tx_ring->wq_id = i; tx_ring->wq_id = i;
tx_ring->wq_len = qdev->tx_ring_size; tx_ring->wq_len = qdev->tx_ring_size;
@ -3430,7 +3505,7 @@ static int ql_configure_rings(struct ql_adapter *qdev)
for (i = 0; i < qdev->rx_ring_count; i++) { for (i = 0; i < qdev->rx_ring_count; i++) {
rx_ring = &qdev->rx_ring[i]; rx_ring = &qdev->rx_ring[i];
memset((void *)rx_ring, 0, sizeof(rx_ring)); memset((void *)rx_ring, 0, sizeof(*rx_ring));
rx_ring->qdev = qdev; rx_ring->qdev = qdev;
rx_ring->cq_id = i; rx_ring->cq_id = i;
rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */ rx_ring->cpu = i % cpu_cnt; /* CPU to run handler on. */
@ -3789,7 +3864,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
int pos, err = 0; int pos, err = 0;
u16 val16; u16 val16;
memset((void *)qdev, 0, sizeof(qdev)); memset((void *)qdev, 0, sizeof(*qdev));
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) { if (err) {
dev_err(&pdev->dev, "PCI device enable failed.\n"); dev_err(&pdev->dev, "PCI device enable failed.\n");
@ -3976,7 +4051,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev,
pci_disable_device(pdev); pci_disable_device(pdev);
return err; return err;
} }
netif_carrier_off(ndev); ql_link_off(qdev);
ql_display_dev_info(ndev); ql_display_dev_info(ndev);
cards_found++; cards_found++;
return 0; return 0;

View File

@ -238,7 +238,7 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp)
&qdev->mpi_port_cfg_work, 0); &qdev->mpi_port_cfg_work, 0);
} }
netif_carrier_on(qdev->ndev); ql_link_on(qdev);
} }
static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
@ -251,7 +251,7 @@ static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
if (status) if (status)
QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n"); QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n");
netif_carrier_off(qdev->ndev); ql_link_off(qdev);
} }
static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp)
@ -849,7 +849,7 @@ void ql_mpi_idc_work(struct work_struct *work)
case MB_CMD_PORT_RESET: case MB_CMD_PORT_RESET:
case MB_CMD_SET_PORT_CFG: case MB_CMD_SET_PORT_CFG:
case MB_CMD_STOP_FW: case MB_CMD_STOP_FW:
netif_carrier_off(qdev->ndev); ql_link_off(qdev);
/* Signal the resulting link up AEN /* Signal the resulting link up AEN
* that the frame routing and mac addr * that the frame routing and mac addr
* needs to be set. * needs to be set.

View File

@ -1938,7 +1938,7 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
if (!res) if (!res)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, res->end - res->start); release_mem_region(res->start, resource_size(res));
iounmap(pdata->ioaddr); iounmap(pdata->ioaddr);
@ -1976,7 +1976,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
retval = -ENODEV; retval = -ENODEV;
goto out_0; goto out_0;
} }
res_size = res->end - res->start + 1; res_size = resource_size(res);
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq_res) { if (!irq_res) {
@ -2104,7 +2104,7 @@ out_unmap_io_3:
out_free_netdev_2: out_free_netdev_2:
free_netdev(dev); free_netdev(dev);
out_release_io_1: out_release_io_1:
release_mem_region(res->start, res->end - res->start); release_mem_region(res->start, resource_size(res));
out_0: out_0:
return retval; return retval;
} }

View File

@ -486,12 +486,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
{ {
struct tun_file *tfile = file->private_data; struct tun_file *tfile = file->private_data;
struct tun_struct *tun = __tun_get(tfile); struct tun_struct *tun = __tun_get(tfile);
struct sock *sk = tun->sk; struct sock *sk;
unsigned int mask = 0; unsigned int mask = 0;
if (!tun) if (!tun)
return POLLERR; return POLLERR;
sk = tun->sk;
DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
poll_wait(file, &tun->socket.wait, wait); poll_wait(file, &tun->socket.wait, wait);
@ -1324,20 +1326,22 @@ static int tun_chr_close(struct inode *inode, struct file *file)
struct tun_file *tfile = file->private_data; struct tun_file *tfile = file->private_data;
struct tun_struct *tun; struct tun_struct *tun;
rtnl_lock();
tun = __tun_get(tfile); tun = __tun_get(tfile);
if (tun) { if (tun) {
DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); struct net_device *dev = tun->dev;
DBG(KERN_INFO "%s: tun_chr_close\n", dev->name);
__tun_detach(tun); __tun_detach(tun);
/* If desireable, unregister the netdevice. */ /* If desireable, unregister the netdevice. */
if (!(tun->flags & TUN_PERSIST)) if (!(tun->flags & TUN_PERSIST)) {
unregister_netdevice(tun->dev); rtnl_lock();
if (dev->reg_state == NETREG_REGISTERED)
unregister_netdevice(dev);
rtnl_unlock();
}
} }
rtnl_unlock();
tun = tfile->tun; tun = tfile->tun;
if (tun) if (tun)

View File

@ -823,30 +823,30 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
struct p54_tx_info *range; struct p54_tx_info *range;
unsigned long flags; unsigned long flags;
if (unlikely(!skb || !dev || skb_queue_empty(&priv->tx_queue))) if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
return; return;
/* There used to be a check here to see if the SKB was on the /*
* TX queue or not. This can never happen because all SKBs we * don't try to free an already unlinked skb
* see here successfully went through p54_assign_address()
* which means the SKB is on the ->tx_queue.
*/ */
if (unlikely((!skb->next) || (!skb->prev)))
return;
spin_lock_irqsave(&priv->tx_queue.lock, flags); spin_lock_irqsave(&priv->tx_queue.lock, flags);
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
range = (void *)info->rate_driver_data; range = (void *)info->rate_driver_data;
if (!skb_queue_is_first(&priv->tx_queue, skb)) { if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
struct ieee80211_tx_info *ni; struct ieee80211_tx_info *ni;
struct p54_tx_info *mr; struct p54_tx_info *mr;
ni = IEEE80211_SKB_CB(skb_queue_prev(&priv->tx_queue, skb)); ni = IEEE80211_SKB_CB(skb->prev);
mr = (struct p54_tx_info *)ni->rate_driver_data; mr = (struct p54_tx_info *)ni->rate_driver_data;
} }
if (!skb_queue_is_last(&priv->tx_queue, skb)) { if (skb->next != (struct sk_buff *)&priv->tx_queue) {
struct ieee80211_tx_info *ni; struct ieee80211_tx_info *ni;
struct p54_tx_info *mr; struct p54_tx_info *mr;
ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, skb)); ni = IEEE80211_SKB_CB(skb->next);
mr = (struct p54_tx_info *)ni->rate_driver_data; mr = (struct p54_tx_info *)ni->rate_driver_data;
} }
__skb_unlink(skb, &priv->tx_queue); __skb_unlink(skb, &priv->tx_queue);
@ -864,13 +864,15 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->tx_queue.lock, flags); spin_lock_irqsave(&priv->tx_queue.lock, flags);
skb_queue_walk(&priv->tx_queue, entry) { entry = priv->tx_queue.next;
while (entry != (struct sk_buff *)&priv->tx_queue) {
struct p54_hdr *hdr = (struct p54_hdr *) entry->data; struct p54_hdr *hdr = (struct p54_hdr *) entry->data;
if (hdr->req_id == req_id) { if (hdr->req_id == req_id) {
spin_unlock_irqrestore(&priv->tx_queue.lock, flags); spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
return entry; return entry;
} }
entry = entry->next;
} }
spin_unlock_irqrestore(&priv->tx_queue.lock, flags); spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
return NULL; return NULL;
@ -888,22 +890,24 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
int count, idx; int count, idx;
spin_lock_irqsave(&priv->tx_queue.lock, flags); spin_lock_irqsave(&priv->tx_queue.lock, flags);
skb_queue_walk(&priv->tx_queue, entry) { entry = (struct sk_buff *) priv->tx_queue.next;
while (entry != (struct sk_buff *)&priv->tx_queue) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
struct p54_hdr *entry_hdr; struct p54_hdr *entry_hdr;
struct p54_tx_data *entry_data; struct p54_tx_data *entry_data;
unsigned int pad = 0, frame_len; unsigned int pad = 0, frame_len;
range = (void *)info->rate_driver_data; range = (void *)info->rate_driver_data;
if (range->start_addr != addr) if (range->start_addr != addr) {
entry = entry->next;
continue; continue;
}
if (!skb_queue_is_last(&priv->tx_queue, entry)) { if (entry->next != (struct sk_buff *)&priv->tx_queue) {
struct ieee80211_tx_info *ni; struct ieee80211_tx_info *ni;
struct p54_tx_info *mr; struct p54_tx_info *mr;
ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, ni = IEEE80211_SKB_CB(entry->next);
entry));
mr = (struct p54_tx_info *)ni->rate_driver_data; mr = (struct p54_tx_info *)ni->rate_driver_data;
} }
@ -1164,21 +1168,23 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
} }
} }
skb_queue_walk(&priv->tx_queue, entry) { entry = priv->tx_queue.next;
while (left--) {
u32 hole_size; u32 hole_size;
info = IEEE80211_SKB_CB(entry); info = IEEE80211_SKB_CB(entry);
range = (void *)info->rate_driver_data; range = (void *)info->rate_driver_data;
hole_size = range->start_addr - last_addr; hole_size = range->start_addr - last_addr;
if (!target_skb && hole_size >= len) { if (!target_skb && hole_size >= len) {
target_skb = skb_queue_prev(&priv->tx_queue, entry); target_skb = entry->prev;
hole_size -= len; hole_size -= len;
target_addr = last_addr; target_addr = last_addr;
} }
largest_hole = max(largest_hole, hole_size); largest_hole = max(largest_hole, hole_size);
last_addr = range->end_addr; last_addr = range->end_addr;
entry = entry->next;
} }
if (!target_skb && priv->rx_end - last_addr >= len) { if (!target_skb && priv->rx_end - last_addr >= len) {
target_skb = skb_peek_tail(&priv->tx_queue); target_skb = priv->tx_queue.prev;
largest_hole = max(largest_hole, priv->rx_end - last_addr - len); largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
if (!skb_queue_empty(&priv->tx_queue)) { if (!skb_queue_empty(&priv->tx_queue)) {
info = IEEE80211_SKB_CB(target_skb); info = IEEE80211_SKB_CB(target_skb);
@ -2084,6 +2090,7 @@ out:
static void p54_stop(struct ieee80211_hw *dev) static void p54_stop(struct ieee80211_hw *dev)
{ {
struct p54_common *priv = dev->priv; struct p54_common *priv = dev->priv;
struct sk_buff *skb;
mutex_lock(&priv->conf_mutex); mutex_lock(&priv->conf_mutex);
priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->mode = NL80211_IFTYPE_UNSPECIFIED;
@ -2098,7 +2105,8 @@ static void p54_stop(struct ieee80211_hw *dev)
p54_tx_cancel(dev, priv->cached_beacon); p54_tx_cancel(dev, priv->cached_beacon);
priv->stop(dev); priv->stop(dev);
skb_queue_purge(&priv->tx_queue); while ((skb = skb_dequeue(&priv->tx_queue)))
kfree_skb(skb);
priv->cached_beacon = NULL; priv->cached_beacon = NULL;
priv->tsf_high32 = priv->tsf_low32 = 0; priv->tsf_high32 = priv->tsf_low32 = 0;
mutex_unlock(&priv->conf_mutex); mutex_unlock(&priv->conf_mutex);

View File

@ -78,6 +78,7 @@
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
#define ETH_P_TIPC 0x88CA /* TIPC */ #define ETH_P_TIPC 0x88CA /* TIPC */
#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */
#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */
#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */
#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */

View File

@ -735,12 +735,14 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
if (!*p) if (!*p)
continue; continue;
token = match_token(p, tokens, args); token = match_token(p, tokens, args);
r = match_int(&args[0], &option); if (token != Opt_err) {
if (r < 0) { r = match_int(&args[0], &option);
P9_DPRINTK(P9_DEBUG_ERROR, if (r < 0) {
"integer field, but no integer?\n"); P9_DPRINTK(P9_DEBUG_ERROR,
ret = r; "integer field, but no integer?\n");
continue; ret = r;
continue;
}
} }
switch (token) { switch (token) {
case Opt_port: case Opt_port:

View File

@ -418,7 +418,7 @@ static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
int i; int i;
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
ret = REG_READ(REG_GLOBAL2, 0x1d); ret = REG_READ(REG_GLOBAL, 0x1d);
if ((ret & 0x8000) == 0) if ((ret & 0x8000) == 0)
return 0; return 0;
} }

View File

@ -136,7 +136,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
case IPPROTO_TCP: case IPPROTO_TCP:
case IPPROTO_SCTP: case IPPROTO_SCTP:
case IPPROTO_DCCP: case IPPROTO_DCCP:
if (pskb_may_pull(skb, xprth + 4 - skb->data)) { if (xprth + 4 < skb->data ||
pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be16 *ports = (__be16 *)xprth; __be16 *ports = (__be16 *)xprth;
fl->fl_ip_sport = ports[!!reverse]; fl->fl_ip_sport = ports[!!reverse];

View File

@ -1916,8 +1916,32 @@ ok:
update_lft = 1; update_lft = 1;
else if (stored_lft <= MIN_VALID_LIFETIME) { else if (stored_lft <= MIN_VALID_LIFETIME) {
/* valid_lft <= stored_lft is always true */ /* valid_lft <= stored_lft is always true */
/* XXX: IPsec */ /*
update_lft = 0; * RFC 4862 Section 5.5.3e:
* "Note that the preferred lifetime of
* the corresponding address is always
* reset to the Preferred Lifetime in
* the received Prefix Information
* option, regardless of whether the
* valid lifetime is also reset or
* ignored."
*
* So if the preferred lifetime in
* this advertisement is different
* than what we have stored, but the
* valid lifetime is invalid, just
* reset prefered_lft.
*
* We must set the valid lifetime
* to the stored lifetime since we'll
* be updating the timestamp below,
* else we'll set it back to the
* minumum.
*/
if (prefered_lft != ifp->prefered_lft) {
valid_lft = stored_lft;
update_lft = 1;
}
} else { } else {
valid_lft = MIN_VALID_LIFETIME; valid_lft = MIN_VALID_LIFETIME;
if (valid_lft < prefered_lft) if (valid_lft < prefered_lft)
@ -3085,7 +3109,7 @@ restart:
spin_unlock(&ifp->lock); spin_unlock(&ifp->lock);
continue; continue;
} else if (age >= ifp->prefered_lft) { } else if (age >= ifp->prefered_lft) {
/* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */
int deprecate = 0; int deprecate = 0;
if (!(ifp->flags&IFA_F_DEPRECATED)) { if (!(ifp->flags&IFA_F_DEPRECATED)) {

View File

@ -157,7 +157,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr);
ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr);
while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) { while (nh + offset + 1 < skb->data ||
pskb_may_pull(skb, nh + offset + 1 - skb->data)) {
nh = skb_network_header(skb); nh = skb_network_header(skb);
exthdr = (struct ipv6_opt_hdr *)(nh + offset); exthdr = (struct ipv6_opt_hdr *)(nh + offset);
@ -177,7 +178,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
case IPPROTO_TCP: case IPPROTO_TCP:
case IPPROTO_SCTP: case IPPROTO_SCTP:
case IPPROTO_DCCP: case IPPROTO_DCCP:
if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) { if (!onlyproto && (nh + offset + 4 < skb->data ||
pskb_may_pull(skb, nh + offset + 4 - skb->data))) {
__be16 *ports = (__be16 *)exthdr; __be16 *ports = (__be16 *)exthdr;
fl->fl_ip_sport = ports[!!reverse]; fl->fl_ip_sport = ports[!!reverse];

View File

@ -6652,21 +6652,6 @@ static void sctp_wait_for_close(struct sock *sk, long timeout)
finish_wait(sk->sk_sleep, &wait); finish_wait(sk->sk_sleep, &wait);
} }
static void sctp_sock_rfree_frag(struct sk_buff *skb)
{
struct sk_buff *frag;
if (!skb->data_len)
goto done;
/* Don't forget the fragments. */
skb_walk_frags(skb, frag)
sctp_sock_rfree_frag(frag);
done:
sctp_sock_rfree(skb);
}
static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk)
{ {
struct sk_buff *frag; struct sk_buff *frag;
@ -6776,7 +6761,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
if (event->asoc == assoc) { if (event->asoc == assoc) {
sctp_sock_rfree_frag(skb);
__skb_unlink(skb, &oldsk->sk_receive_queue); __skb_unlink(skb, &oldsk->sk_receive_queue);
__skb_queue_tail(&newsk->sk_receive_queue, skb); __skb_queue_tail(&newsk->sk_receive_queue, skb);
sctp_skb_set_owner_r_frag(skb, newsk); sctp_skb_set_owner_r_frag(skb, newsk);
@ -6807,7 +6791,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
if (event->asoc == assoc) { if (event->asoc == assoc) {
sctp_sock_rfree_frag(skb);
__skb_unlink(skb, &oldsp->pd_lobby); __skb_unlink(skb, &oldsp->pd_lobby);
__skb_queue_tail(queue, skb); __skb_queue_tail(queue, skb);
sctp_skb_set_owner_r_frag(skb, newsk); sctp_skb_set_owner_r_frag(skb, newsk);
@ -6822,15 +6805,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
} }
sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp)
sctp_sock_rfree_frag(skb);
sctp_skb_set_owner_r_frag(skb, newsk); sctp_skb_set_owner_r_frag(skb, newsk);
}
sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp)
sctp_sock_rfree_frag(skb);
sctp_skb_set_owner_r_frag(skb, newsk); sctp_skb_set_owner_r_frag(skb, newsk);
}
/* Set the type of socket to indicate that it is peeled off from the /* Set the type of socket to indicate that it is peeled off from the
* original UDP-style socket or created with the accept() call on a * original UDP-style socket or created with the accept() call on a