Commit e96094c1 authored by Brett Creeley's avatar Brett Creeley Committed by Jakub Kicinski
Browse files

pds_core: Clear BARs on reset



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: 49ce92fb ("pds_core: add FW update feature to devlink")
Signed-off-by: default avatarBrett Creeley <brett.creeley@amd.com>
Reviewed-by: default avatarShannon Nelson <shannon.nelson@amd.com>
Reviewed-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
Link: https://lore.kernel.org/r/20240129234035.69802-6-brett.creeley@amd.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 7e82a874
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -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);
		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);
			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;
		}
+7 −1
Original line number Diff line number Diff line
@@ -600,7 +600,13 @@ void pdsc_fw_up(struct pdsc *pdsc)

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)
+8 −1
Original line number Diff line number Diff line
@@ -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;
}
+2 −1
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ 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);
	if (!err)
		memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list));
	mutex_unlock(&pdsc->devcmd_lock);
	if (err && err != -EIO)
+3 −0
Original line number Diff line number Diff line
@@ -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);
Loading