aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Merello <andrea.merello@gmail.com>2014-05-31 12:30:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-06-19 15:49:12 -0400
commit325ed9ff14d2c726725324280ce3a56d6258b0ea (patch)
tree169dcfb725a856af0d6381e3ef62eded3a4b2500
parent7049327a686d2ba888b28a0456eddd3c71fb4b55 (diff)
rtl818x_pci: fix possible RX descriptor invalid data read
RX descriptor data must be read only if the descriptor has been fully updated by HW. There is a "ownership" flag in the descriptor itself to test this. The driver code contains a read for the "ownership" flag and, after it, other read access for descriptor data. This is in DMA coherent memory, that is _not_ guaranteed to be immune to instruction reordering, thus it is possible that the descriptor data is read _before_ the "ownership" flag. This can theoretically lead to a DMA/CPU race that may end up with the driver reading the data when it is still not valid, and the "ownership" bit just after enough time that the HW make the whole descriptor valid. The driver will in this case believe the data is valid, but it will use the invalid data read earlier. In order to avoid this, this patch adds a rmb() to force the "ownership" bit read to be issued before other descriptor data reads are attempted. Signed-off-by: Andrea Merello <andrea.merello@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index cd8c09076b52..1e2592918fc6 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -222,12 +222,20 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
222 struct rtl8187se_rx_desc *desc = entry; 222 struct rtl8187se_rx_desc *desc = entry;
223 223
224 flags = le32_to_cpu(desc->flags); 224 flags = le32_to_cpu(desc->flags);
225 /* if ownership flag is set, then we can trust the
226 * HW has written other fields. We must not trust
227 * other descriptor data read before we checked (read)
228 * the ownership flag
229 */
230 rmb();
225 flags2 = le32_to_cpu(desc->flags2); 231 flags2 = le32_to_cpu(desc->flags2);
226 tsft = le64_to_cpu(desc->tsft); 232 tsft = le64_to_cpu(desc->tsft);
227 } else { 233 } else {
228 struct rtl8180_rx_desc *desc = entry; 234 struct rtl8180_rx_desc *desc = entry;
229 235
230 flags = le32_to_cpu(desc->flags); 236 flags = le32_to_cpu(desc->flags);
237 /* same as above */
238 rmb();
231 flags2 = le32_to_cpu(desc->flags2); 239 flags2 = le32_to_cpu(desc->flags2);
232 tsft = le64_to_cpu(desc->tsft); 240 tsft = le64_to_cpu(desc->tsft);
233 } 241 }