|
@@ -224,6 +224,13 @@ struct packet_skb_cb {
|
|
|
|
|
|
#define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb))
|
|
#define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb))
|
|
|
|
|
|
|
|
+static inline struct page *pgv_to_page(void *addr)
|
|
|
|
+{
|
|
|
|
+ if (is_vmalloc_addr(addr))
|
|
|
|
+ return vmalloc_to_page(addr);
|
|
|
|
+ return virt_to_page(addr);
|
|
|
|
+}
|
|
|
|
+
|
|
static void __packet_set_status(struct packet_sock *po, void *frame, int status)
|
|
static void __packet_set_status(struct packet_sock *po, void *frame, int status)
|
|
{
|
|
{
|
|
union {
|
|
union {
|
|
@@ -236,11 +243,11 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status)
|
|
switch (po->tp_version) {
|
|
switch (po->tp_version) {
|
|
case TPACKET_V1:
|
|
case TPACKET_V1:
|
|
h.h1->tp_status = status;
|
|
h.h1->tp_status = status;
|
|
- flush_dcache_page(virt_to_page(&h.h1->tp_status));
|
|
|
|
|
|
+ flush_dcache_page(pgv_to_page(&h.h1->tp_status));
|
|
break;
|
|
break;
|
|
case TPACKET_V2:
|
|
case TPACKET_V2:
|
|
h.h2->tp_status = status;
|
|
h.h2->tp_status = status;
|
|
- flush_dcache_page(virt_to_page(&h.h2->tp_status));
|
|
|
|
|
|
+ flush_dcache_page(pgv_to_page(&h.h2->tp_status));
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
pr_err("TPACKET version not supported\n");
|
|
pr_err("TPACKET version not supported\n");
|
|
@@ -263,10 +270,10 @@ static int __packet_get_status(struct packet_sock *po, void *frame)
|
|
h.raw = frame;
|
|
h.raw = frame;
|
|
switch (po->tp_version) {
|
|
switch (po->tp_version) {
|
|
case TPACKET_V1:
|
|
case TPACKET_V1:
|
|
- flush_dcache_page(virt_to_page(&h.h1->tp_status));
|
|
|
|
|
|
+ flush_dcache_page(pgv_to_page(&h.h1->tp_status));
|
|
return h.h1->tp_status;
|
|
return h.h1->tp_status;
|
|
case TPACKET_V2:
|
|
case TPACKET_V2:
|
|
- flush_dcache_page(virt_to_page(&h.h2->tp_status));
|
|
|
|
|
|
+ flush_dcache_page(pgv_to_page(&h.h2->tp_status));
|
|
return h.h2->tp_status;
|
|
return h.h2->tp_status;
|
|
default:
|
|
default:
|
|
pr_err("TPACKET version not supported\n");
|
|
pr_err("TPACKET version not supported\n");
|
|
@@ -800,15 +807,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
|
|
__packet_set_status(po, h.raw, status);
|
|
__packet_set_status(po, h.raw, status);
|
|
smp_mb();
|
|
smp_mb();
|
|
{
|
|
{
|
|
- struct page *p_start, *p_end;
|
|
|
|
- u8 *h_end = h.raw + macoff + snaplen - 1;
|
|
|
|
-
|
|
|
|
- p_start = virt_to_page(h.raw);
|
|
|
|
- p_end = virt_to_page(h_end);
|
|
|
|
- while (p_start <= p_end) {
|
|
|
|
- flush_dcache_page(p_start);
|
|
|
|
- p_start++;
|
|
|
|
- }
|
|
|
|
|
|
+ u8 *start, *end;
|
|
|
|
+
|
|
|
|
+ end = (u8 *)PAGE_ALIGN((unsigned long)h.raw + macoff + snaplen);
|
|
|
|
+ for (start = h.raw; start < end; start += PAGE_SIZE)
|
|
|
|
+ flush_dcache_page(pgv_to_page(start));
|
|
}
|
|
}
|
|
|
|
|
|
sk->sk_data_ready(sk, 0);
|
|
sk->sk_data_ready(sk, 0);
|
|
@@ -915,7 +918,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
|
|
}
|
|
}
|
|
|
|
|
|
err = -EFAULT;
|
|
err = -EFAULT;
|
|
- page = virt_to_page(data);
|
|
|
|
offset = offset_in_page(data);
|
|
offset = offset_in_page(data);
|
|
len_max = PAGE_SIZE - offset;
|
|
len_max = PAGE_SIZE - offset;
|
|
len = ((to_write > len_max) ? len_max : to_write);
|
|
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,
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ page = pgv_to_page(data);
|
|
|
|
+ data += len;
|
|
flush_dcache_page(page);
|
|
flush_dcache_page(page);
|
|
get_page(page);
|
|
get_page(page);
|
|
- skb_fill_page_desc(skb,
|
|
|
|
- nr_frags,
|
|
|
|
- page++, offset, len);
|
|
|
|
|
|
+ skb_fill_page_desc(skb, nr_frags, page, offset, len);
|
|
to_write -= len;
|
|
to_write -= len;
|
|
offset = 0;
|
|
offset = 0;
|
|
len_max = PAGE_SIZE;
|
|
len_max = PAGE_SIZE;
|