Skip to content

Commit 4bd46aa

Browse files
b-rad-NDimchehab
authored andcommitted
media: cx23885: only reset DMA on problematic CPUs
It is reported that commit 95f408b ("media: cx23885: Ryzen DMA related RiSC engine stall fixes") caused regresssions with other CPUs. Ensure that the quirk will be applied only for the CPUs that are known to cause problems. A module option is added for explicit control of the behaviour. Fixes: 95f408b ("media: cx23885: Ryzen DMA related RiSC engine stall fixes") Signed-off-by: Brad Love <brad@nextdimension.cc> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
1 parent bbb55cd commit 4bd46aa

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

drivers/media/pci/cx23885/cx23885-core.c

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/moduleparam.h>
2424
#include <linux/kmod.h>
2525
#include <linux/kernel.h>
26+
#include <linux/pci.h>
2627
#include <linux/slab.h>
2728
#include <linux/interrupt.h>
2829
#include <linux/delay.h>
@@ -41,6 +42,18 @@ MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
4142
MODULE_LICENSE("GPL");
4243
MODULE_VERSION(CX23885_VERSION);
4344

45+
/*
46+
* Some platforms have been found to require periodic resetting of the DMA
47+
* engine. Ryzen and XEON platforms are known to be affected. The symptom
48+
* encountered is "mpeg risc op code error". Only Ryzen platforms employ
49+
* this workaround if the option equals 1. The workaround can be explicitly
50+
* disabled for all platforms by setting to 0, the workaround can be forced
51+
* on for any platform by setting to 2.
52+
*/
53+
static unsigned int dma_reset_workaround = 1;
54+
module_param(dma_reset_workaround, int, 0644);
55+
MODULE_PARM_DESC(dma_reset_workaround, "periodic RiSC dma engine reset; 0-force disable, 1-driver detect (default), 2-force enable");
56+
4457
static unsigned int debug;
4558
module_param(debug, int, 0644);
4659
MODULE_PARM_DESC(debug, "enable debug messages");
@@ -603,8 +616,13 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port,
603616

604617
static void cx23885_clear_bridge_error(struct cx23885_dev *dev)
605618
{
606-
uint32_t reg1_val = cx_read(TC_REQ); /* read-only */
607-
uint32_t reg2_val = cx_read(TC_REQ_SET);
619+
uint32_t reg1_val, reg2_val;
620+
621+
if (!dev->need_dma_reset)
622+
return;
623+
624+
reg1_val = cx_read(TC_REQ); /* read-only */
625+
reg2_val = cx_read(TC_REQ_SET);
608626

609627
if (reg1_val && reg2_val) {
610628
cx_write(TC_REQ, reg1_val);
@@ -2058,6 +2076,37 @@ void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
20582076
/* TODO: 23-19 */
20592077
}
20602078

2079+
static struct {
2080+
int vendor, dev;
2081+
} const broken_dev_id[] = {
2082+
/* According with
2083+
* https://openbenchmarking.org/system/1703021-RI-AMDZEN08075/Ryzen%207%201800X/lspci,
2084+
* 0x1451 is PCI ID for the IOMMU found on Ryzen
2085+
*/
2086+
{ PCI_VENDOR_ID_AMD, 0x1451 },
2087+
};
2088+
2089+
static bool cx23885_does_need_dma_reset(void)
2090+
{
2091+
int i;
2092+
struct pci_dev *pdev = NULL;
2093+
2094+
if (dma_reset_workaround == 0)
2095+
return false;
2096+
else if (dma_reset_workaround == 2)
2097+
return true;
2098+
2099+
for (i = 0; i < ARRAY_SIZE(broken_dev_id); i++) {
2100+
pdev = pci_get_device(broken_dev_id[i].vendor,
2101+
broken_dev_id[i].dev, NULL);
2102+
if (pdev) {
2103+
pci_dev_put(pdev);
2104+
return true;
2105+
}
2106+
}
2107+
return false;
2108+
}
2109+
20612110
static int cx23885_initdev(struct pci_dev *pci_dev,
20622111
const struct pci_device_id *pci_id)
20632112
{
@@ -2069,6 +2118,8 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
20692118
if (NULL == dev)
20702119
return -ENOMEM;
20712120

2121+
dev->need_dma_reset = cx23885_does_need_dma_reset();
2122+
20722123
err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
20732124
if (err < 0)
20742125
goto fail_free;

drivers/media/pci/cx23885/cx23885.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,8 @@ struct cx23885_dev {
451451
/* Analog raw audio */
452452
struct cx23885_audio_dev *audio_dev;
453453

454+
/* Does the system require periodic DMA resets? */
455+
unsigned int need_dma_reset:1;
454456
};
455457

456458
static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)

0 commit comments

Comments
 (0)