Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 281436
b: refs/heads/master
c: 4d447c9
h: refs/heads/master
v: v3
  • Loading branch information
Haiyang Zhang authored and Greg Kroah-Hartman committed Jan 5, 2012
1 parent 5554793 commit e489f98
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f157e78de5923dfb209355f3005ce1b5d64f7998
refs/heads/master: 4d447c9a6ebc0142d320f075c5bac6d202a79fd4
8 changes: 3 additions & 5 deletions trunk/drivers/net/hyperv/hyperv_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,12 +456,9 @@ struct nvsp_message {
} __packed;


#define NETVSC_MTU 65536


/* #define NVSC_MIN_PROTOCOL_VERSION 1 */
/* #define NVSC_MAX_PROTOCOL_VERSION 1 */

#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024) /* 1MB */
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*2) /* 2MB */

#define NETVSC_RECEIVE_BUFFER_ID 0xcafe

Expand All @@ -479,6 +476,7 @@ struct netvsc_device {
u32 nvsp_version;

atomic_t num_outstanding_sends;
bool start_remove;
bool destroy;
/*
* List of free preallocated hv_netvsc_packet to represent receive
Expand Down
6 changes: 3 additions & 3 deletions trunk/drivers/net/hyperv/netvsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
if (!net_device)
return NULL;


net_device->start_remove = false;
net_device->destroy = false;
net_device->dev = device;
net_device->ndev = ndev;
Expand Down Expand Up @@ -299,7 +299,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
/* NVSPv2 only: Send NDIS config */
memset(init_packet, 0, sizeof(struct nvsp_message));
init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG;
init_packet->msg.v2_msg.send_ndis_config.mtu = ETH_DATA_LEN;
init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu;

ret = vmbus_sendpacket(device->channel, init_packet,
sizeof(struct nvsp_message),
Expand Down Expand Up @@ -464,7 +464,7 @@ static void netvsc_send_completion(struct hv_device *device,

atomic_dec(&net_device->num_outstanding_sends);

if (netif_queue_stopped(ndev))
if (netif_queue_stopped(ndev) && !net_device->start_remove)
netif_wake_queue(ndev);
} else {
netdev_err(ndev, "Unknown send completion packet type- "
Expand Down
70 changes: 61 additions & 9 deletions trunk/drivers/net/hyperv/netvsc_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,12 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
struct net_device_context *net_device_ctx = netdev_priv(net);
struct hv_netvsc_packet *packet;
int ret;
unsigned int i, num_pages;
unsigned int i, num_pages, npg_data;

/* Add 1 for skb->data and additional one for RNDIS */
num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
/* Add multipage for skb->data and additional one for RNDIS */
npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)
>> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1;
num_pages = skb_shinfo(skb)->nr_frags + npg_data + 1;

/* Allocate a netvsc packet based on # of frags. */
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
Expand All @@ -174,21 +176,36 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet->page_buf_cnt = num_pages;

/* Initialize it from the skb */
packet->total_data_buflen = skb->len;
packet->total_data_buflen = skb->len;

/* Start filling in the page buffers starting after RNDIS buffer. */
packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
packet->page_buf[1].offset
= (unsigned long)skb->data & (PAGE_SIZE - 1);
packet->page_buf[1].len = skb_headlen(skb);
if (npg_data == 1)
packet->page_buf[1].len = skb_headlen(skb);
else
packet->page_buf[1].len = PAGE_SIZE
- packet->page_buf[1].offset;

for (i = 2; i <= npg_data; i++) {
packet->page_buf[i].pfn = virt_to_phys(skb->data
+ PAGE_SIZE * (i-1)) >> PAGE_SHIFT;
packet->page_buf[i].offset = 0;
packet->page_buf[i].len = PAGE_SIZE;
}
if (npg_data > 1)
packet->page_buf[npg_data].len = (((unsigned long)skb->data
+ skb_headlen(skb) - 1) & (PAGE_SIZE - 1)) + 1;

/* Additional fragments are after SKB data */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
const skb_frag_t *f = &skb_shinfo(skb)->frags[i];

packet->page_buf[i+2].pfn = page_to_pfn(skb_frag_page(f));
packet->page_buf[i+2].offset = f->page_offset;
packet->page_buf[i+2].len = skb_frag_size(f);
packet->page_buf[i+npg_data+1].pfn =
page_to_pfn(skb_frag_page(f));
packet->page_buf[i+npg_data+1].offset = f->page_offset;
packet->page_buf[i+npg_data+1].len = skb_frag_size(f);
}

/* Set the completion routine */
Expand Down Expand Up @@ -300,6 +317,39 @@ static void netvsc_get_drvinfo(struct net_device *net,
strcpy(info->fw_version, "N/A");
}

static int netvsc_change_mtu(struct net_device *ndev, int mtu)
{
struct net_device_context *ndevctx = netdev_priv(ndev);
struct hv_device *hdev = ndevctx->device_ctx;
struct netvsc_device *nvdev = hv_get_drvdata(hdev);
struct netvsc_device_info device_info;
int limit = ETH_DATA_LEN;

if (nvdev == NULL || nvdev->destroy)
return -ENODEV;

if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2)
limit = NETVSC_MTU;

if (mtu < 68 || mtu > limit)
return -EINVAL;

nvdev->start_remove = true;
cancel_delayed_work_sync(&ndevctx->dwork);
netif_stop_queue(ndev);
rndis_filter_device_remove(hdev);

ndev->mtu = mtu;

ndevctx->device_ctx = hdev;
hv_set_drvdata(hdev, ndev);
device_info.ring_size = ring_size;
rndis_filter_device_add(hdev, &device_info);
netif_wake_queue(ndev);

return 0;
}

static const struct ethtool_ops ethtool_ops = {
.get_drvinfo = netvsc_get_drvinfo,
.get_link = ethtool_op_get_link,
Expand All @@ -310,7 +360,7 @@ static const struct net_device_ops device_ops = {
.ndo_stop = netvsc_close,
.ndo_start_xmit = netvsc_start_xmit,
.ndo_set_rx_mode = netvsc_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_change_mtu = netvsc_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
};
Expand Down Expand Up @@ -403,6 +453,8 @@ static int netvsc_remove(struct hv_device *dev)
return 0;
}

net_device->start_remove = true;

ndev_ctx = netdev_priv(net);
cancel_delayed_work_sync(&ndev_ctx->dwork);

Expand Down
2 changes: 1 addition & 1 deletion trunk/include/linux/hyperv.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include <linux/mod_devicetable.h>


#define MAX_PAGE_BUFFER_COUNT 16
#define MAX_PAGE_BUFFER_COUNT 18
#define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */

#pragma pack(push, 1)
Expand Down

0 comments on commit e489f98

Please sign in to comment.