summaryrefslogtreecommitdiffstats
path: root/drivers/cxl/pci.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2023-09-29 21:44:20 +0200
committerDan Williams <dan.j.williams@intel.com>2023-09-30 00:43:34 +0200
commite30a106558e7d1e06d1fcfd12466dc646673d03d (patch)
tree0f74ed85e69eff71aca3b8554468d72370ac6c62 /drivers/cxl/pci.c
parentcxl/pci: Remove unnecessary device reference management in sanitize work (diff)
downloadlinux-e30a106558e7d1e06d1fcfd12466dc646673d03d.tar.xz
linux-e30a106558e7d1e06d1fcfd12466dc646673d03d.zip
cxl/pci: Cleanup 'sanitize' to always poll
In preparation for fixing the init/teardown of the 'sanitize' workqueue and sysfs notification mechanism, arrange for cxl_mbox_sanitize_work() to be the single location where the sysfs attribute is notified. With that change there is no distinction between polled mode and interrupt mode. All the interrupt does is accelerate the polling interval. The change to check for "mds->security.sanitize_node" under the lock is there to ensure that the interrupt, the work routine and the setup/teardown code can all have a consistent view of the registered notifier and the workqueue state. I.e. the expectation is that the interrupt is live past the point that the sanitize sysfs attribute is published, and it may race teardown, so it must be consulted under a lock. Given that new locking requirement, cxl_pci_mbox_irq() is moved from hard to thread irq context. Lastly, some opportunistic replacements of "queue_delayed_work(system_wq, ...)", which is just open coded schedule_delayed_work(), are included. Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Davidlohr Bueso <dave@stgolabs.net> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to '')
-rw-r--r--drivers/cxl/pci.c60
1 files changed, 25 insertions, 35 deletions
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index aa1b3dd9e64c..49d9b2ef5c5c 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -128,10 +128,10 @@ static irqreturn_t cxl_pci_mbox_irq(int irq, void *id)
reg = readq(cxlds->regs.mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET);
opcode = FIELD_GET(CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK, reg);
if (opcode == CXL_MBOX_OP_SANITIZE) {
+ mutex_lock(&mds->mbox_mutex);
if (mds->security.sanitize_node)
- sysfs_notify_dirent(mds->security.sanitize_node);
-
- dev_dbg(cxlds->dev, "Sanitization operation ended\n");
+ mod_delayed_work(system_wq, &mds->security.poll_dwork, 0);
+ mutex_unlock(&mds->mbox_mutex);
} else {
/* short-circuit the wait in __cxl_pci_mbox_send_cmd() */
rcuwait_wake_up(&mds->mbox_wait);
@@ -160,8 +160,7 @@ static void cxl_mbox_sanitize_work(struct work_struct *work)
int timeout = mds->security.poll_tmo_secs + 10;
mds->security.poll_tmo_secs = min(15 * 60, timeout);
- queue_delayed_work(system_wq, &mds->security.poll_dwork,
- timeout * HZ);
+ schedule_delayed_work(&mds->security.poll_dwork, timeout * HZ);
}
mutex_unlock(&mds->mbox_mutex);
}
@@ -293,15 +292,11 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_memdev_state *mds,
* and allow userspace to poll(2) for completion.
*/
if (mbox_cmd->opcode == CXL_MBOX_OP_SANITIZE) {
- if (mds->security.poll) {
- /* give first timeout a second */
- timeout = 1;
- mds->security.poll_tmo_secs = timeout;
- queue_delayed_work(system_wq,
- &mds->security.poll_dwork,
- timeout * HZ);
- }
-
+ /* give first timeout a second */
+ timeout = 1;
+ mds->security.poll_tmo_secs = timeout;
+ schedule_delayed_work(&mds->security.poll_dwork,
+ timeout * HZ);
dev_dbg(dev, "Sanitization operation started\n");
goto success;
}
@@ -384,7 +379,9 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds)
const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET);
struct device *dev = cxlds->dev;
unsigned long timeout;
+ int irq, msgnum;
u64 md_status;
+ u32 ctrl;
timeout = jiffies + mbox_ready_timeout * HZ;
do {
@@ -432,33 +429,26 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds)
dev_dbg(dev, "Mailbox payload sized %zu", mds->payload_size);
rcuwait_init(&mds->mbox_wait);
+ INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work);
- if (cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ) {
- u32 ctrl;
- int irq, msgnum;
- struct pci_dev *pdev = to_pci_dev(cxlds->dev);
-
- msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap);
- irq = pci_irq_vector(pdev, msgnum);
- if (irq < 0)
- goto mbox_poll;
-
- if (cxl_request_irq(cxlds, irq, cxl_pci_mbox_irq, NULL))
- goto mbox_poll;
+ /* background command interrupts are optional */
+ if (!(cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ))
+ return 0;
- /* enable background command mbox irq support */
- ctrl = readl(cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
- ctrl |= CXLDEV_MBOX_CTRL_BG_CMD_IRQ;
- writel(ctrl, cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
+ msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap);
+ irq = pci_irq_vector(to_pci_dev(cxlds->dev), msgnum);
+ if (irq < 0)
+ return 0;
+ if (cxl_request_irq(cxlds, irq, NULL, cxl_pci_mbox_irq))
return 0;
- }
-mbox_poll:
- mds->security.poll = true;
- INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work);
+ dev_dbg(cxlds->dev, "Mailbox interrupts enabled\n");
+ /* enable background command mbox irq support */
+ ctrl = readl(cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
+ ctrl |= CXLDEV_MBOX_CTRL_BG_CMD_IRQ;
+ writel(ctrl, cxlds->regs.mbox + CXLDEV_MBOX_CTRL_OFFSET);
- dev_dbg(cxlds->dev, "Mailbox interrupts are unsupported");
return 0;
}