In queue_skb(), skb->data is mapped to streaming DMA on line 850:
dma_map_single(..., skb->data, ...);
Then skb->data is accessed on lines 862 and 863:
tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
(skb->data[2] << 8) | (skb->data[3] << 0);
and on lines 893 and 894:
tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
(skb->data[2] << 8) | (skb->data[3] << 0);
These accesses may cause data inconsistency between CPU cache and
hardware.
To fix this problem, the calculation result of skb->data is stored in a
local variable before DMA mapping, and then the driver accesses this
local variable instead of skb->data.
Signed-off-by: Jia-Ju Bai <[email protected]>
---
drivers/atm/idt77252.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index df51680e8931..65a3886f68c9 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -835,6 +835,7 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
unsigned long flags;
int error;
int aal;
+ u32 word4;
if (skb->len == 0) {
printk("%s: invalid skb->len (%d)\n", card->name, skb->len);
@@ -846,6 +847,8 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
tbd = &IDT77252_PRV_TBD(skb);
vcc = ATM_SKB(skb)->vcc;
+ word4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
+ (skb->data[2] << 8) | (skb->data[3] << 0);
IDT77252_PRV_PADDR(skb) = dma_map_single(&card->pcidev->dev, skb->data,
skb->len, DMA_TO_DEVICE);
@@ -859,8 +862,7 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU;
tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
tbd->word_3 = 0x00000000;
- tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
- (skb->data[2] << 8) | (skb->data[3] << 0);
+ tbd->word_4 = word4;
if (test_bit(VCF_RSV, &vc->flags))
vc = card->vcs[0];
@@ -890,8 +892,7 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
tbd->word_3 = 0x00000000;
- tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
- (skb->data[2] << 8) | (skb->data[3] << 0);
+ tbd->word_4 = word4;
break;
case ATM_AAL5:
--
2.17.1
From: Jia-Ju Bai <[email protected]>
Date: Sun, 2 Aug 2020 17:33:40 +0800
> In queue_skb(), skb->data is mapped to streaming DMA on line 850:
> dma_map_single(..., skb->data, ...);
>
> Then skb->data is accessed on lines 862 and 863:
> tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
> (skb->data[2] << 8) | (skb->data[3] << 0);
> and on lines 893 and 894:
> tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
> (skb->data[2] << 8) | (skb->data[3] << 0);
>
> These accesses may cause data inconsistency between CPU cache and
> hardware.
>
> To fix this problem, the calculation result of skb->data is stored in a
> local variable before DMA mapping, and then the driver accesses this
> local variable instead of skb->data.
>
> Signed-off-by: Jia-Ju Bai <[email protected]>
Applied.