mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 17:01:14 +00:00
media: cobalt: fix race condition in setting HPD
The cobalt_s_bit_sysctrl reads the old register value over PCI, then changes a bit and sets writes the new value to the register. This is used among other things for setting the HPD output pin. But if the HPD is changed for multiple inputs at the same time, then this causes a race condition where a stale value is read. Serialize this function with a mutex. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
b2cd0b31ed
commit
3d37ef41be
2 changed files with 7 additions and 1 deletions
|
@ -667,6 +667,7 @@ static int cobalt_probe(struct pci_dev *pci_dev,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
cobalt->pci_dev = pci_dev;
|
cobalt->pci_dev = pci_dev;
|
||||||
cobalt->instance = i;
|
cobalt->instance = i;
|
||||||
|
mutex_init(&cobalt->pci_lock);
|
||||||
|
|
||||||
retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
|
retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
|
|
@ -251,6 +251,8 @@ struct cobalt {
|
||||||
int instance;
|
int instance;
|
||||||
struct pci_dev *pci_dev;
|
struct pci_dev *pci_dev;
|
||||||
struct v4l2_device v4l2_dev;
|
struct v4l2_device v4l2_dev;
|
||||||
|
/* serialize PCI access in cobalt_s_bit_sysctrl() */
|
||||||
|
struct mutex pci_lock;
|
||||||
|
|
||||||
void __iomem *bar0, *bar1;
|
void __iomem *bar0, *bar1;
|
||||||
|
|
||||||
|
@ -320,10 +322,13 @@ static inline u32 cobalt_g_sysctrl(struct cobalt *cobalt)
|
||||||
static inline void cobalt_s_bit_sysctrl(struct cobalt *cobalt,
|
static inline void cobalt_s_bit_sysctrl(struct cobalt *cobalt,
|
||||||
int bit, int val)
|
int bit, int val)
|
||||||
{
|
{
|
||||||
u32 ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
|
u32 ctrl;
|
||||||
|
|
||||||
|
mutex_lock(&cobalt->pci_lock);
|
||||||
|
ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
|
||||||
cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE,
|
cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE,
|
||||||
(ctrl & ~(1UL << bit)) | (val << bit));
|
(ctrl & ~(1UL << bit)) | (val << bit));
|
||||||
|
mutex_unlock(&cobalt->pci_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 cobalt_g_sysstat(struct cobalt *cobalt)
|
static inline u32 cobalt_g_sysstat(struct cobalt *cobalt)
|
||||||
|
|
Loading…
Reference in a new issue