diff options
Diffstat (limited to 'drivers/net')
36 files changed, 721 insertions, 223 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index a80da0e14a5..3b79a225628 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -259,6 +259,8 @@ struct be_adapter { u32 port_num; bool promiscuous; u32 cap; + u32 rx_fc; /* Rx flow control */ + u32 tx_fc; /* Tx flow control */ }; extern const struct ethtool_ops be_ethtool_ops; diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 49953787e41..e5f9676cf1b 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -68,7 +68,7 @@ enum { #define CQE_STATUS_COMPL_MASK 0xFFFF #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ #define CQE_STATUS_EXTD_MASK 0xFFFF -#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ +#define CQE_STATUS_EXTD_SHIFT 16 /* bits 16 - 31 */ struct be_mcc_compl { u32 status; /* dword 0 */ diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index cda5bf2fc50..f0fd95b43c0 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -323,10 +323,12 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) if (ecmd->autoneg != 0) return -EINVAL; + adapter->tx_fc = ecmd->tx_pause; + adapter->rx_fc = ecmd->rx_pause; - status = be_cmd_set_flow_control(adapter, ecmd->tx_pause, - ecmd->rx_pause); - if (!status) + status = be_cmd_set_flow_control(adapter, + adapter->tx_fc, adapter->rx_fc); + if (status) dev_warn(&adapter->pdev->dev, "Pause param set failed.\n"); return status; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 1f941f02771..876b357101f 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1610,11 +1610,21 @@ static int be_open(struct net_device *netdev) status = be_cmd_link_status_query(adapter, &link_up); if (status) - return status; + goto ret_sts; be_link_status_update(adapter, link_up); + status = be_vid_config(adapter); + if (status) + goto ret_sts; + + status = be_cmd_set_flow_control(adapter, + adapter->tx_fc, adapter->rx_fc); + if (status) + goto ret_sts; + schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); - return 0; +ret_sts: + return status; } static int be_setup(struct be_adapter *adapter) @@ -1648,17 +1658,8 @@ static int be_setup(struct be_adapter *adapter) if (status != 0) goto rx_qs_destroy; - status = be_vid_config(adapter); - if (status != 0) - goto mccqs_destroy; - - status = be_cmd_set_flow_control(adapter, true, true); - if (status != 0) - goto mccqs_destroy; return 0; -mccqs_destroy: - be_mcc_queues_destroy(adapter); rx_qs_destroy: be_rx_queues_destroy(adapter); tx_qs_destroy: @@ -1909,6 +1910,10 @@ static void be_netdev_init(struct net_device *netdev) adapter->rx_csum = true; + /* Default settings for Rx and Tx flow control */ + adapter->rx_fc = true; + adapter->tx_fc = true; + netif_set_gso_max_size(netdev, 65535); BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); @@ -2171,6 +2176,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) be_close(netdev); rtnl_unlock(); } + be_cmd_get_flow_control(adapter, &adapter->tx_fc, &adapter->rx_fc); be_clear(adapter); pci_save_state(pdev); diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index f0b9a1e1db4..564e31c9fee 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -589,6 +589,22 @@ static int can_changelink(struct net_device *dev, return 0; } +static size_t can_get_size(const struct net_device *dev) +{ + struct can_priv *priv = netdev_priv(dev); + size_t size; + + size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */ + size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */ + size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ + size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ + size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ + if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ + size += sizeof(struct can_bittiming_const); + + return size; +} + static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); @@ -639,6 +655,7 @@ static struct rtnl_link_ops can_link_ops __read_mostly = { .setup = can_setup, .newlink = can_newlink, .changelink = can_changelink, + .get_size = can_get_size, .fill_info = can_fill_info, .fill_xstats = can_fill_xstats, }; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 9012e0abc62..abdbd9c2b78 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -319,7 +319,7 @@ static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg) cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); - cf->can_id = msg->msg.can_msg.id; + cf->can_id = le32_to_cpu(msg->msg.can_msg.id); cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8); if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME @@ -813,6 +813,9 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc; } + /* Respect byte order */ + msg->msg.can_msg.id = cpu_to_le32(msg->msg.can_msg.id); + for (i = 0; i < MAX_TX_URBS; i++) { if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) { context = &dev->tx_contexts[i]; diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 05916aafa4f..f857afe8e48 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -4342,11 +4342,11 @@ static int cas_open(struct net_device *dev) cas_unlock_all_restore(cp, flags); } + err = -ENOMEM; if (cas_tx_tiny_alloc(cp) < 0) - return -ENOMEM; + goto err_unlock; /* alloc rx descriptors */ - err = -ENOMEM; if (cas_alloc_rxds(cp) < 0) goto err_tx_tiny; @@ -4386,6 +4386,7 @@ err_spare: cas_free_rxds(cp); err_tx_tiny: cas_tx_tiny_free(cp); +err_unlock: mutex_unlock(&cp->pm_mutex); return err; } diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index f72c56dec33..3179521aee9 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -2221,7 +2221,7 @@ void emac_poll_controller(struct net_device *ndev) struct emac_priv *priv = netdev_priv(ndev); emac_int_disable(priv); - emac_irq(ndev->irq, priv); + emac_irq(ndev->irq, ndev); emac_int_enable(priv); } #endif diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 5d2f48f0225..3c29a20b751 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1427,19 +1427,31 @@ static int e100_phy_init(struct nic *nic) } else DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); - /* Isolate all the PHY ids */ - for (addr = 0; addr < 32; addr++) - mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); - /* Select the discovered PHY */ - bmcr &= ~BMCR_ISOLATE; - mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); - /* Get phy ID */ id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); nic->phy = (u32)id_hi << 16 | (u32)id_lo; DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); + /* Select the phy and isolate the rest */ + for (addr = 0; addr < 32; addr++) { + if (addr != nic->mii.phy_id) { + mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); + } else if (nic->phy != phy_82552_v) { + bmcr = mdio_read(netdev, addr, MII_BMCR); + mdio_write(netdev, addr, MII_BMCR, + bmcr & ~BMCR_ISOLATE); + } + } + /* + * Workaround for 82552: + * Clear the ISOLATE bit on selected phy_id last (mirrored on all + * other phy_id's) using bmcr value from addr discovery loop above. + */ + if (nic->phy == phy_82552_v) + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, + bmcr & ~BMCR_ISOLATE); + /* Handle National tx phys */ #define NCS_PHY_MODEL_MASK 0xFFF0FFFF if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index c0f185beb8b..1190167a8b3 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -76,6 +76,7 @@ /* Extended Device Control */ #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ +#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 @@ -347,6 +348,7 @@ /* Extended Configuration Control and Size */ #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 +#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 405a144ebca..189dfa2d6c7 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -141,6 +141,20 @@ struct e1000_info; #define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */ #define HV_TNCRS_LOWER PHY_REG(778, 30) +/* BM PHY Copper Specific Status */ +#define BM_CS_STATUS 17 +#define BM_CS_STATUS_LINK_UP 0x0400 +#define BM_CS_STATUS_RESOLVED 0x0800 +#define BM_CS_STATUS_SPEED_MASK 0xC000 +#define BM_CS_STATUS_SPEED_1000 0x8000 + +/* 82577 Mobile Phy Status Register */ +#define HV_M_STATUS 26 +#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 +#define HV_M_STATUS_SPEED_MASK 0x0300 +#define HV_M_STATUS_SPEED_1000 0x0200 +#define HV_M_STATUS_LINK_UP 0x0040 + enum e1000_boards { board_82571, board_82572, diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 7b05cf47f7f..aaea41ef794 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -903,6 +903,7 @@ struct e1000_shadow_ram { struct e1000_dev_spec_ich8lan { bool kmrn_lock_loss_workaround_enabled; struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; + bool nvm_k1_enabled; }; struct e1000_hw { diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index b6388b9535f..51ddb04ab19 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -124,11 +124,25 @@ #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */ +/* SMBus Address Phy Register */ +#define HV_SMB_ADDR PHY_REG(768, 26) +#define HV_SMB_ADDR_PEC_EN 0x0200 +#define HV_SMB_ADDR_VALID 0x0080 + +/* Strapping Option Register - RO */ +#define E1000_STRAP 0x0000C +#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 +#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 + /* OEM Bits Phy Register */ #define HV_OEM_BITS PHY_REG(768, 25) #define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ +#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ #define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ +#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ +#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ + /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ union ich8_hws_flash_status { @@ -208,6 +222,9 @@ static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); static s32 e1000_led_on_pchlan(struct e1000_hw *hw); static s32 e1000_led_off_pchlan(struct e1000_hw *hw); static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); +static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); +static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); +static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -483,14 +500,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) 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 @@ -500,6 +509,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) goto out; + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000_k1_gig_workaround_hv(hw, link); + if (ret_val) + goto out; + } + if (!link) goto out; /* No link detected */ @@ -794,6 +809,326 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw) } /** + * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration + * @hw: pointer to the HW structure + * + * SW should configure the LCD from the NVM extended configuration region + * as a workaround for certain parts. + **/ +static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; + s32 ret_val; + u16 word_addr, reg_data, reg_addr, phy_page = 0; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + + /* + * Initialize the PHY from the NVM on ICH platforms. This + * is needed due to an issue where the NVM configuration is + * not properly autoloaded after power transitions. + * Therefore, after each PHY reset, we will load the + * configuration data out of the NVM manually. + */ + if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) || + (hw->mac.type == e1000_pchlan)) { + struct e1000_adapter *adapter = hw->adapter; + + /* Check if SW needs to configure the PHY */ + if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) || + (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) || + (hw->mac.type == e1000_pchlan)) + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; + else + sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; + + data = er32(FEXTNVM); + if (!(data & sw_cfg_mask)) + goto out; + + /* Wait for basic configuration completes before proceeding */ + e1000_lan_init_done_ich8lan(hw); + + /* + * Make sure HW does not configure LCD from PHY + * extended configuration before SW configuration + */ + data = er32(EXTCNF_CTRL); + if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) + goto out; + + cnf_size = er32(EXTCNF_SIZE); + cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; + cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; + if (!cnf_size) + goto out; + + cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; + cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; + + if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && + (hw->mac.type == e1000_pchlan)) { + /* + * HW configures the SMBus address and LEDs when the + * OEM and LCD Write Enable bits are set in the NVM. + * When both NVM bits are cleared, SW will configure + * them instead. + */ + data = er32(STRAP); + data &= E1000_STRAP_SMBUS_ADDRESS_MASK; + reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; + reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, + reg_data); + if (ret_val) + goto out; + + data = er32(LEDCTL); + ret_val = e1000_write_phy_reg_hv_locked(hw, + HV_LED_CONFIG, + (u16)data); + if (ret_val) + goto out; + } + /* Configure LCD from extended configuration region. */ + + /* cnf_base_addr is in DWORD */ + word_addr = (u16)(cnf_base_addr << 1); + + for (i = 0; i < cnf_size; i++) { + ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, + ®_data); + if (ret_val) + goto out; + + ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1), + 1, ®_addr); + if (ret_val) + goto out; + + /* Save off the PHY page for future writes. */ + if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { + phy_page = reg_data; + continue; + } + + reg_addr &= PHY_REG_MASK; + reg_addr |= phy_page; + + ret_val = phy->ops.write_phy_reg_locked(hw, + (u32)reg_addr, + reg_data); + if (ret_val) + goto out; + } + } + +out: + hw->phy.ops.release_phy(hw); + return ret_val; +} + +/** + * e1000_k1_gig_workaround_hv - K1 Si workaround + * @hw: pointer to the HW structure + * @link: link up bool flag + * + * If K1 is enabled for 1Gbps, the MAC might stall when transitioning + * from a lower speed. This workaround disables K1 whenever link is at 1Gig + * If link is down, the function will restore the default K1 setting located + * in the NVM. + **/ +static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) +{ + s32 ret_val = 0; + u16 status_reg = 0; + bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; + + if (hw->mac.type != e1000_pchlan) + goto out; + + /* Wrap the whole flow with the sw flag */ + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + goto out; + + /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ + if (link) { + if (hw->phy.type == e1000_phy_82578) { + ret_val = hw->phy.ops.read_phy_reg_locked(hw, + BM_CS_STATUS, + &status_reg); + if (ret_val) + goto release; + + status_reg &= BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_MASK; + + if (status_reg == (BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_1000)) + k1_enable = false; + } + + if (hw->phy.type == e1000_phy_82577) { + ret_val = hw->phy.ops.read_phy_reg_locked(hw, + HV_M_STATUS, + &status_reg); + if (ret_val) + goto release; + + status_reg &= HV_M_STATUS_LINK_UP | + HV_M_STATUS_AUTONEG_COMPLETE | + HV_M_STATUS_SPEED_MASK; + + if (status_reg == (HV_M_STATUS_LINK_UP | + HV_M_STATUS_AUTONEG_COMPLETE | + HV_M_STATUS_SPEED_1000)) + k1_enable = false; + } + + /* Link stall fix for link up */ + ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), + 0x0100); + if (ret_val) + goto release; + + } else { + /* Link stall fix for link down */ + ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), + 0x4100); + if (ret_val) + goto release; + } + + ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); + +release: + hw->phy.ops.release_phy(hw); +out: + return ret_val; +} + +/** + * e1000_configure_k1_ich8lan - Configure K1 power state + * @hw: pointer to the HW structure + * @enable: K1 state to configure + * + * Configure the K1 power state based on the provided parameter. + * Assumes semaphore already acquired. + * + * Success returns 0, Failure returns -E1000_ERR_PHY (-2) + **/ +static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) +{ + s32 ret_val = 0; + u32 ctrl_reg = 0; + u32 ctrl_ext = 0; + u32 reg = 0; + u16 kmrn_reg = 0; + + ret_val = e1000e_read_kmrn_reg_locked(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + &kmrn_reg); + if (ret_val) + goto out; + + if (k1_enable) + kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; + else + kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; + + ret_val = e1000e_write_kmrn_reg_locked(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + kmrn_reg); + if (ret_val) + goto out; + + udelay(20); + ctrl_ext = er32(CTRL_EXT); + ctrl_reg = er32(CTRL); + + reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); + reg |= E1000_CTRL_FRCSPD; + ew32(CTRL, reg); + + ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); + udelay(20); + ew32(CTRL, ctrl_reg); + ew32(CTRL_EXT, ctrl_ext); + udelay(20); + +out: + return ret_val; +} + +/** + * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration + * @hw: pointer to the HW structure + * @d0_state: boolean if entering d0 or d3 device state + * + * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are + * collectively called OEM bits. The OEM Write Enable bit and SW Config bit + * in NVM determines whether HW should configure LPLU and Gbe Disable. + **/ +static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) +{ + s32 ret_val = 0; + u32 mac_reg; + u16 oem_reg; + + if (hw->mac.type != e1000_pchlan) + return ret_val; + + ret_val = hw->phy.ops.acquire_phy(hw); + if (ret_val) + return ret_val; + + mac_reg = er32(EXTCNF_CTRL); + if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) + goto out; + + mac_reg = er32(FEXTNVM); + if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) + goto out; + + mac_reg = er32(PHY_CTRL); + + ret_val = hw->phy.ops.read_phy_reg_locked(hw, HV_OEM_BITS, &oem_reg); + if (ret_val) + goto out; + + oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); + + if (d0_state) { + if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) + oem_reg |= HV_OEM_BITS_GBE_DIS; + + if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) + oem_reg |= HV_OEM_BITS_LPLU; + } else { + if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE) + oem_reg |= HV_OEM_BITS_GBE_DIS; + + if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU) + oem_reg |= HV_OEM_BITS_LPLU; + } + /* Restart auto-neg to activate the bits */ + oem_reg |= HV_OEM_BITS_RESTART_AN; + ret_val = hw->phy.ops.write_phy_reg_locked(hw, HV_OEM_BITS, oem_reg); + +out: + hw->phy.ops.release_phy(hw); + + return ret_val; +} + + +/** * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be * done after every PHY reset. **/ @@ -833,10 +1168,20 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.acquire_phy(hw); if (ret_val) return ret_val; + hw->phy.addr = 1; - e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + if (ret_val) + goto out; hw->phy.ops.release_phy(hw); + /* + * Configure the K1 Si workaround during phy reset assuming there is + * link so that it disables K1 if link is in 1Gbps. + */ + ret_val = e1000_k1_gig_workaround_hv(hw, true); + +out: return ret_val; } @@ -882,11 +1227,8 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { - struct e1000_phy_info *phy = &hw->phy; - u32 i; - u32 data, cnf_size, cnf_base_addr, sw_cfg_mask; - s32 ret_val; - u16 reg, word_addr, reg_data, reg_addr, phy_page = 0; + s32 ret_val = 0; + u16 reg; ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) @@ -905,81 +1247,16 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) e1e_rphy(hw, BM_WUC, ®); - /* - * Initialize the PHY from the NVM on ICH platforms. This - * is needed due to an issue where the NVM configuration is - * not properly autoloaded after power transitions. - * Therefore, after each PHY reset, we will load the - * configuration data out of the NVM manually. - */ - if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) { - struct e1000_adapter *adapter = hw->adapter; - - /* Check if SW needs configure the PHY */ - if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) || - (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M)) - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; - else - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; - - data = er32(FEXTNVM); - if (!(data & sw_cfg_mask)) - return 0; - - /* Wait for basic configuration completes before proceeding */ - e1000_lan_init_done_ich8lan(hw); - - /* - * Make sure HW does not configure LCD from PHY - * extended configuration before SW configuration - */ - data = er32(EXTCNF_CTRL); - if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) - return 0; - - cnf_size = er32(EXTCNF_SIZE); - cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; - cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; - if (!cnf_size) - return 0; - - cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; - cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - - /* Configure LCD from extended configuration region. */ - - /* cnf_base_addr is in DWORD */ - word_addr = (u16)(cnf_base_addr << 1); - - for (i = 0; i < cnf_size; i++) { - ret_val = e1000_read_nvm(hw, - (word_addr + i * 2), - 1, - ®_data); - if (ret_val) - return ret_val; - - ret_val = e1000_read_nvm(hw, - (word_addr + i * 2 + 1), - 1, - ®_addr); - if (ret_val) - return ret_val; - - /* Save off the PHY page for future writes. */ - if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { - phy_page = reg_data; - continue; - } - - reg_addr |= phy_page; + /* Configure the LCD with the extended configuration region in NVM */ + ret_val = e1000_sw_lcd_config_ich8lan(hw); + if (ret_val) + goto out; - ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data); - if (ret_val) - return ret_val; - } - } + /* Configure the LCD with the OEM bits in NVM */ + if (hw->mac.type == e1000_pchlan) + ret_val = e1000_oem_bits_config_ich8lan(hw, true); +out: return 0; } @@ -2306,6 +2583,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) { + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u16 reg; u32 ctrl, icr, kab; s32 ret_val; @@ -2341,6 +2619,18 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ew32(PBS, E1000_PBS_16K); } + if (hw->mac.type == e1000_pchlan) { + /* Save the NVM K1 bit setting*/ + ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); + if (ret_val) + return ret_val; + + if (reg & E1000_NVM_K1_ENABLE) + dev_spec->nvm_k1_enabled = true; + else + dev_spec->nvm_k1_enabled = false; + } + ctrl = er32(CTRL); if (!e1000_check_reset_block(hw)) { @@ -2386,6 +2676,15 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) e1e_rphy(hw, BM_WUC, ®); + ret_val = e1000_sw_lcd_config_ich8lan(hw); + if (ret_val) + goto out; + + if (hw->mac.type == e1000_pchlan) { + ret_val = e1000_oem_bits_config_ich8lan(hw, true); + if (ret_val) + goto out; + } /* * For PCH, this write will make sure that any noise * will be detected as a CRC error and be dropped rather than show up @@ -2404,6 +2703,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) ret_val = e1000_hv_phy_workarounds_ich8lan(hw); +out: return ret_val; } @@ -2708,14 +3008,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, if (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) && (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index f9d33ab05e9..03175b3a2c9 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -95,13 +95,6 @@ static const u16 e1000_igp_2_cable_length_table[] = /* BM PHY Copper Specific Control 1 */ #define BM_CS_CTRL1 16 -/* BM PHY Copper Specific Status */ -#define BM_CS_STATUS 17 -#define BM_CS_STATUS_LINK_UP 0x0400 -#define BM_CS_STATUS_RESOLVED 0x0800 -#define BM_CS_STATUS_SPEED_MASK 0xC000 -#define BM_CS_STATUS_SPEED_1000 0x8000 - #define HV_MUX_DATA_CTRL PHY_REG(776, 16) #define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 #define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 @@ -563,7 +556,7 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) } /** - * e1000_read_kmrn_reg_locked - Read kumeran register + * e1000e_read_kmrn_reg_locked - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data @@ -572,7 +565,7 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) * information retrieved is stored in data. * Assumes semaphore already acquired. **/ -s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) +s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_kmrn_reg(hw, offset, data, true); } @@ -631,7 +624,7 @@ s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) } /** - * e1000_write_kmrn_reg_locked - Write kumeran register + * e1000e_write_kmrn_reg_locked - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset @@ -639,7 +632,7 @@ s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) * Write the data to PHY register at the offset using the kumeran interface. * Assumes semaphore already acquired. **/ -s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) +s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_kmrn_reg(hw, offset, data, true); } diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index 6ac46486697..efbf67689ec 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -427,3 +427,4 @@ void fsl_pq_mdio_exit(void) of_unregister_platform_driver(&fsl_pq_mdio_driver); } module_exit(fsl_pq_mdio_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index cbb143ca1eb..5bd9e6bf6f2 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -44,6 +44,7 @@ #include "ixgbe.h" #include "ixgbe_common.h" +#include "ixgbe_dcb_82599.h" char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = @@ -226,6 +227,56 @@ static void ixgbe_unmap_and_free_tx_resource(struct ixgbe_adapter *adapter, /* tx_buffer_info must be completely set up in the transmit path */ } +/** + * ixgbe_tx_is_paused - check if the tx ring is paused + * @adapter: the ixgbe adapter + * @tx_ring: the corresponding tx_ring + * + * If not in DCB mode, checks TFCS.TXOFF, otherwise, find out the + * corresponding TC of this tx_ring when checking TFCS. + * + * Returns : true if paused + */ +static inline bool ixgbe_tx_is_paused(struct ixgbe_adapter *adapter, + struct ixgbe_ring *tx_ring) +{ + int tc; + u32 txoff = IXGBE_TFCS_TXOFF; + +#ifdef CONFIG_IXGBE_DCB + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + int reg_idx = tx_ring->reg_idx; + int dcb_i = adapter->ring_feature[RING_F_DCB].indices; + + if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + tc = reg_idx >> 2; + txoff = IXGBE_TFCS_TXOFF0; + } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + tc = 0; + txoff = IXGBE_TFCS_TXOFF; + if (dcb_i == 8) { + /* TC0, TC1 */ + tc = reg_idx >> 5; + if (tc == 2) /* TC2, TC3 */ + tc += (reg_idx - 64) >> 4; + else if (tc == 3) /* TC4, TC5, TC6, TC7 */ + tc += 1 + ((reg_idx - 96) >> 3); + } else if (dcb_i == 4) { + /* TC0, TC1 */ + tc = reg_idx >> 6; + if (tc == 1) { + tc += (reg_idx - 64) >> 5; + if (tc == 2) /* TC2, TC3 */ + tc += (reg_idx - 96) >> 4; + } + } + } + txoff <<= tc; + } +#endif + return IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & txoff; +} + static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring, unsigned int eop) @@ -237,7 +288,7 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, adapter->detect_tx_hung = false; if (tx_ring->tx_buffer_info[eop].time_stamp && time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ) && - !(IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF)) { + !ixgbe_tx_is_paused(adapter, tx_ring)) { /* detected Tx unit hang */ union ixgbe_adv_tx_desc *tx_desc; tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); @@ -412,19 +463,23 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, u32 txctrl; int cpu = get_cpu(); int q = tx_ring - adapter->tx_ring; + struct ixgbe_hw *hw = &adapter->hw; if (tx_ring->cpu != cpu) { - txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q)); if (adapter->hw.mac.type == ixgbe_mac_82598EB) { + txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(q)); txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); + txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(q), txctrl); } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { + txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(q)); txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599; txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << - IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); + IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); + txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; + IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(q), txctrl); } - txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl); tx_ring->cpu = cpu; } put_cpu(); @@ -1913,11 +1968,25 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) break; } } + if (hw->mac.type == ixgbe_mac_82599EB) { + u32 rttdcs; + + /* disable the arbiter while setting MTQC */ + rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); + rttdcs |= IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); + /* We enable 8 traffic classes, DCB only */ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) IXGBE_WRITE_REG(hw, IXGBE_MTQC, (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ)); + else + IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); + + /* re-eable the arbiter */ + rttdcs &= ~IXGBE_RTTDCS_ARBDIS; + IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); } } @@ -2471,7 +2540,10 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) ixgbe_restore_vlan(adapter); #ifdef CONFIG_IXGBE_DCB if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - netif_set_gso_max_size(netdev, 32768); + if (hw->mac.type == ixgbe_mac_82598EB) + netif_set_gso_max_size(netdev, 32768); + else + netif_set_gso_max_size(netdev, 65536); ixgbe_configure_dcb(adapter); } else { netif_set_gso_max_size(netdev, 65536); diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index 61eabcac734..b3d7d8d77f4 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -223,69 +223,73 @@ static int __devinit macsonic_init(struct net_device *dev) return 0; } -static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) +#define INVALID_MAC(mac) (memcmp(mac, "\x08\x00\x07", 3) && \ + memcmp(mac, "\x00\xA0\x40", 3) && \ + memcmp(mac, "\x00\x80\x19", 3) && \ + memcmp(mac, "\x00\x05\x02", 3)) + +static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev) { struct sonic_local *lp = netdev_priv(dev); const int prom_addr = ONBOARD_SONIC_PROM_BASE; - int i; + unsigned short val; - /* On NuBus boards we can sometimes look in the ROM resources. - No such luck for comm-slot/onboard. */ - for(i = 0; i < 6; i++) - dev->dev_addr[i] = SONIC_READ_PROM(i); + /* + * On NuBus boards we can sometimes look in the ROM resources. + * No such luck for comm-slot/onboard. + * On the PowerBook 520, the PROM base address is a mystery. + */ + if (hwreg_present((void *)prom_addr)) { + int i; + + for (i = 0; i < 6; i++) + dev->dev_addr[i] = SONIC_READ_PROM(i); + if (!INVALID_MAC(dev->dev_addr)) + return; - /* Most of the time, the address is bit-reversed. The NetBSD - source has a rather long and detailed historical account of - why this is so. */ - if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && - memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && - memcmp(dev->dev_addr, "\x00\x80\x19", 3) && - memcmp(dev->dev_addr, "\x00\x05\x02", 3)) + /* + * Most of the time, the address is bit-reversed. The NetBSD + * source has a rather long and detailed historical account of + * why this is so. + */ bit_reverse_addr(dev->dev_addr); - else - return 0; - - /* If we still have what seems to be a bogus address, we'll - look in the CAM. The top entry should be ours. */ - /* Danger! This only works if MacOS has already initialized - the card... */ - if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && - memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && - memcmp(dev->dev_addr, "\x00\x80\x19", 3) && - memcmp(dev->dev_addr, "\x00\x05\x02", 3)) - { - unsigned short val; - - printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n"); - - SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); - SONIC_WRITE(SONIC_CEP, 15); - - val = SONIC_READ(SONIC_CAP2); - dev->dev_addr[5] = val >> 8; - dev->dev_addr[4] = val & 0xff; - val = SONIC_READ(SONIC_CAP1); - dev->dev_addr[3] = val >> 8; - dev->dev_addr[2] = val & 0xff; - val = SONIC_READ(SONIC_CAP0); - dev->dev_addr[1] = val >> 8; - dev->dev_addr[0] = val & 0xff; - - printk(KERN_INFO "HW Address from CAM 15: %pM\n", - dev->dev_addr); - } else return 0; - - if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) && - memcmp(dev->dev_addr, "\x00\xA0\x40", 3) && - memcmp(dev->dev_addr, "\x00\x80\x19", 3) && - memcmp(dev->dev_addr, "\x00\x05\x02", 3)) - { + if (!INVALID_MAC(dev->dev_addr)) + return; + /* - * Still nonsense ... messed up someplace! + * If we still have what seems to be a bogus address, we'll + * look in the CAM. The top entry should be ours. */ - printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n"); - return -EIO; - } else return 0; + printk(KERN_WARNING "macsonic: MAC address in PROM seems " + "to be invalid, trying CAM\n"); + } else { + printk(KERN_WARNING "macsonic: cannot read MAC address from " + "PROM, trying CAM\n"); + } + + /* This only works if MacOS has already initialized the card. */ + + SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); + SONIC_WRITE(SONIC_CEP, 15); + + val = SONIC_READ(SONIC_CAP2); + dev->dev_addr[5] = val >> 8; + dev->dev_addr[4] = val & 0xff; + val = SONIC_READ(SONIC_CAP1); + dev->dev_addr[3] = val >> 8; + dev->dev_addr[2] = val & 0xff; + val = SONIC_READ(SONIC_CAP0); + dev->dev_addr[1] = val >> 8; + dev->dev_addr[0] = val & 0xff; + + if (!INVALID_MAC(dev->dev_addr)) + return; + + /* Still nonsense ... messed up someplace! */ + + printk(KERN_WARNING "macsonic: MAC address in CAM entry 15 " + "seems invalid, will use a random MAC\n"); + random_ether_addr(dev->dev_addr); } static int __devinit mac_onboard_sonic_probe(struct net_device *dev) @@ -402,8 +406,7 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev) SONIC_WRITE(SONIC_ISR, 0x7fff); /* Now look for the MAC address. */ - if (mac_onboard_sonic_ethernet_addr(dev) != 0) - return -ENODEV; + mac_onboard_sonic_ethernet_addr(dev); /* Shared init code */ return macsonic_init(dev); diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index bd3447f0490..94c9ad2746b 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1760,7 +1760,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"), PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b), PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index cea7531f4f4..a2fc70a0d0c 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3916,6 +3916,8 @@ static int __devinit ql_init_device(struct pci_dev *pdev, goto err_out; } + /* Set PCIe reset type for EEH to fundamental. */ + pdev->needs_freset = 1; pci_save_state(pdev); qdev->reg_base = ioremap_nocache(pci_resource_start(pdev, 1), diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index bcf13c96f73..aec05f26610 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -499,7 +499,7 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) /* Wait for the interrupt to come in. */ status = ql_wait_mbx_cmd_cmplt(qdev); if (status) - goto end; + continue; /* Process the event. If it's an AEN, it * will be handled in-line or a worker diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index f98ef523f52..fa493567848 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3379,7 +3379,7 @@ static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) { /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz); + RTL_W16(RxMaxSize, rx_buf_sz + 1); } static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index cee00ad49b5..49eb91b5f50 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -188,7 +188,7 @@ static int sfn4111t_reset(struct efx_nic *efx) efx_oword_t reg; /* GPIO 3 and the GPIO register are shared with I2C, so block that */ - mutex_lock(&efx->i2c_adap.bus_lock); + i2c_lock_adapter(&efx->i2c_adap); /* Pull RST_N (GPIO 2) low then let it up again, setting the * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the @@ -204,7 +204,7 @@ static int sfn4111t_reset(struct efx_nic *efx) falcon_write(efx, ®, GPIO_CTL_REG_KER); msleep(1); - mutex_unlock(&efx->i2c_adap.bus_lock); + i2c_unlock_adapter(&efx->i2c_adap); ssleep(1); return 0; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2ab5c39f33c..6a10d7ba587 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4538,6 +4538,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_netdev; } + netif_carrier_off(dev); + netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT); err = request_irq(pdev->irq, sky2_intr, diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 36cb2423bcf..75fa32e34fd 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -1144,9 +1144,16 @@ static void dir_open_adapter (struct net_device *dev) } else { char **prphase = printphase; char **prerror = printerror; + int pnr = err / 16 - 1; + int enr = err % 16 - 1; DPRINTK("TR Adapter misc open failure, error code = "); - printk("0x%x, Phase: %s, Error: %s\n", - err, prphase[err/16 -1], prerror[err%16 -1]); + if (pnr < 0 || pnr >= ARRAY_SIZE(printphase) || + enr < 0 || + enr >= ARRAY_SIZE(printerror)) + printk("0x%x, invalid Phase/Error.", err); + else + printk("0x%x, Phase: %s, Error: %s\n", err, + prphase[pnr], prerror[enr]); printk(" retrying after %ds delay...\n", TR_RETRY_INTERVAL/HZ); } diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index c47237c2d63..32d93564a74 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -174,7 +174,7 @@ config USB_NET_CDCETHER * Ericsson Mobile Broadband Module (all variants) * Motorola (DM100 and SB4100) * Broadcom Cable Modem (reference design) - * Toshiba (PCX1100U and F3507g) + * Toshiba (PCX1100U and F3507g/F3607gw) * ... This driver creates an interface named "ethX", where X depends on diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 4a6aff57940..21e1ba16000 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -544,20 +544,60 @@ static const struct usb_device_id products [] = { USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, }, { - /* Ericsson F3307 */ + /* Ericsson F3607gw ver 2 */ + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1905, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, +}, { + /* Ericsson F3607gw ver 3 */ USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, }, { + /* Ericsson F3307 */ + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190a, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, +}, { + /* Ericsson F3307 ver 2 */ + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1909, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, +}, { + /* Ericsson C3607w */ + USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1049, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, +}, { /* Toshiba F3507g */ USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, }, { + /* Toshiba F3607gw */ + USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130c, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, +}, { + /* Toshiba F3607gw ver 2 */ + USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x1311, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, +}, { /* Dell F3507g */ USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8147, USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, +}, { + /* Dell F3607gw */ + USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8183, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, +}, { + /* Dell F3607gw ver 2 */ + USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8184, USB_CLASS_COMM, + USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &cdc_info, }, { }, // END }; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 0caa8008c51..f56dec6119c 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -362,12 +362,12 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) retval = -EINVAL; goto halt_fail_and_release; } - dev->hard_mtu = tmp; - net->mtu = dev->hard_mtu - net->hard_header_len; dev_warn(&intf->dev, "dev can't take %u byte packets (max %u), " "adjusting MTU to %u\n", - dev->hard_mtu, tmp, net->mtu); + dev->hard_mtu, tmp, tmp - net->hard_header_len); + dev->hard_mtu = tmp; + net->mtu = dev->hard_mtu - net->hard_header_len; } /* REVISIT: peripheral "alignment" request is ignored ... */ diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 05630f2f693..b9e002fccbc 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -998,7 +998,7 @@ static unsigned int features[] = { VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, }; -static struct virtio_driver virtio_net = { +static struct virtio_driver virtio_net_driver = { .feature_table = features, .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, @@ -1011,12 +1011,12 @@ static struct virtio_driver virtio_net = { static int __init init(void) { - return register_virtio_driver(&virtio_net); + return register_virtio_driver(&virtio_net_driver); } static void __exit fini(void) { - unregister_virtio_driver(&virtio_net); + unregister_virtio_driver(&virtio_net_driver); } module_init(init); module_exit(fini); diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 16a271787b8..1895d63aad0 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -679,7 +679,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc, return rate; if (rate_table->info[rate].valid_single_stream && - !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)); + !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) return rate; /* This should not happen */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 8701034569f..de4e804bedf 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1157,8 +1157,9 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) } static int dma_tx_fragment(struct b43_dmaring *ring, - struct sk_buff *skb) + struct sk_buff **in_skb) { + struct sk_buff *skb = *in_skb; const struct b43_dma_ops *ops = ring->ops; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u8 *header; @@ -1224,8 +1225,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring, } memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); + memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb)); + bounce_skb->dev = skb->dev; + skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb)); + info = IEEE80211_SKB_CB(bounce_skb); + dev_kfree_skb_any(skb); skb = bounce_skb; + *in_skb = bounce_skb; meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { @@ -1355,7 +1362,11 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) * static, so we don't need to store it per frame. */ ring->queue_prio = skb_get_queue_mapping(skb); - err = dma_tx_fragment(ring, skb); + /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing + * into the skb data or cb now. */ + hdr = NULL; + info = NULL; + err = dma_tx_fragment(ring, &skb); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 92bc8c5f1ca..3fac4efa5ac 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -508,7 +508,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, /* Fill the receive configuration URB and initialise the Rx call back */ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->ep_in), - (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET), + skb->data + IPFIELD_ALIGN_OFFSET, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 71761b34383..73bbec58341 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -815,6 +815,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) mutex_init(&rt2x00dev->csr_mutex); + set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); + /* * Make room for rt2x00_intf inside the per-interface * structure ieee80211_vif. @@ -871,8 +873,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00leds_register(rt2x00dev); rt2x00debug_register(rt2x00dev); - set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - return 0; exit: diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index c64db0ba7f4..c708d0be915 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -362,8 +362,9 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) rt2x00link_reset_tuner(rt2x00dev, false); - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->work, LINK_TUNE_INTERVAL); + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) @@ -469,8 +470,10 @@ static void rt2x00link_tuner(struct work_struct *work) * Increase tuner counter, and reschedule the next link tuner run. */ link->count++; - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->work, LINK_TUNE_INTERVAL); + + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->work, LINK_TUNE_INTERVAL); } void rt2x00link_register(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 501544882c2..f02b48a9059 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -47,6 +47,8 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, (requesttype == USB_VENDOR_REQUEST_IN) ? usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return -ENODEV; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { status = usb_control_msg(usb_dev, pipe, request, requesttype, @@ -60,8 +62,10 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, * -ENODEV: Device has disappeared, no point continuing. * All other errors: Try again. */ - else if (status == -ENODEV) + else if (status == -ENODEV) { + clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); break; + } } ERROR(rt2x00dev, @@ -161,6 +165,9 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, { unsigned int i; + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return -ENODEV; + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00usb_register_read_lock(rt2x00dev, offset, reg); if (!rt2x00_get_field32(*reg, field)) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b8f5ee33445..14e7bb21007 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2389,10 +2389,13 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, /* MSI */ + { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Ovislink */ + { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, /* Ralink */ { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, @@ -2420,6 +2423,8 @@ static struct usb_device_id rt73usb_device_table[] = { /* Planex */ { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, + /* WideTell */ + { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, /* Zcom */ { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, /* ZyXEL */ diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index a1c670fc155..cf8a4a40fdf 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c @@ -210,10 +210,10 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev) /* turn the LED off before exiting */ ieee80211_queue_delayed_work(dev, &priv->led_off, 0); - cancel_delayed_work_sync(&priv->led_off); - cancel_delayed_work_sync(&priv->led_on); rtl8187_unregister_led(&priv->led_rx); rtl8187_unregister_led(&priv->led_tx); + cancel_delayed_work_sync(&priv->led_off); + cancel_delayed_work_sync(&priv->led_on); } #endif /* def CONFIG_RTL8187_LED */ |