From cbbb64f62acd97429f517bd382ada9d618c8856a Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Sun, 2 Aug 2020 17:33:40 +0800 Subject: atm: idt77252: avoid accessing the data mapped to streaming DMA 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 Signed-off-by: David S. Miller --- drivers/atm/idt77252.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/atm') 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: -- cgit