|
@@ -38,6 +38,17 @@ static DEFINE_MUTEX(sev_cmd_mutex);
|
|
static struct sev_misc_dev *misc_dev;
|
|
static struct sev_misc_dev *misc_dev;
|
|
static struct psp_device *psp_master;
|
|
static struct psp_device *psp_master;
|
|
|
|
|
|
|
|
+static int psp_cmd_timeout = 100;
|
|
|
|
+module_param(psp_cmd_timeout, int, 0644);
|
|
|
|
+MODULE_PARM_DESC(psp_cmd_timeout, " default timeout value, in seconds, for PSP commands");
|
|
|
|
+
|
|
|
|
+static int psp_probe_timeout = 5;
|
|
|
|
+module_param(psp_probe_timeout, int, 0644);
|
|
|
|
+MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe");
|
|
|
|
+
|
|
|
|
+static bool psp_dead;
|
|
|
|
+static int psp_timeout;
|
|
|
|
+
|
|
static struct psp_device *psp_alloc_struct(struct sp_device *sp)
|
|
static struct psp_device *psp_alloc_struct(struct sp_device *sp)
|
|
{
|
|
{
|
|
struct device *dev = sp->dev;
|
|
struct device *dev = sp->dev;
|
|
@@ -82,10 +93,19 @@ done:
|
|
return IRQ_HANDLED;
|
|
return IRQ_HANDLED;
|
|
}
|
|
}
|
|
|
|
|
|
-static void sev_wait_cmd_ioc(struct psp_device *psp, unsigned int *reg)
|
|
|
|
|
|
+static int sev_wait_cmd_ioc(struct psp_device *psp,
|
|
|
|
+ unsigned int *reg, unsigned int timeout)
|
|
{
|
|
{
|
|
- wait_event(psp->sev_int_queue, psp->sev_int_rcvd);
|
|
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ ret = wait_event_timeout(psp->sev_int_queue,
|
|
|
|
+ psp->sev_int_rcvd, timeout * HZ);
|
|
|
|
+ if (!ret)
|
|
|
|
+ return -ETIMEDOUT;
|
|
|
|
+
|
|
*reg = ioread32(psp->io_regs + psp->vdata->cmdresp_reg);
|
|
*reg = ioread32(psp->io_regs + psp->vdata->cmdresp_reg);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static int sev_cmd_buffer_len(int cmd)
|
|
static int sev_cmd_buffer_len(int cmd)
|
|
@@ -133,12 +153,15 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
|
|
if (!psp)
|
|
if (!psp)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
+ if (psp_dead)
|
|
|
|
+ return -EBUSY;
|
|
|
|
+
|
|
/* Get the physical address of the command buffer */
|
|
/* Get the physical address of the command buffer */
|
|
phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0;
|
|
phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0;
|
|
phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0;
|
|
phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0;
|
|
|
|
|
|
- dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x\n",
|
|
|
|
- cmd, phys_msb, phys_lsb);
|
|
|
|
|
|
+ dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n",
|
|
|
|
+ cmd, phys_msb, phys_lsb, psp_timeout);
|
|
|
|
|
|
print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
|
|
print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
|
|
sev_cmd_buffer_len(cmd), false);
|
|
sev_cmd_buffer_len(cmd), false);
|
|
@@ -154,7 +177,18 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
|
|
iowrite32(reg, psp->io_regs + psp->vdata->cmdresp_reg);
|
|
iowrite32(reg, psp->io_regs + psp->vdata->cmdresp_reg);
|
|
|
|
|
|
/* wait for command completion */
|
|
/* wait for command completion */
|
|
- sev_wait_cmd_ioc(psp, ®);
|
|
|
|
|
|
+ ret = sev_wait_cmd_ioc(psp, ®, psp_timeout);
|
|
|
|
+ if (ret) {
|
|
|
|
+ if (psp_ret)
|
|
|
|
+ *psp_ret = 0;
|
|
|
|
+
|
|
|
|
+ dev_err(psp->dev, "sev command %#x timed out, disabling PSP \n", cmd);
|
|
|
|
+ psp_dead = true;
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ psp_timeout = psp_cmd_timeout;
|
|
|
|
|
|
if (psp_ret)
|
|
if (psp_ret)
|
|
*psp_ret = reg & PSP_CMDRESP_ERR_MASK;
|
|
*psp_ret = reg & PSP_CMDRESP_ERR_MASK;
|
|
@@ -888,6 +922,8 @@ void psp_pci_init(void)
|
|
|
|
|
|
psp_master = sp->psp_data;
|
|
psp_master = sp->psp_data;
|
|
|
|
|
|
|
|
+ psp_timeout = psp_probe_timeout;
|
|
|
|
+
|
|
if (sev_get_api_version())
|
|
if (sev_get_api_version())
|
|
goto err;
|
|
goto err;
|
|
|
|
|