222 lines
7.2 KiB
Diff
222 lines
7.2 KiB
Diff
From: Haiyang Zhang <haiyangz@microsoft.com>
|
|
Date: Thu, 15 Dec 2011 13:45:15 -0800
|
|
Subject: [PATCH 33/77] net/hyperv: Remove unnecessary kmap_atomic in netvsc
|
|
driver
|
|
|
|
commit 453263421f88b4a7e508c2e7b639c97e99c5b118 upstream.
|
|
|
|
__get_free_pages() doesn't return HI memory, so the memory is always mapped.
|
|
kmap_atomic() is not necessary here. This patch removes the kmap_atomic()
|
|
calls and related code for locking and page manipulation.
|
|
|
|
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
|
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
|
---
|
|
drivers/net/hyperv/hyperv_net.h | 6 ++---
|
|
drivers/net/hyperv/netvsc.c | 53 +++----------------------------------
|
|
drivers/net/hyperv/netvsc_drv.c | 22 ++-------------
|
|
drivers/net/hyperv/rndis_filter.c | 21 ++-------------
|
|
4 files changed, 10 insertions(+), 92 deletions(-)
|
|
|
|
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
|
index 49b131f..ff1b520 100644
|
|
--- a/drivers/net/hyperv/hyperv_net.h
|
|
+++ b/drivers/net/hyperv/hyperv_net.h
|
|
@@ -39,9 +39,6 @@ struct xferpage_packet {
|
|
u32 count;
|
|
};
|
|
|
|
-/* The number of pages which are enough to cover jumbo frame buffer. */
|
|
-#define NETVSC_PACKET_MAXPAGE 4
|
|
-
|
|
/*
|
|
* Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
|
|
* within the RNDIS
|
|
@@ -77,8 +74,9 @@ struct hv_netvsc_packet {
|
|
|
|
u32 total_data_buflen;
|
|
/* Points to the send/receive buffer where the ethernet frame is */
|
|
+ void *data;
|
|
u32 page_buf_cnt;
|
|
- struct hv_page_buffer page_buf[NETVSC_PACKET_MAXPAGE];
|
|
+ struct hv_page_buffer page_buf[0];
|
|
};
|
|
|
|
struct netvsc_device_info {
|
|
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
|
index b6ac152..bab627f 100644
|
|
--- a/drivers/net/hyperv/netvsc.c
|
|
+++ b/drivers/net/hyperv/netvsc.c
|
|
@@ -603,12 +603,10 @@ static void netvsc_receive(struct hv_device *device,
|
|
struct vmtransfer_page_packet_header *vmxferpage_packet;
|
|
struct nvsp_message *nvsp_packet;
|
|
struct hv_netvsc_packet *netvsc_packet = NULL;
|
|
- unsigned long start;
|
|
- unsigned long end, end_virtual;
|
|
/* struct netvsc_driver *netvscDriver; */
|
|
struct xferpage_packet *xferpage_packet = NULL;
|
|
- int i, j;
|
|
- int count = 0, bytes_remain = 0;
|
|
+ int i;
|
|
+ int count = 0;
|
|
unsigned long flags;
|
|
struct net_device *ndev;
|
|
|
|
@@ -717,53 +715,10 @@ static void netvsc_receive(struct hv_device *device,
|
|
netvsc_packet->completion.recv.recv_completion_tid =
|
|
vmxferpage_packet->d.trans_id;
|
|
|
|
+ netvsc_packet->data = (void *)((unsigned long)net_device->
|
|
+ recv_buf + vmxferpage_packet->ranges[i].byte_offset);
|
|
netvsc_packet->total_data_buflen =
|
|
vmxferpage_packet->ranges[i].byte_count;
|
|
- netvsc_packet->page_buf_cnt = 1;
|
|
-
|
|
- netvsc_packet->page_buf[0].len =
|
|
- vmxferpage_packet->ranges[i].byte_count;
|
|
-
|
|
- start = virt_to_phys((void *)((unsigned long)net_device->
|
|
- recv_buf + vmxferpage_packet->ranges[i].byte_offset));
|
|
-
|
|
- netvsc_packet->page_buf[0].pfn = start >> PAGE_SHIFT;
|
|
- end_virtual = (unsigned long)net_device->recv_buf
|
|
- + vmxferpage_packet->ranges[i].byte_offset
|
|
- + vmxferpage_packet->ranges[i].byte_count - 1;
|
|
- end = virt_to_phys((void *)end_virtual);
|
|
-
|
|
- /* Calculate the page relative offset */
|
|
- netvsc_packet->page_buf[0].offset =
|
|
- vmxferpage_packet->ranges[i].byte_offset &
|
|
- (PAGE_SIZE - 1);
|
|
- if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) {
|
|
- /* Handle frame across multiple pages: */
|
|
- netvsc_packet->page_buf[0].len =
|
|
- (netvsc_packet->page_buf[0].pfn <<
|
|
- PAGE_SHIFT)
|
|
- + PAGE_SIZE - start;
|
|
- bytes_remain = netvsc_packet->total_data_buflen -
|
|
- netvsc_packet->page_buf[0].len;
|
|
- for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) {
|
|
- netvsc_packet->page_buf[j].offset = 0;
|
|
- if (bytes_remain <= PAGE_SIZE) {
|
|
- netvsc_packet->page_buf[j].len =
|
|
- bytes_remain;
|
|
- bytes_remain = 0;
|
|
- } else {
|
|
- netvsc_packet->page_buf[j].len =
|
|
- PAGE_SIZE;
|
|
- bytes_remain -= PAGE_SIZE;
|
|
- }
|
|
- netvsc_packet->page_buf[j].pfn =
|
|
- virt_to_phys((void *)(end_virtual -
|
|
- bytes_remain)) >> PAGE_SHIFT;
|
|
- netvsc_packet->page_buf_cnt++;
|
|
- if (bytes_remain == 0)
|
|
- break;
|
|
- }
|
|
- }
|
|
|
|
/* Pass it to the upper layer */
|
|
rndis_filter_receive(device, netvsc_packet);
|
|
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
|
index 7da85eb..b7cbd12 100644
|
|
--- a/drivers/net/hyperv/netvsc_drv.c
|
|
+++ b/drivers/net/hyperv/netvsc_drv.c
|
|
@@ -251,9 +251,6 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
|
{
|
|
struct net_device *net = dev_get_drvdata(&device_obj->device);
|
|
struct sk_buff *skb;
|
|
- void *data;
|
|
- int i;
|
|
- unsigned long flags;
|
|
struct netvsc_device *net_device;
|
|
|
|
net_device = hv_get_drvdata(device_obj);
|
|
@@ -272,27 +269,12 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
|
return 0;
|
|
}
|
|
|
|
- /* for kmap_atomic */
|
|
- local_irq_save(flags);
|
|
-
|
|
/*
|
|
* Copy to skb. This copy is needed here since the memory pointed by
|
|
* hv_netvsc_packet cannot be deallocated
|
|
*/
|
|
- for (i = 0; i < packet->page_buf_cnt; i++) {
|
|
- data = kmap_atomic(pfn_to_page(packet->page_buf[i].pfn),
|
|
- KM_IRQ1);
|
|
- data = (void *)(unsigned long)data +
|
|
- packet->page_buf[i].offset;
|
|
-
|
|
- memcpy(skb_put(skb, packet->page_buf[i].len), data,
|
|
- packet->page_buf[i].len);
|
|
-
|
|
- kunmap_atomic((void *)((unsigned long)data -
|
|
- packet->page_buf[i].offset), KM_IRQ1);
|
|
- }
|
|
-
|
|
- local_irq_restore(flags);
|
|
+ memcpy(skb_put(skb, packet->total_data_buflen), packet->data,
|
|
+ packet->total_data_buflen);
|
|
|
|
skb->protocol = eth_type_trans(skb, net);
|
|
skb->ip_summed = CHECKSUM_NONE;
|
|
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
|
index 418e7aa..da181f9 100644
|
|
--- a/drivers/net/hyperv/rndis_filter.c
|
|
+++ b/drivers/net/hyperv/rndis_filter.c
|
|
@@ -309,7 +309,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
|
|
{
|
|
struct rndis_packet *rndis_pkt;
|
|
u32 data_offset;
|
|
- int i;
|
|
|
|
rndis_pkt = &msg->msg.pkt;
|
|
|
|
@@ -322,17 +321,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
|
|
data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
|
|
|
|
pkt->total_data_buflen -= data_offset;
|
|
- pkt->page_buf[0].offset += data_offset;
|
|
- pkt->page_buf[0].len -= data_offset;
|
|
-
|
|
- /* Drop the 0th page, if rndis data go beyond page boundary */
|
|
- if (pkt->page_buf[0].offset >= PAGE_SIZE) {
|
|
- pkt->page_buf[1].offset = pkt->page_buf[0].offset - PAGE_SIZE;
|
|
- pkt->page_buf[1].len -= pkt->page_buf[1].offset;
|
|
- pkt->page_buf_cnt--;
|
|
- for (i = 0; i < pkt->page_buf_cnt; i++)
|
|
- pkt->page_buf[i] = pkt->page_buf[i+1];
|
|
- }
|
|
+ pkt->data = (void *)((unsigned long)pkt->data + data_offset);
|
|
|
|
pkt->is_data_pkt = true;
|
|
|
|
@@ -367,11 +356,7 @@ int rndis_filter_receive(struct hv_device *dev,
|
|
return -ENODEV;
|
|
}
|
|
|
|
- rndis_hdr = (struct rndis_message *)kmap_atomic(
|
|
- pfn_to_page(pkt->page_buf[0].pfn), KM_IRQ0);
|
|
-
|
|
- rndis_hdr = (void *)((unsigned long)rndis_hdr +
|
|
- pkt->page_buf[0].offset);
|
|
+ rndis_hdr = pkt->data;
|
|
|
|
/* Make sure we got a valid rndis message */
|
|
if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
|
|
@@ -387,8 +372,6 @@ int rndis_filter_receive(struct hv_device *dev,
|
|
sizeof(struct rndis_message) :
|
|
rndis_hdr->msg_len);
|
|
|
|
- kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
|
|
-
|
|
dump_rndis_message(dev, &rndis_msg);
|
|
|
|
switch (rndis_msg.ndis_msg_type) {
|
|
--
|
|
1.7.9.5
|
|
|