diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_common.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_common.c | 438 |
1 files changed, 173 insertions, 265 deletions
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index ebbda7d..a7fb2e0 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.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, @@ -46,10 +46,7 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_release_eeprom(struct ixgbe_hw *hw); -static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); -static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); -static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num); /** @@ -454,8 +451,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests */ - if (ixgbe_disable_pcie_master(hw) != 0) - hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); + ixgbe_disable_pcie_master(hw); return 0; } @@ -603,7 +599,6 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) ixgbe_shift_out_eeprom_bits(hw, data, 16); ixgbe_standby_eeprom(hw); - msleep(hw->eeprom.semaphore_delay); /* Done with writing - release the EEPROM */ ixgbe_release_eeprom(hw); } @@ -747,10 +742,10 @@ s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) { s32 status = 0; - u32 eec = 0; + u32 eec; u32 i; - if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0) + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0) status = IXGBE_ERR_SWFW_SYNC; if (status == 0) { @@ -773,18 +768,18 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); hw_dbg(hw, "Could not acquire EEPROM grant\n"); - ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); status = IXGBE_ERR_EEPROM; } - } - /* Setup EEPROM for Read/Write */ - if (status == 0) { - /* Clear CS and SK */ - eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); - IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); - IXGBE_WRITE_FLUSH(hw); - udelay(1); + /* Setup EEPROM for Read/Write */ + if (status == 0) { + /* Clear CS and SK */ + eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); + IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); + IXGBE_WRITE_FLUSH(hw); + udelay(1); + } } return status; } @@ -798,13 +793,10 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_EEPROM; - u32 timeout; + u32 timeout = 2000; u32 i; u32 swsm; - /* Set timeout value based on size of EEPROM */ - timeout = hw->eeprom.word_size + 1; - /* Get SMBI software semaphore between device drivers first */ for (i = 0; i < timeout; i++) { /* @@ -816,7 +808,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) status = 0; break; } - msleep(1); + udelay(50); } /* Now get the semaphore between SW/FW through the SWESMBI bit */ @@ -844,11 +836,14 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) * was not granted because we don't have access to the EEPROM */ if (i >= timeout) { - hw_dbg(hw, "Driver can't access the Eeprom - Semaphore " + hw_dbg(hw, "SWESMBI Software EEPROM semaphore " "not granted.\n"); ixgbe_release_eeprom_semaphore(hw); status = IXGBE_ERR_EEPROM; } + } else { + hw_dbg(hw, "Software semaphore SMBI between device drivers " + "not granted.\n"); } return status; @@ -1081,10 +1076,13 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + + /* Delay before attempt to obtain semaphore again to allow FW access */ + msleep(hw->eeprom.semaphore_delay); } /** - * ixgbe_calc_eeprom_checksum - Calculates and returns the checksum + * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum * @hw: pointer to hardware structure **/ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) @@ -1190,7 +1188,7 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) if (status == 0) { checksum = hw->eeprom.ops.calc_checksum(hw); status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, - checksum); + checksum); } else { hw_dbg(hw, "EEPROM read failed\n"); } @@ -1238,37 +1236,37 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 rar_low, rar_high; u32 rar_entries = hw->mac.num_rar_entries; + /* Make sure we are using a valid rar index range */ + if (index >= rar_entries) { + hw_dbg(hw, "RAR index %d is out of range.\n", index); + return IXGBE_ERR_INVALID_ARGUMENT; + } + /* setup VMDq pool selection before this RAR gets enabled */ hw->mac.ops.set_vmdq(hw, index, vmdq); - /* Make sure we are using a valid rar index range */ - if (index < rar_entries) { - /* - * HW expects these in little endian so we reverse the byte - * order from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | - ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | - ((u32)addr[3] << 24)); - /* - * Some parts put the VMDq setting in the extra RAH bits, - * so save everything except the lower 16 bits that hold part - * of the address and the address valid bit. - */ - rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); - rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); - rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); + /* + * HW expects these in little endian so we reverse the byte + * order from network order (big endian) to little endian + */ + rar_low = ((u32)addr[0] | + ((u32)addr[1] << 8) | + ((u32)addr[2] << 16) | + ((u32)addr[3] << 24)); + /* + * Some parts put the VMDq setting in the extra RAH bits, + * so save everything except the lower 16 bits that hold part + * of the address and the address valid bit. + */ + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); + rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); + rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); - if (enable_addr != 0) - rar_high |= IXGBE_RAH_AV; + if (enable_addr != 0) + rar_high |= IXGBE_RAH_AV; - IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); - IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); - } else { - hw_dbg(hw, "RAR index %d is out of range.\n", index); - return IXGBE_ERR_RAR_INDEX; - } + IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); + IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); return 0; } @@ -1286,58 +1284,26 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ - if (index < rar_entries) { - /* - * Some parts put the VMDq setting in the extra RAH bits, - * so save everything except the lower 16 bits that hold part - * of the address and the address valid bit. - */ - rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); - rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); - - IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); - IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); - } else { + if (index >= rar_entries) { hw_dbg(hw, "RAR index %d is out of range.\n", index); - return IXGBE_ERR_RAR_INDEX; + return IXGBE_ERR_INVALID_ARGUMENT; } - /* clear VMDq pool/queue selection for this RAR */ - hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); - - return 0; -} - -/** - * ixgbe_enable_rar - Enable Rx address register - * @hw: pointer to hardware structure - * @index: index into the RAR table - * - * Enables the select receive address register. - **/ -static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index) -{ - u32 rar_high; - + /* + * Some parts put the VMDq setting in the extra RAH bits, + * so save everything except the lower 16 bits that hold part + * of the address and the address valid bit. + */ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); - rar_high |= IXGBE_RAH_AV; + rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); + + IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); -} -/** - * ixgbe_disable_rar - Disable Rx address register - * @hw: pointer to hardware structure - * @index: index into the RAR table - * - * Disables the select receive address register. - **/ -static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index) -{ - u32 rar_high; + /* clear VMDq pool/queue selection for this RAR */ + hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); - rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); - rar_high &= (~IXGBE_RAH_AV); - IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + return 0; } /** @@ -1386,7 +1352,6 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) } /* Clear the MTA */ - hw->addr_ctrl.mc_addr_in_rar_count = 0; hw->addr_ctrl.mta_in_use = 0; IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); @@ -1401,105 +1366,6 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) } /** - * ixgbe_add_uc_addr - Adds a secondary unicast address. - * @hw: pointer to hardware structure - * @addr: new address - * - * Adds it to unused receive address register or goes into promiscuous mode. - **/ -static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) -{ - u32 rar_entries = hw->mac.num_rar_entries; - u32 rar; - - hw_dbg(hw, " UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - - /* - * Place this address in the RAR if there is room, - * else put the controller into promiscuous mode - */ - if (hw->addr_ctrl.rar_used_count < rar_entries) { - rar = hw->addr_ctrl.rar_used_count - - hw->addr_ctrl.mc_addr_in_rar_count; - hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); - hw_dbg(hw, "Added a secondary address to RAR[%d]\n", rar); - hw->addr_ctrl.rar_used_count++; - } else { - hw->addr_ctrl.overflow_promisc++; - } - - hw_dbg(hw, "ixgbe_add_uc_addr Complete\n"); -} - -/** - * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses - * @hw: pointer to hardware structure - * @netdev: pointer to net device structure - * - * The given list replaces any existing list. Clears the secondary addrs from - * receive address registers. Uses unused receive address registers for the - * first secondary addresses, and falls back to promiscuous mode as needed. - * - * Drivers using secondary unicast addresses must set user_set_promisc when - * manually putting the device into promiscuous mode. - **/ -s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, - struct net_device *netdev) -{ - u32 i; - u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; - u32 uc_addr_in_use; - u32 fctrl; - struct netdev_hw_addr *ha; - - /* - * Clear accounting of old secondary address list, - * don't count RAR[0] - */ - uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; - hw->addr_ctrl.rar_used_count -= uc_addr_in_use; - hw->addr_ctrl.overflow_promisc = 0; - - /* Zero out the other receive addresses */ - hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use + 1); - for (i = 0; i < uc_addr_in_use; i++) { - IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); - IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); - } - - /* Add the new addresses */ - netdev_for_each_uc_addr(ha, netdev) { - hw_dbg(hw, " Adding the secondary addresses:\n"); - ixgbe_add_uc_addr(hw, ha->addr, 0); - } - - if (hw->addr_ctrl.overflow_promisc) { - /* enable promisc if not already in overflow or set by user */ - if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { - hw_dbg(hw, " Entering address overflow promisc mode\n"); - fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); - fctrl |= IXGBE_FCTRL_UPE; - IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); - hw->addr_ctrl.uc_set_promisc = true; - } - } else { - /* only disable if set by overflow, not by user */ - if ((old_promisc_setting && hw->addr_ctrl.uc_set_promisc) && - !(hw->addr_ctrl.user_set_promisc)) { - hw_dbg(hw, " Leaving address overflow promisc mode\n"); - fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); - fctrl &= ~IXGBE_FCTRL_UPE; - IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); - hw->addr_ctrl.uc_set_promisc = false; - } - } - - hw_dbg(hw, "ixgbe_update_uc_addr_list_generic Complete\n"); - return 0; -} - -/** * ixgbe_mta_vector - Determines bit-vector in multicast table to set * @hw: pointer to hardware structure * @mc_addr: the multicast address @@ -1550,7 +1416,6 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) u32 vector; u32 vector_bit; u32 vector_reg; - u32 mta_reg; hw->addr_ctrl.mta_in_use++; @@ -1568,9 +1433,7 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) */ vector_reg = (vector >> 5) & 0x7F; vector_bit = vector & 0x1F; - mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); - mta_reg |= (1 << vector_bit); - IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); + hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); } /** @@ -1596,18 +1459,21 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, hw->addr_ctrl.num_mc_addrs = netdev_mc_count(netdev); hw->addr_ctrl.mta_in_use = 0; - /* Clear the MTA */ + /* Clear mta_shadow */ hw_dbg(hw, " Clearing MTA\n"); - for (i = 0; i < hw->mac.mcft_size; i++) - IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); + memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - /* Add the new addresses */ + /* Update mta shadow */ netdev_for_each_mc_addr(ha, netdev) { hw_dbg(hw, " Adding the multicast addresses:\n"); ixgbe_set_mta(hw, ha->addr); } /* Enable mta */ + for (i = 0; i < hw->mac.mcft_size; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, + hw->mac.mta_shadow[i]); + if (hw->addr_ctrl.mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); @@ -1624,15 +1490,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, **/ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) { - u32 i; - u32 rar_entries = hw->mac.num_rar_entries; struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; - if (a->mc_addr_in_rar_count > 0) - for (i = (rar_entries - a->mc_addr_in_rar_count); - i < rar_entries; i++) - ixgbe_enable_rar(hw, i); - if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); @@ -1648,15 +1507,8 @@ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) **/ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) { - u32 i; - u32 rar_entries = hw->mac.num_rar_entries; struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; - if (a->mc_addr_in_rar_count > 0) - for (i = (rar_entries - a->mc_addr_in_rar_count); - i < rar_entries; i++) - ixgbe_disable_rar(hw, i); - if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); @@ -1703,7 +1555,9 @@ s32 ixgbe_fc_enable_generic(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. +#ifdef CONFIG_DCB * 4: Priority Flow Control is enabled. +#endif * other: Invalid. */ switch (hw->fc.current_mode) { @@ -2159,10 +2013,16 @@ out: **/ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) { + struct ixgbe_adapter *adapter = hw->back; u32 i; u32 reg_val; u32 number_of_queues; - s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + s32 status = 0; + u16 dev_status = 0; + + /* Just jump out if bus mastering is already disabled */ + if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) + goto out; /* Disable the receive unit by stopping each queue */ number_of_queues = hw->mac.max_rx_queues; @@ -2179,13 +2039,43 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val); for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { - if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) { - status = 0; + if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) + goto check_device_status; + udelay(100); + } + + hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n"); + status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + + /* + * Before proceeding, make sure that the PCIe block does not have + * transactions pending. + */ +check_device_status: + for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { + pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS, + &dev_status); + if (!(dev_status & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) break; - } udelay(100); } + if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT) + hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n"); + else + goto out; + + /* + * Two consecutive resets are required via CTRL.RST per datasheet + * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine + * of this need. The first reset prevents new master requests from + * being issued by our device. We then must wait 1usec for any + * remaining completions from the PCIe bus to trickle in, and then reset + * again to clear out any effects they may have had on our device. + */ + hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + +out: return status; } @@ -2206,6 +2096,10 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) s32 timeout = 200; while (timeout) { + /* + * SW EEPROM semaphore bit is used for access to all + * SW_FW_SYNC/GSSR bits (not just EEPROM) + */ if (ixgbe_get_eeprom_semaphore(hw)) return IXGBE_ERR_SWFW_SYNC; @@ -2223,7 +2117,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) } if (!timeout) { - hw_dbg(hw, "Driver can't access resource, GSSR timeout.\n"); + hw_dbg(hw, "Driver can't access resource, SW_FW_SYNC timeout.\n"); return IXGBE_ERR_SWFW_SYNC; } @@ -2427,37 +2321,38 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) u32 mpsar_lo, mpsar_hi; u32 rar_entries = hw->mac.num_rar_entries; - if (rar < rar_entries) { - mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); - mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); + /* 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; + } - if (!mpsar_lo && !mpsar_hi) - goto done; + mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); + mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); - if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { - if (mpsar_lo) { - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); - mpsar_lo = 0; - } - if (mpsar_hi) { - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); - mpsar_hi = 0; - } - } else if (vmdq < 32) { - mpsar_lo &= ~(1 << vmdq); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); - } else { - mpsar_hi &= ~(1 << (vmdq - 32)); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); - } + if (!mpsar_lo && !mpsar_hi) + goto done; - /* was that the last pool using this rar? */ - if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) - hw->mac.ops.clear_rar(hw, rar); + if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { + if (mpsar_lo) { + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); + mpsar_lo = 0; + } + if (mpsar_hi) { + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); + mpsar_hi = 0; + } + } else if (vmdq < 32) { + mpsar_lo &= ~(1 << vmdq); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); } else { - hw_dbg(hw, "RAR index %d is out of range.\n", rar); + mpsar_hi &= ~(1 << (vmdq - 32)); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); } + /* was that the last pool using this rar? */ + if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) + hw->mac.ops.clear_rar(hw, rar); done: return 0; } @@ -2473,18 +2368,20 @@ s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) u32 mpsar; u32 rar_entries = hw->mac.num_rar_entries; - if (rar < rar_entries) { - if (vmdq < 32) { - mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); - mpsar |= 1 << vmdq; - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); - } else { - mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); - mpsar |= 1 << (vmdq - 32); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); - } - } 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; + } + + if (vmdq < 32) { + mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); + mpsar |= 1 << vmdq; + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); + } else { + mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); + mpsar |= 1 << (vmdq - 32); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); } return 0; } @@ -2497,7 +2394,6 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) { int i; - for (i = 0; i < 128; i++) IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); @@ -2726,12 +2622,21 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) * Reads the links register to determine if link is up and the current speed **/ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete) + bool *link_up, bool link_up_wait_to_complete) { - u32 links_reg; + u32 links_reg, links_orig; u32 i; + /* clear the old state */ + links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + + if (links_orig != links_reg) { + hw_dbg(hw, "LINKS changed from %08X to %08X\n", + links_orig, links_reg); + } + if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if (links_reg & IXGBE_LINKS_UP) { @@ -2754,10 +2659,13 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, IXGBE_LINKS_SPEED_10G_82599) *speed = IXGBE_LINK_SPEED_10GB_FULL; else if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_1G_82599) + IXGBE_LINKS_SPEED_1G_82599) *speed = IXGBE_LINK_SPEED_1GB_FULL; - else + else if ((links_reg & IXGBE_LINKS_SPEED_82599) == + IXGBE_LINKS_SPEED_100_82599) *speed = IXGBE_LINK_SPEED_100_FULL; + else + *speed = IXGBE_LINK_SPEED_UNKNOWN; /* if link is down, zero out the current_mode */ if (*link_up == false) { |