| From 6fb05e0dd32e566facb96ea61a48c7488daa5ac3 Mon Sep 17 00:00:00 2001 |
| From: Steven Toth <stoth@kernellabs.com> |
| Date: Tue, 6 Jun 2017 09:30:27 -0300 |
| Subject: [media] saa7164: fix double fetch PCIe access condition |
| |
| From: Steven Toth <stoth@kernellabs.com> |
| |
| commit 6fb05e0dd32e566facb96ea61a48c7488daa5ac3 upstream. |
| |
| Avoid a double fetch by reusing the values from the prior transfer. |
| |
| Originally reported via https://bugzilla.kernel.org/show_bug.cgi?id=195559 |
| |
| Thanks to Pengfei Wang <wpengfeinudt@gmail.com> for reporting. |
| |
| Signed-off-by: Steven Toth <stoth@kernellabs.com> |
| Reported-by: Pengfei Wang <wpengfeinudt@gmail.com> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> |
| Cc: Eduardo Valentin <eduval@amazon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/media/pci/saa7164/saa7164-bus.c | 13 +------------ |
| 1 file changed, 1 insertion(+), 12 deletions(-) |
| |
| --- a/drivers/media/pci/saa7164/saa7164-bus.c |
| +++ b/drivers/media/pci/saa7164/saa7164-bus.c |
| @@ -393,11 +393,11 @@ int saa7164_bus_get(struct saa7164_dev * |
| msg_tmp.size = le16_to_cpu((__force __le16)msg_tmp.size); |
| msg_tmp.command = le32_to_cpu((__force __le32)msg_tmp.command); |
| msg_tmp.controlselector = le16_to_cpu((__force __le16)msg_tmp.controlselector); |
| + memcpy(msg, &msg_tmp, sizeof(*msg)); |
| |
| /* No need to update the read positions, because this was a peek */ |
| /* If the caller specifically want to peek, return */ |
| if (peekonly) { |
| - memcpy(msg, &msg_tmp, sizeof(*msg)); |
| goto peekout; |
| } |
| |
| @@ -442,21 +442,15 @@ int saa7164_bus_get(struct saa7164_dev * |
| space_rem = bus->m_dwSizeGetRing - curr_grp; |
| |
| if (space_rem < sizeof(*msg)) { |
| - /* msg wraps around the ring */ |
| - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem); |
| - memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing, |
| - sizeof(*msg) - space_rem); |
| if (buf) |
| memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) - |
| space_rem, buf_size); |
| |
| } else if (space_rem == sizeof(*msg)) { |
| - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); |
| if (buf) |
| memcpy_fromio(buf, bus->m_pdwGetRing, buf_size); |
| } else { |
| /* Additional data wraps around the ring */ |
| - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); |
| if (buf) { |
| memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + |
| sizeof(*msg), space_rem - sizeof(*msg)); |
| @@ -469,15 +463,10 @@ int saa7164_bus_get(struct saa7164_dev * |
| |
| } else { |
| /* No wrapping */ |
| - memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); |
| if (buf) |
| memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg), |
| buf_size); |
| } |
| - /* Convert from little endian to CPU */ |
| - msg->size = le16_to_cpu((__force __le16)msg->size); |
| - msg->command = le32_to_cpu((__force __le32)msg->command); |
| - msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector); |
| |
| /* Update the read positions, adjusting the ring */ |
| saa7164_writel(bus->m_dwGetReadPos, new_grp); |