diff --git a/drivers/crypto/ccp/hygon/psp-dev.c b/drivers/crypto/ccp/hygon/psp-dev.c index 92c6500d2dfecbaa9030b21e0c9215393877cd57..85c7f09999a7c63bca15c559a003591742d958c2 100644 --- a/drivers/crypto/ccp/hygon/psp-dev.c +++ b/drivers/crypto/ccp/hygon/psp-dev.c @@ -22,6 +22,8 @@ /* Function and variable pointers for hooks */ struct hygon_psp_hooks_table hygon_psp_hooks; +unsigned int psp_int_rcvd; +wait_queue_head_t psp_int_queue; struct kmem_cache *vpsp_cmd_ctx_slab; static struct workqueue_struct *vpsp_wq; @@ -350,65 +352,69 @@ int fixup_hygon_psp_caps(struct psp_device *psp) return 0; } +static int psp_wait_cmd_ioc(struct psp_device *psp, + unsigned int *reg, unsigned int timeout) +{ + int ret; + + ret = wait_event_timeout(psp_int_queue, + psp_int_rcvd, timeout * HZ); + if (!ret) + return -ETIMEDOUT; + + *reg = ioread32(psp->io_regs + psp->vdata->sev->cmdresp_reg); + + return 0; +} + static int __psp_do_cmd_locked(int cmd, void *data, int *psp_ret) { struct psp_device *psp = psp_master; - struct sev_device *sev; unsigned int phys_lsb, phys_msb; unsigned int reg, ret = 0; - if (!psp || !psp->sev_data || !hygon_psp_hooks.sev_dev_hooks_installed) + if (!psp || !hygon_psp_hooks.sev_dev_hooks_installed) return -ENODEV; if (*hygon_psp_hooks.psp_dead) return -EBUSY; - sev = psp->sev_data; - /* Get the physical address of the command buffer */ phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0; phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0; - dev_dbg(sev->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n", - cmd, phys_msb, phys_lsb, *hygon_psp_hooks.psp_timeout); - - print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data, - hygon_psp_hooks.sev_cmd_buffer_len(cmd), false); + dev_dbg(psp->dev, "psp command id %#x buffer 0x%08x%08x timeout %us\n", + cmd, phys_msb, phys_lsb, *hygon_psp_hooks.psp_cmd_timeout); - iowrite32(phys_lsb, sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg); - iowrite32(phys_msb, sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg); + iowrite32(phys_lsb, psp->io_regs + psp->vdata->sev->cmdbuff_addr_lo_reg); + iowrite32(phys_msb, psp->io_regs + psp->vdata->sev->cmdbuff_addr_hi_reg); - sev->int_rcvd = 0; + psp_int_rcvd = 0; reg = FIELD_PREP(SEV_CMDRESP_CMD, cmd) | SEV_CMDRESP_IOC; - iowrite32(reg, sev->io_regs + sev->vdata->cmdresp_reg); + iowrite32(reg, psp->io_regs + psp->vdata->sev->cmdresp_reg); /* wait for command completion */ - ret = hygon_psp_hooks.sev_wait_cmd_ioc(sev, ®, *hygon_psp_hooks.psp_timeout); + ret = psp_wait_cmd_ioc(psp, ®, *hygon_psp_hooks.psp_cmd_timeout); if (ret) { if (psp_ret) *psp_ret = 0; - dev_err(sev->dev, "sev command %#x timed out, disabling PSP\n", cmd); + dev_err(psp->dev, "psp command %#x timed out, disabling PSP\n", cmd); *hygon_psp_hooks.psp_dead = true; return ret; } - *hygon_psp_hooks.psp_timeout = *hygon_psp_hooks.psp_cmd_timeout; - if (psp_ret) *psp_ret = FIELD_GET(PSP_CMDRESP_STS, reg); if (FIELD_GET(PSP_CMDRESP_STS, reg)) { - dev_dbg(sev->dev, "sev command %#x failed (%#010lx)\n", + dev_dbg(psp->dev, "psp command %#x failed (%#010lx)\n", cmd, FIELD_GET(PSP_CMDRESP_STS, reg)); ret = -EIO; } - print_hex_dump_debug("(out): ", DUMP_PREFIX_OFFSET, 16, 2, data, - hygon_psp_hooks.sev_cmd_buffer_len(cmd), false); - return ret; } @@ -508,8 +514,12 @@ static irqreturn_t psp_irq_handler_hygon(int irq, void *data) if (vpsp_in_ringbuffer_mode) { queue_work(vpsp_wq, &vpsp_work); } else { - sev->int_rcvd = 1; - wake_up(&sev->int_queue); + psp_int_rcvd = 1; + wake_up(&psp_int_queue); + if (sev != NULL) { + sev->int_rcvd = 1; + wake_up(&sev->int_queue); + } } } } diff --git a/drivers/crypto/ccp/hygon/psp-dev.h b/drivers/crypto/ccp/hygon/psp-dev.h index 1d180e46b1a3ac8c2a8b0f4ac6574f542fbf16f4..8a00a53273c282907eb5e30fa9097b23e36d916d 100644 --- a/drivers/crypto/ccp/hygon/psp-dev.h +++ b/drivers/crypto/ccp/hygon/psp-dev.h @@ -45,6 +45,8 @@ extern struct hygon_psp_hooks_table { long (*sev_ioctl)(struct file *file, unsigned int ioctl, unsigned long arg); } hygon_psp_hooks; +extern struct wait_queue_head psp_int_queue; + #define PSP_MUTEX_TIMEOUT 600000 struct psp_mutex { uint64_t locked; diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c index ccb605bf861895115f461e888e295123cc9c921a..cfe6f9654d8b8dcec322fe187d09d906ea6edb5c 100644 --- a/drivers/crypto/ccp/psp-dev.c +++ b/drivers/crypto/ccp/psp-dev.c @@ -216,6 +216,9 @@ int psp_dev_init(struct sp_device *sp) if (ret) goto e_irq; + if (is_vendor_hygon()) + init_waitqueue_head(&psp_int_queue); + /** * hygon_psp_additional_setup() needs to wait for * sev_dev_install_hooks() to complete before it can be called. diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index 97797c34725d844bb8a47cba1b6b3fef41e99a44..3dd1c796c658ae7a4eb9c3371e77434a0bcaccf0 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -586,6 +586,8 @@ static const struct pci_device_id sp_pci_table[] = { { PCI_VDEVICE(HYGON, 0x1486), (kernel_ulong_t)&hygon_dev_vdata[2] }, { PCI_VDEVICE(HYGON, 0x14b8), (kernel_ulong_t)&hygon_dev_vdata[1] }, { PCI_VDEVICE(HYGON, 0x14a6), (kernel_ulong_t)&hygon_dev_vdata[2] }, + { PCI_VDEVICE(HYGON, 0x14d8), (kernel_ulong_t)&hygon_dev_vdata[1] }, + { PCI_VDEVICE(HYGON, 0x14c6), (kernel_ulong_t)&hygon_dev_vdata[2] }, /* Last entry must be zero */ { 0, } };