--- v3
+++ v4
@@ -11,10 +11,10 @@
Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
---
drivers/net/hyperv/hyperv_net.h | 6 ++
- drivers/net/hyperv/netvsc.c | 125 ++++++++++++++++++++++++++++--
- drivers/net/hyperv/rndis_filter.c | 3 +
+ drivers/net/hyperv/netvsc.c | 144 +++++++++++++++++++++++++++++-
+ drivers/net/hyperv/rndis_filter.c | 2 +
include/linux/hyperv.h | 5 ++
- 4 files changed, 133 insertions(+), 6 deletions(-)
+ 4 files changed, 154 insertions(+), 3 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index b11aa68b44ec..c2fbb9d4df2c 100644
@@ -53,7 +53,7 @@
+ struct hv_netvsc_packet *packet);
#endif /* _HYPERV_NET_H */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
-index 7bd935412853..a01740c6c6b8 100644
+index 7bd935412853..fc312e5db4d5 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -153,8 +153,21 @@ static void free_netvsc_device(struct rcu_head *head)
@@ -80,32 +80,51 @@
kfree(nvdev->send_section_map);
for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
-@@ -338,8 +351,10 @@ static int netvsc_init_buf(struct hv_device *device,
- struct net_device *ndev = hv_get_drvdata(device);
- struct nvsp_message *init_packet;
+@@ -330,6 +343,27 @@ int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx)
+ return nvchan->mrc.slots ? 0 : -ENOMEM;
+ }
+
++static void *netvsc_remap_buf(void *buf, unsigned long size)
++{
++ unsigned long *pfns;
++ void *vaddr;
++ int i;
++
++ pfns = kcalloc(size / HV_HYP_PAGE_SIZE, sizeof(unsigned long),
++ GFP_KERNEL);
++ if (!pfns)
++ return NULL;
++
++ for (i = 0; i < size / HV_HYP_PAGE_SIZE; i++)
++ pfns[i] = virt_to_hvpfn(buf + i * HV_HYP_PAGE_SIZE)
++ + (ms_hyperv.shared_gpa_boundary >> HV_HYP_PAGE_SHIFT);
++
++ vaddr = vmap_pfn(pfns, size / HV_HYP_PAGE_SIZE, PAGE_KERNEL_IO);
++ kfree(pfns);
++
++ return vaddr;
++}
++
+ static int netvsc_init_buf(struct hv_device *device,
+ struct netvsc_device *net_device,
+ const struct netvsc_device_info *device_info)
+@@ -340,6 +374,7 @@ static int netvsc_init_buf(struct hv_device *device,
unsigned int buf_size;
-+ unsigned long *pfns;
size_t map_words;
int i, ret = 0;
+ void *vaddr;
/* Get receive buffer area. */
buf_size = device_info->recv_sections * device_info->recv_section_size;
-@@ -375,6 +390,21 @@ static int netvsc_init_buf(struct hv_device *device,
+@@ -375,6 +410,15 @@ static int netvsc_init_buf(struct hv_device *device,
goto cleanup;
}
+ if (hv_isolation_type_snp()) {
-+ pfns = kcalloc(buf_size / HV_HYP_PAGE_SIZE, sizeof(unsigned long),
-+ GFP_KERNEL);
-+ for (i = 0; i < buf_size / HV_HYP_PAGE_SIZE; i++)
-+ pfns[i] = virt_to_hvpfn(net_device->recv_buf + i * HV_HYP_PAGE_SIZE) +
-+ (ms_hyperv.shared_gpa_boundary >> HV_HYP_PAGE_SHIFT);
-+
-+ vaddr = vmap_pfn(pfns, buf_size / HV_HYP_PAGE_SIZE, PAGE_KERNEL_IO);
-+ kfree(pfns);
++ vaddr = netvsc_remap_buf(net_device->recv_buf, buf_size);
+ if (!vaddr)
+ goto cleanup;
++
+ net_device->recv_original_buf = net_device->recv_buf;
+ net_device->recv_buf = vaddr;
+ }
@@ -113,20 +132,12 @@
/* Notify the NetVsp of the gpadl handle */
init_packet = &net_device->channel_init_pkt;
memset(init_packet, 0, sizeof(struct nvsp_message));
-@@ -477,6 +507,23 @@ static int netvsc_init_buf(struct hv_device *device,
+@@ -477,6 +521,15 @@ static int netvsc_init_buf(struct hv_device *device,
goto cleanup;
}
+ if (hv_isolation_type_snp()) {
-+ pfns = kcalloc(buf_size / HV_HYP_PAGE_SIZE, sizeof(unsigned long),
-+ GFP_KERNEL);
-+
-+ for (i = 0; i < buf_size / HV_HYP_PAGE_SIZE; i++)
-+ pfns[i] = virt_to_hvpfn(net_device->send_buf + i * HV_HYP_PAGE_SIZE)
-+ + (ms_hyperv.shared_gpa_boundary >> HV_HYP_PAGE_SHIFT);
-+
-+ vaddr = vmap_pfn(pfns, buf_size / HV_HYP_PAGE_SIZE, PAGE_KERNEL_IO);
-+ kfree(pfns);
++ vaddr = netvsc_remap_buf(net_device->send_buf, buf_size);
+ if (!vaddr)
+ goto cleanup;
+
@@ -137,7 +148,7 @@
/* Notify the NetVsp of the gpadl handle */
init_packet = &net_device->channel_init_pkt;
memset(init_packet, 0, sizeof(struct nvsp_message));
-@@ -767,7 +814,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev,
+@@ -767,7 +820,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev,
/* Notify the layer above us */
if (likely(skb)) {
@@ -146,7 +157,7 @@
= (struct hv_netvsc_packet *)skb->cb;
u32 send_index = packet->send_buf_index;
struct netvsc_stats *tx_stats;
-@@ -783,6 +830,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev,
+@@ -783,6 +836,7 @@ static void netvsc_send_tx_complete(struct net_device *ndev,
tx_stats->bytes += packet->total_bytes;
u64_stats_update_end(&tx_stats->syncp);
@@ -154,7 +165,7 @@
napi_consume_skb(skb, budget);
}
-@@ -947,6 +995,63 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
+@@ -947,6 +1001,82 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
memset(dest, 0, padding);
}
@@ -166,6 +177,9 @@
+ packet->page_buf_cnt;
+ int i;
+
++ if (!hv_is_isolation_supported())
++ return;
++
+ if (!packet->dma_range)
+ return;
+
@@ -177,6 +191,19 @@
+ kfree(packet->dma_range);
+}
+
++/* netvsc_dma_map - Map swiotlb bounce buffer with data page of
++ * packet sent by vmbus_sendpacket_pagebuffer() in the Isolation
++ * VM.
++ *
++ * In isolation VM, netvsc send buffer has been marked visible to
++ * host and so the data copied to send buffer doesn't need to use
++ * bounce buffer. The data pages handled by vmbus_sendpacket_pagebuffer()
++ * may not be copied to send buffer and so these pages need to be
++ * mapped with swiotlb bounce buffer. netvsc_dma_map() is to do
++ * that. The pfns in the struct hv_page_buffer need to be converted
++ * to bounce buffer's pfn. The loop here is necessary and so not
++ * use dma_map_sg() here.
++ */
+int netvsc_dma_map(struct hv_device *hv_dev,
+ struct hv_netvsc_packet *packet,
+ struct hv_page_buffer *pb)
@@ -187,6 +214,9 @@
+ dma_addr_t dma;
+ int i;
+
++ if (!hv_is_isolation_supported())
++ return 0;
++
+ packet->dma_range = kcalloc(page_count,
+ sizeof(*packet->dma_range),
+ GFP_KERNEL);
@@ -218,7 +248,7 @@
static inline int netvsc_send_pkt(
struct hv_device *device,
struct hv_netvsc_packet *packet,
-@@ -987,14 +1092,22 @@ static inline int netvsc_send_pkt(
+@@ -987,14 +1117,22 @@ static inline int netvsc_send_pkt(
trace_nvsp_send_pkt(ndev, out_channel, rpkt);
@@ -232,12 +262,9 @@
+ return ret;
+
ret = vmbus_sendpacket_pagebuffer(out_channel,
-- pb, packet->page_buf_cnt,
-- &nvmsg, sizeof(nvmsg),
-- req_id);
-+ pb, packet->page_buf_cnt,
-+ &nvmsg, sizeof(nvmsg),
-+ req_id);
+ pb, packet->page_buf_cnt,
+ &nvmsg, sizeof(nvmsg),
+ req_id);
+
+ if (ret)
+ netvsc_dma_unmap(ndev_ctx->device_ctx, packet);
@@ -245,23 +272,15 @@
ret = vmbus_sendpacket(out_channel,
&nvmsg, sizeof(nvmsg),
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
-index 983bf362466a..448c1ee39246 100644
+index 983bf362466a..9425fee85aa0 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
-@@ -293,6 +293,8 @@ static void rndis_filter_receive_response(struct net_device *ndev,
- u32 *req_id = &resp->msg.init_complete.req_id;
- struct rndis_device *dev = nvdev->extension;
- struct rndis_request *request = NULL;
-+ struct hv_device *hv_dev = ((struct net_device_context *)
-+ netdev_priv(ndev))->device_ctx;
- bool found = false;
- unsigned long flags;
-
-@@ -361,6 +363,7 @@ static void rndis_filter_receive_response(struct net_device *ndev,
+@@ -361,6 +361,8 @@ static void rndis_filter_receive_response(struct net_device *ndev,
}
}
-+ netvsc_dma_unmap(hv_dev, &request->pkt);
++ netvsc_dma_unmap(((struct net_device_context *)
++ netdev_priv(ndev))->device_ctx, &request->pkt);
complete(&request->wait_event);
} else {
netdev_err(ndev,