mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
liquidio: fix use of pf in pass-through mode in a virtual machine
Fix problem when PF is used in pass-through mode in a VM (w/embedded f/w). If host error reading PF num from CN23XX_PCIE_SRIOV_FDL reg, try to retrieve PF num from SLI_PKT(0)_INPUT_CONTROL (initialized by f/w). Signed-off-by: Rick Farrington <ricardo.farrington@cavium.com> Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
6eb15e2130
commit
0c45d7fe12
@ -1150,14 +1150,50 @@ static void cn23xx_get_pcie_qlmport(struct octeon_device *oct)
|
||||
oct->pcie_port);
|
||||
}
|
||||
|
||||
static void cn23xx_get_pf_num(struct octeon_device *oct)
|
||||
static int cn23xx_get_pf_num(struct octeon_device *oct)
|
||||
{
|
||||
u32 fdl_bit = 0;
|
||||
u64 pkt0_in_ctl, d64;
|
||||
int pfnum, mac, trs, ret;
|
||||
|
||||
ret = 0;
|
||||
|
||||
/** Read Function Dependency Link reg to get the function number */
|
||||
pci_read_config_dword(oct->pci_dev, CN23XX_PCIE_SRIOV_FDL, &fdl_bit);
|
||||
oct->pf_num = ((fdl_bit >> CN23XX_PCIE_SRIOV_FDL_BIT_POS) &
|
||||
CN23XX_PCIE_SRIOV_FDL_MASK);
|
||||
if (pci_read_config_dword(oct->pci_dev, CN23XX_PCIE_SRIOV_FDL,
|
||||
&fdl_bit) == 0) {
|
||||
oct->pf_num = ((fdl_bit >> CN23XX_PCIE_SRIOV_FDL_BIT_POS) &
|
||||
CN23XX_PCIE_SRIOV_FDL_MASK);
|
||||
} else {
|
||||
ret = EINVAL;
|
||||
|
||||
/* Under some virtual environments, extended PCI regs are
|
||||
* inaccessible, in which case the above read will have failed.
|
||||
* In this case, read the PF number from the
|
||||
* SLI_PKT0_INPUT_CONTROL reg (written by f/w)
|
||||
*/
|
||||
pkt0_in_ctl = octeon_read_csr64(oct,
|
||||
CN23XX_SLI_IQ_PKT_CONTROL64(0));
|
||||
pfnum = (pkt0_in_ctl >> CN23XX_PKT_INPUT_CTL_PF_NUM_POS) &
|
||||
CN23XX_PKT_INPUT_CTL_PF_NUM_MASK;
|
||||
mac = (octeon_read_csr(oct, CN23XX_SLI_MAC_NUMBER)) & 0xff;
|
||||
|
||||
/* validate PF num by reading RINFO; f/w writes RINFO.trs == 1*/
|
||||
d64 = octeon_read_csr64(oct,
|
||||
CN23XX_SLI_PKT_MAC_RINFO64(mac, pfnum));
|
||||
trs = (int)(d64 >> CN23XX_PKT_MAC_CTL_RINFO_TRS_BIT_POS) & 0xff;
|
||||
if (trs == 1) {
|
||||
dev_err(&oct->pci_dev->dev,
|
||||
"OCTEON: error reading PCI cfg space pfnum, re-read %u\n",
|
||||
pfnum);
|
||||
oct->pf_num = pfnum;
|
||||
ret = 0;
|
||||
} else {
|
||||
dev_err(&oct->pci_dev->dev,
|
||||
"OCTEON: error reading PCI cfg space pfnum; could not ascertain PF number\n");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cn23xx_setup_reg_address(struct octeon_device *oct)
|
||||
@ -1279,7 +1315,8 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct)
|
||||
return 1;
|
||||
}
|
||||
|
||||
cn23xx_get_pf_num(oct);
|
||||
if (cn23xx_get_pf_num(oct) != 0)
|
||||
return 1;
|
||||
|
||||
if (cn23xx_sriov_config(oct)) {
|
||||
octeon_unmap_pci_barx(oct, 0);
|
||||
|
@ -1560,6 +1560,8 @@ static int octeon_chip_specific_setup(struct octeon_device *oct)
|
||||
case OCTEON_CN23XX_PCIID_PF:
|
||||
oct->chip_id = OCTEON_CN23XX_PF_VID;
|
||||
ret = setup_cn23xx_octeon_pf_device(oct);
|
||||
if (ret)
|
||||
break;
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
if (!ret)
|
||||
pci_sriov_set_totalvfs(oct->pci_dev,
|
||||
|
Loading…
Reference in New Issue
Block a user