diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 422705d62b5b..26fbeb140a6a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -224,6 +224,13 @@ struct packet_skb_cb { | |||
224 | 224 | ||
225 | #define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb)) | 225 | #define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb)) |
226 | 226 | ||
227 | static inline struct page *pgv_to_page(void *addr) | ||
228 | { | ||
229 | if (is_vmalloc_addr(addr)) | ||
230 | return vmalloc_to_page(addr); | ||
231 | return virt_to_page(addr); | ||
232 | } | ||
233 | |||
227 | static void __packet_set_status(struct packet_sock *po, void *frame, int status) | 234 | static void __packet_set_status(struct packet_sock *po, void *frame, int status) |
228 | { | 235 | { |
229 | union { | 236 | union { |
@@ -236,11 +243,11 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status) | |||
236 | switch (po->tp_version) { | 243 | switch (po->tp_version) { |
237 | case TPACKET_V1: | 244 | case TPACKET_V1: |
238 | h.h1->tp_status = status; | 245 | h.h1->tp_status = status; |
239 | flush_dcache_page(virt_to_page(&h.h1->tp_status)); | 246 | flush_dcache_page(pgv_to_page(&h.h1->tp_status)); |
240 | break; | 247 | break; |
241 | case TPACKET_V2: | 248 | case TPACKET_V2: |
242 | h.h2->tp_status = status; | 249 | h.h2->tp_status = status; |
243 | flush_dcache_page(virt_to_page(&h.h2->tp_status)); | 250 | flush_dcache_page(pgv_to_page(&h.h2->tp_status)); |
244 | break; | 251 | break; |
245 | default: | 252 | default: |
246 | pr_err("TPACKET version not supported\n"); | 253 | pr_err("TPACKET version not supported\n"); |
@@ -263,10 +270,10 @@ static int __packet_get_status(struct packet_sock *po, void *frame) | |||
263 | h.raw = frame; | 270 | h.raw = frame; |
264 | switch (po->tp_version) { | 271 | switch (po->tp_version) { |
265 | case TPACKET_V1: | 272 | case TPACKET_V1: |
266 | flush_dcache_page(virt_to_page(&h.h1->tp_status)); | 273 | flush_dcache_page(pgv_to_page(&h.h1->tp_status)); |
267 | return h.h1->tp_status; | 274 | return h.h1->tp_status; |
268 | case TPACKET_V2: | 275 | case TPACKET_V2: |
269 | flush_dcache_page(virt_to_page(&h.h2->tp_status)); | 276 | flush_dcache_page(pgv_to_page(&h.h2->tp_status)); |
270 | return h.h2->tp_status; | 277 | return h.h2->tp_status; |
271 | default: | 278 | default: |
272 | pr_err("TPACKET version not supported\n"); | 279 | pr_err("TPACKET version not supported\n"); |
@@ -800,15 +807,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
800 | __packet_set_status(po, h.raw, status); | 807 | __packet_set_status(po, h.raw, status); |
801 | smp_mb(); | 808 | smp_mb(); |
802 | { | 809 | { |
803 | struct page *p_start, *p_end; | 810 | u8 *start, *end; |
804 | u8 *h_end = h.raw + macoff + snaplen - 1; | 811 | |
805 | 812 | end = (u8 *)PAGE_ALIGN((unsigned long)h.raw + macoff + snaplen); | |
806 | p_start = virt_to_page(h.raw); | 813 | for (start = h.raw; start < end; start += PAGE_SIZE) |
807 | p_end = virt_to_page(h_end); | 814 | flush_dcache_page(pgv_to_page(start)); |
808 | while (p_start <= p_end) { | ||
809 | flush_dcache_page(p_start); | ||
810 | p_start++; | ||
811 | } | ||
812 | } | 815 | } |
813 | 816 | ||
814 | sk->sk_data_ready(sk, 0); | 817 | sk->sk_data_ready(sk, 0); |
@@ -915,7 +918,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
915 | } | 918 | } |
916 | 919 | ||
917 | err = -EFAULT; | 920 | err = -EFAULT; |
918 | page = virt_to_page(data); | ||
919 | offset = offset_in_page(data); | 921 | offset = offset_in_page(data); |
920 | len_max = PAGE_SIZE - offset; | 922 | len_max = PAGE_SIZE - offset; |
921 | len = ((to_write > len_max) ? len_max : to_write); | 923 | len = ((to_write > len_max) ? len_max : to_write); |
@@ -934,11 +936,11 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
934 | return -EFAULT; | 936 | return -EFAULT; |
935 | } | 937 | } |
936 | 938 | ||
939 | page = pgv_to_page(data); | ||
940 | data += len; | ||
937 | flush_dcache_page(page); | 941 | flush_dcache_page(page); |
938 | get_page(page); | 942 | get_page(page); |
939 | skb_fill_page_desc(skb, | 943 | skb_fill_page_desc(skb, nr_frags, page, offset, len); |
940 | nr_frags, | ||
941 | page++, offset, len); | ||
942 | to_write -= len; | 944 | to_write -= len; |
943 | offset = 0; | 945 | offset = 0; |
944 | len_max = PAGE_SIZE; | 946 | len_max = PAGE_SIZE; |