Commit 14438464 authored by Mark Rustad's avatar Mark Rustad Committed by David S. Miller

ixgbe: Check config reads for removal

Configuration space reads should also be checked for removal. So
add some checks related to config space accesses.

v2:
* Fixed indent
Signed-off-by: default avatarMark Rustad <mark.d.rustad@intel.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0edd2bdf
/******************************************************************************* /*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2013 Intel Corporation. Copyright(c) 1999 - 2014 Intel Corporation.
This program is free software; you can redistribute it and/or modify it This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License, under the terms and conditions of the GNU General Public License,
...@@ -61,6 +61,9 @@ static void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) ...@@ -61,6 +61,9 @@ static void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR); u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
u16 pcie_devctl2; u16 pcie_devctl2;
if (ixgbe_removed(hw->hw_addr))
return;
/* only take action if timeout value is defaulted to 0 */ /* only take action if timeout value is defaulted to 0 */
if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK) if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
goto out; goto out;
...@@ -79,8 +82,9 @@ static void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) ...@@ -79,8 +82,9 @@ static void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
* directly in order to set the completion timeout value for * directly in order to set the completion timeout value for
* 16ms to 55ms * 16ms to 55ms
*/ */
pci_read_config_word(adapter->pdev, pcie_devctl2 = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_CONTROL2);
IXGBE_PCI_DEVICE_CONTROL2, &pcie_devctl2); if (ixgbe_removed(hw->hw_addr))
return;
pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms; pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
pci_write_config_word(adapter->pdev, pci_write_config_word(adapter->pdev,
IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2); IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
......
/******************************************************************************* /*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2013 Intel Corporation. Copyright(c) 1999 - 2014 Intel Corporation.
This program is free software; you can redistribute it and/or modify it This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License, under the terms and conditions of the GNU General Public License,
...@@ -2487,7 +2487,6 @@ static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) ...@@ -2487,7 +2487,6 @@ static u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw)
**/ **/
static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
{ {
struct ixgbe_adapter *adapter = hw->back;
s32 status = 0; s32 status = 0;
u32 i, poll; u32 i, poll;
u16 value; u16 value;
...@@ -2496,7 +2495,8 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) ...@@ -2496,7 +2495,8 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
/* Exit if master requests are blocked */ /* Exit if master requests are blocked */
if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
ixgbe_removed(hw->hw_addr))
goto out; goto out;
/* Poll for master request bit to clear */ /* Poll for master request bit to clear */
...@@ -2524,8 +2524,9 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) ...@@ -2524,8 +2524,9 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
poll = ixgbe_pcie_timeout_poll(hw); poll = ixgbe_pcie_timeout_poll(hw);
for (i = 0; i < poll; i++) { for (i = 0; i < poll; i++) {
udelay(100); udelay(100);
pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS, value = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_DEVICE_STATUS);
&value); if (ixgbe_removed(hw->hw_addr))
goto out;
if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
goto out; goto out;
} }
...@@ -2867,7 +2868,6 @@ s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) ...@@ -2867,7 +2868,6 @@ s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
**/ **/
u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
{ {
struct ixgbe_adapter *adapter = hw->back;
u16 msix_count = 1; u16 msix_count = 1;
u16 max_msix_count; u16 max_msix_count;
u16 pcie_offset; u16 pcie_offset;
...@@ -2886,7 +2886,9 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) ...@@ -2886,7 +2886,9 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
return msix_count; return msix_count;
} }
pci_read_config_word(adapter->pdev, pcie_offset, &msix_count); msix_count = ixgbe_read_pci_cfg_word(hw, pcie_offset);
if (ixgbe_removed(hw->hw_addr))
msix_count = 0;
msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
/* MSI-X count is zero-based in HW */ /* MSI-X count is zero-based in HW */
......
/******************************************************************************* /*******************************************************************************
Intel 10 Gigabit PCI Express Linux driver Intel 10 Gigabit PCI Express Linux driver
Copyright(c) 1999 - 2013 Intel Corporation. Copyright(c) 1999 - 2014 Intel Corporation.
This program is free software; you can redistribute it and/or modify it This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License, under the terms and conditions of the GNU General Public License,
...@@ -128,6 +128,10 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw); ...@@ -128,6 +128,10 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw); s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
#define IXGBE_FAILED_READ_REG 0xffffffffU #define IXGBE_FAILED_READ_REG 0xffffffffU
#define IXGBE_FAILED_READ_CFG_DWORD 0xffffffffU
#define IXGBE_FAILED_READ_CFG_WORD 0xffffU
u16 ixgbe_read_pci_cfg_word(struct ixgbe_hw *hw, u32 reg);
static inline bool ixgbe_removed(void __iomem *addr) static inline bool ixgbe_removed(void __iomem *addr)
{ {
......
...@@ -151,6 +151,8 @@ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver"); ...@@ -151,6 +151,8 @@ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);
static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter, static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,
u32 reg, u16 *value) u32 reg, u16 *value)
{ {
...@@ -169,6 +171,9 @@ static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter, ...@@ -169,6 +171,9 @@ static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,
return -1; return -1;
pcie_capability_read_word(parent_dev, reg, value); pcie_capability_read_word(parent_dev, reg, value);
if (*value == IXGBE_FAILED_READ_CFG_WORD &&
ixgbe_check_cfg_remove(&adapter->hw, parent_dev))
return -1;
return 0; return 0;
} }
...@@ -313,6 +318,48 @@ void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg) ...@@ -313,6 +318,48 @@ void ixgbe_check_remove(struct ixgbe_hw *hw, u32 reg)
ixgbe_remove_adapter(hw); ixgbe_remove_adapter(hw);
} }
static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev)
{
u16 value;
pci_read_config_word(pdev, PCI_VENDOR_ID, &value);
if (value == IXGBE_FAILED_READ_CFG_WORD) {
ixgbe_remove_adapter(hw);
return true;
}
return false;
}
u16 ixgbe_read_pci_cfg_word(struct ixgbe_hw *hw, u32 reg)
{
struct ixgbe_adapter *adapter = hw->back;
u16 value;
if (ixgbe_removed(hw->hw_addr))
return IXGBE_FAILED_READ_CFG_WORD;
pci_read_config_word(adapter->pdev, reg, &value);
if (value == IXGBE_FAILED_READ_CFG_WORD &&
ixgbe_check_cfg_remove(hw, adapter->pdev))
return IXGBE_FAILED_READ_CFG_WORD;
return value;
}
#ifdef CONFIG_PCI_IOV
static u32 ixgbe_read_pci_cfg_dword(struct ixgbe_hw *hw, u32 reg)
{
struct ixgbe_adapter *adapter = hw->back;
u32 value;
if (ixgbe_removed(hw->hw_addr))
return IXGBE_FAILED_READ_CFG_DWORD;
pci_read_config_dword(adapter->pdev, reg, &value);
if (value == IXGBE_FAILED_READ_CFG_DWORD &&
ixgbe_check_cfg_remove(hw, adapter->pdev))
return IXGBE_FAILED_READ_CFG_DWORD;
return value;
}
#endif /* CONFIG_PCI_IOV */
static void ixgbe_service_event_complete(struct ixgbe_adapter *adapter) static void ixgbe_service_event_complete(struct ixgbe_adapter *adapter)
{ {
BUG_ON(!test_bit(__IXGBE_SERVICE_SCHED, &adapter->state)); BUG_ON(!test_bit(__IXGBE_SERVICE_SCHED, &adapter->state));
...@@ -8339,6 +8386,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, ...@@ -8339,6 +8386,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
struct ixgbe_hw *hw = &adapter->hw;
struct pci_dev *bdev, *vfdev; struct pci_dev *bdev, *vfdev;
u32 dw0, dw1, dw2, dw3; u32 dw0, dw1, dw2, dw3;
int vf, pos; int vf, pos;
...@@ -8359,10 +8407,12 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, ...@@ -8359,10 +8407,12 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
if (!pos) if (!pos)
goto skip_bad_vf_detection; goto skip_bad_vf_detection;
pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG, &dw0); dw0 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG);
pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 4, &dw1); dw1 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG + 4);
pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 8, &dw2); dw2 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG + 8);
pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 12, &dw3); dw3 = ixgbe_read_pci_cfg_dword(hw, pos + PCI_ERR_HEADER_LOG + 12);
if (ixgbe_removed(hw->hw_addr))
goto skip_bad_vf_detection;
req_id = dw1 >> 16; req_id = dw1 >> 16;
/* On the 82599 if bit 7 of the requestor ID is set then it's a VF */ /* On the 82599 if bit 7 of the requestor ID is set then it's a VF */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment