]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
pds_core: Clear BARs on reset
authorBrett Creeley <brett.creeley@amd.com>
Mon, 29 Jan 2024 23:40:34 +0000 (15:40 -0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 1 Feb 2024 02:26:59 +0000 (18:26 -0800)
During reset the BARs might be accessed when they are
unmapped. This can cause unexpected issues, so fix it by
clearing the cached BAR values so they are not accessed
until they are re-mapped.

Also, make sure any places that can access the BARs
when they are NULL are prevented.

Fixes: 49ce92fbee0b ("pds_core: add FW update feature to devlink")
Signed-off-by: Brett Creeley <brett.creeley@amd.com>
Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Link: https://lore.kernel.org/r/20240129234035.69802-6-brett.creeley@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/amd/pds_core/adminq.c
drivers/net/ethernet/amd/pds_core/core.c
drivers/net/ethernet/amd/pds_core/dev.c
drivers/net/ethernet/amd/pds_core/devlink.c
drivers/net/ethernet/amd/pds_core/fw.c
drivers/net/ethernet/amd/pds_core/main.c

index 5edff33d56f3603f0133ec96458222823ac2d8ae..ea773cfa0af67bd06d86037bc8208b4111b3bbc5 100644 (file)
@@ -191,10 +191,16 @@ static int __pdsc_adminq_post(struct pdsc *pdsc,
 
        /* Check that the FW is running */
        if (!pdsc_is_fw_running(pdsc)) {
-               u8 fw_status = ioread8(&pdsc->info_regs->fw_status);
-
-               dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n",
-                        __func__, fw_status);
+               if (pdsc->info_regs) {
+                       u8 fw_status =
+                               ioread8(&pdsc->info_regs->fw_status);
+
+                       dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n",
+                                __func__, fw_status);
+               } else {
+                       dev_info(pdsc->dev, "%s: post failed - BARs not setup\n",
+                                __func__);
+               }
                ret = -ENXIO;
 
                goto err_out_unlock;
@@ -266,10 +272,16 @@ int pdsc_adminq_post(struct pdsc *pdsc,
                        break;
 
                if (!pdsc_is_fw_running(pdsc)) {
-                       u8 fw_status = ioread8(&pdsc->info_regs->fw_status);
-
-                       dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n",
-                               __func__, fw_status);
+                       if (pdsc->info_regs) {
+                               u8 fw_status =
+                                       ioread8(&pdsc->info_regs->fw_status);
+
+                               dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n",
+                                       __func__, fw_status);
+                       } else {
+                               dev_dbg(pdsc->dev, "%s: post wait failed - BARs not setup\n",
+                                       __func__);
+                       }
                        err = -ENXIO;
                        break;
                }
index f44333bd1256ec5d886628c6d1b1d7ab78928802..65c8a7072e354800c17b94851cece9ae3a6f3896 100644 (file)
@@ -600,7 +600,13 @@ err_out:
 
 static void pdsc_check_pci_health(struct pdsc *pdsc)
 {
-       u8 fw_status = ioread8(&pdsc->info_regs->fw_status);
+       u8 fw_status;
+
+       /* some sort of teardown already in progress */
+       if (!pdsc->info_regs)
+               return;
+
+       fw_status = ioread8(&pdsc->info_regs->fw_status);
 
        /* is PCI broken? */
        if (fw_status != PDS_RC_BAD_PCI)
index 31940b857e0e501d2d4d220a0ed6a0cfd03098c7..62a38e0a845462b6406d980083339e8514ba421b 100644 (file)
@@ -57,6 +57,9 @@ int pdsc_err_to_errno(enum pds_core_status_code code)
 
 bool pdsc_is_fw_running(struct pdsc *pdsc)
 {
+       if (!pdsc->info_regs)
+               return false;
+
        pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status);
        pdsc->last_fw_time = jiffies;
        pdsc->last_hb = ioread32(&pdsc->info_regs->fw_heartbeat);
@@ -182,13 +185,17 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
 {
        int err;
 
+       if (!pdsc->cmd_regs)
+               return -ENXIO;
+
        memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd));
        pdsc_devcmd_dbell(pdsc);
        err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds);
-       memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
 
        if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq)
                queue_work(pdsc->wq, &pdsc->health_work);
+       else
+               memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp));
 
        return err;
 }
index e9948ea5bbcdbaae713390cca46280e55b548956..54864f27c87a9e526524a023e444e318cc2bc0f7 100644 (file)
@@ -111,7 +111,8 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
 
        mutex_lock(&pdsc->devcmd_lock);
        err = pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout * 2);
-       memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));
+       if (!err)
+               memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));
        mutex_unlock(&pdsc->devcmd_lock);
        if (err && err != -EIO)
                return err;
index 90a811f3878ae974679bc5caba97e18aae04bdfb..fa626719e68d1b206fc9bbe1d038daf51984f19b 100644 (file)
@@ -107,6 +107,9 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw,
 
        dev_info(pdsc->dev, "Installing firmware\n");
 
+       if (!pdsc->cmd_regs)
+               return -ENXIO;
+
        dl = priv_to_devlink(pdsc);
        devlink_flash_update_status_notify(dl, "Preparing to flash",
                                           NULL, 0, 0);
index 5172a5ad8ec6dbae45079cbddaea52d20a58f91d..05fdeb235e5f1610762f44f2da62b569083beb99 100644 (file)
@@ -37,6 +37,11 @@ static void pdsc_unmap_bars(struct pdsc *pdsc)
        struct pdsc_dev_bar *bars = pdsc->bars;
        unsigned int i;
 
+       pdsc->info_regs = NULL;
+       pdsc->cmd_regs = NULL;
+       pdsc->intr_status = NULL;
+       pdsc->intr_ctrl = NULL;
+
        for (i = 0; i < PDS_CORE_BARS_MAX; i++) {
                if (bars[i].vaddr)
                        pci_iounmap(pdsc->pdev, bars[i].vaddr);