diff options
| -rw-r--r-- | drivers/staging/rdma/hfi1/chip.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/staging/rdma/hfi1/chip.c b/drivers/staging/rdma/hfi1/chip.c index fe73ebf077e4..7799652773d5 100644 --- a/drivers/staging/rdma/hfi1/chip.c +++ b/drivers/staging/rdma/hfi1/chip.c | |||
| @@ -13943,6 +13943,50 @@ static int obtain_boardname(struct hfi1_devdata *dd) | |||
| 13943 | return 0; | 13943 | return 0; |
| 13944 | } | 13944 | } |
| 13945 | 13945 | ||
| 13946 | /* | ||
| 13947 | * Check the interrupt registers to make sure that they are mapped correctly. | ||
| 13948 | * It is intended to help user identify any mismapping by VMM when the driver | ||
| 13949 | * is running in a VM. This function should only be called before interrupt | ||
| 13950 | * is set up properly. | ||
| 13951 | * | ||
| 13952 | * Return 0 on success, -EINVAL on failure. | ||
| 13953 | */ | ||
| 13954 | static int check_int_registers(struct hfi1_devdata *dd) | ||
| 13955 | { | ||
| 13956 | u64 reg; | ||
| 13957 | u64 all_bits = ~(u64)0; | ||
| 13958 | u64 mask; | ||
| 13959 | |||
| 13960 | /* Clear CceIntMask[0] to avoid raising any interrupts */ | ||
| 13961 | mask = read_csr(dd, CCE_INT_MASK); | ||
| 13962 | write_csr(dd, CCE_INT_MASK, 0ull); | ||
| 13963 | reg = read_csr(dd, CCE_INT_MASK); | ||
| 13964 | if (reg) | ||
| 13965 | goto err_exit; | ||
| 13966 | |||
| 13967 | /* Clear all interrupt status bits */ | ||
| 13968 | write_csr(dd, CCE_INT_CLEAR, all_bits); | ||
| 13969 | reg = read_csr(dd, CCE_INT_STATUS); | ||
| 13970 | if (reg) | ||
| 13971 | goto err_exit; | ||
| 13972 | |||
| 13973 | /* Set all interrupt status bits */ | ||
| 13974 | write_csr(dd, CCE_INT_FORCE, all_bits); | ||
| 13975 | reg = read_csr(dd, CCE_INT_STATUS); | ||
| 13976 | if (reg != all_bits) | ||
| 13977 | goto err_exit; | ||
| 13978 | |||
| 13979 | /* Restore the interrupt mask */ | ||
| 13980 | write_csr(dd, CCE_INT_CLEAR, all_bits); | ||
| 13981 | write_csr(dd, CCE_INT_MASK, mask); | ||
| 13982 | |||
| 13983 | return 0; | ||
| 13984 | err_exit: | ||
| 13985 | write_csr(dd, CCE_INT_MASK, mask); | ||
| 13986 | dd_dev_err(dd, "Interrupt registers not properly mapped by VMM\n"); | ||
| 13987 | return -EINVAL; | ||
| 13988 | } | ||
| 13989 | |||
| 13946 | /** | 13990 | /** |
| 13947 | * Allocate and initialize the device structure for the hfi. | 13991 | * Allocate and initialize the device structure for the hfi. |
| 13948 | * @dev: the pci_dev for hfi1_ib device | 13992 | * @dev: the pci_dev for hfi1_ib device |
| @@ -13967,6 +14011,7 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev, | |||
| 13967 | "RTL FPGA emulation", | 14011 | "RTL FPGA emulation", |
| 13968 | "Functional simulator" | 14012 | "Functional simulator" |
| 13969 | }; | 14013 | }; |
| 14014 | struct pci_dev *parent = pdev->bus->self; | ||
| 13970 | 14015 | ||
| 13971 | dd = hfi1_alloc_devdata(pdev, NUM_IB_PORTS * | 14016 | dd = hfi1_alloc_devdata(pdev, NUM_IB_PORTS * |
| 13972 | sizeof(struct hfi1_pportdata)); | 14017 | sizeof(struct hfi1_pportdata)); |
| @@ -14046,6 +14091,17 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev, | |||
| 14046 | & CCE_REVISION_CHIP_REV_MINOR_MASK; | 14091 | & CCE_REVISION_CHIP_REV_MINOR_MASK; |
| 14047 | 14092 | ||
| 14048 | /* | 14093 | /* |
| 14094 | * Check interrupt registers mapping if the driver has no access to | ||
| 14095 | * the upstream component. In this case, it is likely that the driver | ||
| 14096 | * is running in a VM. | ||
| 14097 | */ | ||
| 14098 | if (!parent) { | ||
| 14099 | ret = check_int_registers(dd); | ||
| 14100 | if (ret) | ||
| 14101 | goto bail_cleanup; | ||
| 14102 | } | ||
| 14103 | |||
| 14104 | /* | ||
| 14049 | * obtain the hardware ID - NOT related to unit, which is a | 14105 | * obtain the hardware ID - NOT related to unit, which is a |
| 14050 | * software enumeration | 14106 | * software enumeration |
| 14051 | */ | 14107 | */ |
