summaryrefslogtreecommitdiff
path: root/drivers/net/ixgbe/ixgbe_82598.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-03-25 18:41:20 +0300
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2011-03-25 18:41:20 +0300
commit7bf7e370d5919112c223a269462cd0b546903829 (patch)
tree03ccc715239df14ae168277dbccc9d9cf4d8a2c8 /drivers/net/ixgbe/ixgbe_82598.c
parent68b1a1e786f29c900fa1c516a402e24f0ece622a (diff)
parentd39dd11c3e6a7af5c20bfac40594db36cf270f42 (diff)
downloadlinux-7bf7e370d5919112c223a269462cd0b546903829.tar.xz
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus-1
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6: (9356 commits) [media] rc: update for bitop name changes fs: simplify iget & friends fs: pull inode->i_lock up out of writeback_single_inode fs: rename inode_lock to inode_hash_lock fs: move i_wb_list out from under inode_lock fs: move i_sb_list out from under inode_lock fs: remove inode_lock from iput_final and prune_icache fs: Lock the inode LRU list separately fs: factor inode disposal fs: protect inode->i_state with inode->i_lock lib, arch: add filter argument to show_mem and fix private implementations SLUB: Write to per cpu data when allocating it slub: Fix debugobjects with lockless fastpath autofs4: Do not potentially dereference NULL pointer returned by fget() in autofs_dev_ioctl_setpipefd() autofs4 - remove autofs4_lock autofs4 - fix d_manage() return on rcu-walk autofs4 - fix autofs4_expire_indirect() traversal autofs4 - fix dentry leak in autofs4_expire_direct() autofs4 - reinstate last used update on access vfs - check non-mountpoint dentry might block in __follow_mount_rcu() ... NOTE! This merge commit was created to fix compilation error. The block tree was merged upstream and removed the 'elv_queue_empty()' function which the new 'mtdswap' driver is using. So a simple merge of the mtd tree with upstream does not compile. And the mtd tree has already be published, so re-basing it is not an option. To fix this unfortunate situation, I had to merge upstream into the mtd-2.6.git tree without committing, put the fixup patch on top of this, and then commit this. The result is that we do not have commits which do not compile. In other words, this merge commit "merges" 3 things: the MTD tree, the upstream tree, and the fixup patch.
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_82598.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c102
1 files changed, 69 insertions, 33 deletions
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index d0f1d9d2c416..845c679c8b87 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver
- Copyright(c) 1999 - 2010 Intel Corporation.
+ Copyright(c) 1999 - 2011 Intel Corporation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -158,6 +158,7 @@ static s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
switch (hw->phy.type) {
case ixgbe_phy_tn:
+ phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
phy->ops.check_link = &ixgbe_check_phy_link_tnx;
phy->ops.get_firmware_version =
&ixgbe_get_phy_firmware_version_tnx;
@@ -280,10 +281,22 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
{
enum ixgbe_media_type media_type;
+ /* Detect if there is a copper PHY attached. */
+ switch (hw->phy.type) {
+ case ixgbe_phy_cu_unknown:
+ case ixgbe_phy_tn:
+ case ixgbe_phy_aq:
+ media_type = ixgbe_media_type_copper;
+ goto out;
+ default:
+ break;
+ }
+
/* Media type for I82598 is based on device ID */
switch (hw->device_id) {
case IXGBE_DEV_ID_82598:
case IXGBE_DEV_ID_82598_BX:
+ /* Default device ID is mezzanine card KX/KX4 */
media_type = ixgbe_media_type_backplane;
break;
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
@@ -306,7 +319,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
media_type = ixgbe_media_type_unknown;
break;
}
-
+out:
return media_type;
}
@@ -354,7 +367,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
/* Negotiate the fc mode to use */
ret_val = ixgbe_fc_autoneg(hw);
- if (ret_val)
+ if (ret_val == IXGBE_ERR_FLOW_CONTROL)
goto out;
/* Disable any previous flow control settings */
@@ -372,10 +385,10 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
* 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
- * other: Invalid.
#ifdef CONFIG_DCB
* 4: Priority Flow Control is enabled.
#endif
+ * other: Invalid.
*/
switch (hw->fc.current_mode) {
case ixgbe_fc_none:
@@ -432,9 +445,10 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
reg = (rx_pba_size - hw->fc.low_water) << 6;
if (hw->fc.send_xon)
reg |= IXGBE_FCRTL_XONE;
+
IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
- reg = (rx_pba_size - hw->fc.high_water) << 10;
+ reg = (rx_pba_size - hw->fc.high_water) << 6;
reg |= IXGBE_FCRTH_FCEN;
IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
@@ -627,13 +641,12 @@ out:
return 0;
}
-
/**
* ixgbe_setup_mac_link_82598 - Set MAC link speed
* @hw: pointer to hardware structure
* @speed: new link speed
* @autoneg: true if auto-negotiation enabled
- * @autoneg_wait_to_complete: true if waiting is needed to complete
+ * @autoneg_wait_to_complete: true when waiting for completion is needed
*
* Set the link speed in the AUTOC register and restarts link.
**/
@@ -672,7 +685,8 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
* ixgbe_hw This will write the AUTOC register based on the new
* stored values
*/
- status = ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
+ status = ixgbe_start_mac_link_82598(hw,
+ autoneg_wait_to_complete);
}
return status;
@@ -698,7 +712,6 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
/* Setup the PHY according to input speed */
status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
autoneg_wait_to_complete);
-
/* Set up MAC */
ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
@@ -770,7 +783,6 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
goto no_phy_reset;
-
hw->phy.ops.reset(hw);
}
@@ -779,12 +791,9 @@ no_phy_reset:
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
* access and verify no pending requests before reset
*/
- status = ixgbe_disable_pcie_master(hw);
- if (status != 0) {
- status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
- hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
- }
+ ixgbe_disable_pcie_master(hw);
+mac_reset_top:
/*
* Issue global reset to the MAC. This needs to be a SW reset.
* If link reset is used, it might reset the MAC when mng is using it
@@ -805,6 +814,19 @@ no_phy_reset:
hw_dbg(hw, "Reset polling failed to complete.\n");
}
+ /*
+ * Double resets are required for recovery from certain error
+ * conditions. Between resets, it is necessary to stall to allow time
+ * for any pending HW events to complete. We use 1usec since that is
+ * what is needed for ixgbe_disable_pcie_master(). The second reset
+ * then clears out any effects of those events.
+ */
+ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+ hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ udelay(1);
+ goto mac_reset_top;
+ }
+
msleep(50);
gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
@@ -824,15 +846,15 @@ no_phy_reset:
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
}
+ /* Store the permanent mac address */
+ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
/*
* Store MAC address from RAR0, clear receive address registers, and
* clear the multicast table
*/
hw->mac.ops.init_rx_addrs(hw);
- /* Store the permanent mac address */
- hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
-
reset_hw_out:
if (phy_status)
status = phy_status;
@@ -849,6 +871,13 @@ reset_hw_out:
static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
{
u32 rar_high;
+ u32 rar_entries = hw->mac.num_rar_entries;
+
+ /* Make sure we are using a valid rar index range */
+ if (rar >= rar_entries) {
+ hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
rar_high &= ~IXGBE_RAH_VIND_MASK;
@@ -868,14 +897,17 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
u32 rar_high;
u32 rar_entries = hw->mac.num_rar_entries;
- if (rar < rar_entries) {
- rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
- if (rar_high & IXGBE_RAH_VIND_MASK) {
- rar_high &= ~IXGBE_RAH_VIND_MASK;
- IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
- }
- } else {
+
+ /* Make sure we are using a valid rar index range */
+ if (rar >= rar_entries) {
hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+ return IXGBE_ERR_INVALID_ARGUMENT;
+ }
+
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+ if (rar_high & IXGBE_RAH_VIND_MASK) {
+ rar_high &= ~IXGBE_RAH_VIND_MASK;
+ IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
}
return 0;
@@ -994,13 +1026,12 @@ static s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
}
/**
- * ixgbe_read_i2c_eeprom_82598 - Read 8 bit EEPROM word of an SFP+ module
- * over I2C interface through an intermediate phy.
+ * ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface.
* @hw: pointer to hardware structure
* @byte_offset: EEPROM byte offset to read
* @eeprom_data: value read
*
- * Performs byte read operation to SFP module's EEPROM over I2C interface.
+ * Performs 8 byte read operation to SFP module's EEPROM over I2C interface.
**/
static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data)
@@ -1074,10 +1105,12 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
/* Copper PHY must be checked before AUTOC LMS to determine correct
* physical layer because 10GBase-T PHYs use LMS = KX4/KX */
- if (hw->phy.type == ixgbe_phy_tn ||
- hw->phy.type == ixgbe_phy_cu_unknown) {
- hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
- &ext_ability);
+ switch (hw->phy.type) {
+ case ixgbe_phy_tn:
+ case ixgbe_phy_aq:
+ case ixgbe_phy_cu_unknown:
+ hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE,
+ MDIO_MMD_PMAPMD, &ext_ability);
if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
@@ -1085,6 +1118,8 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
goto out;
+ default:
+ break;
}
switch (autoc & IXGBE_AUTOC_LMS_MASK) {
@@ -1179,13 +1214,14 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.set_vmdq = &ixgbe_set_vmdq_82598,
.clear_vmdq = &ixgbe_clear_vmdq_82598,
.init_rx_addrs = &ixgbe_init_rx_addrs_generic,
- .update_uc_addr_list = &ixgbe_update_uc_addr_list_generic,
.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic,
.enable_mc = &ixgbe_enable_mc_generic,
.disable_mc = &ixgbe_disable_mc_generic,
.clear_vfta = &ixgbe_clear_vfta_82598,
.set_vfta = &ixgbe_set_vfta_82598,
.fc_enable = &ixgbe_fc_enable_82598,
+ .acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
+ .release_swfw_sync = &ixgbe_release_swfw_sync,
};
static struct ixgbe_eeprom_operations eeprom_ops_82598 = {