diff options
Diffstat (limited to 'drivers/net/hyperv/netvsc_drv.c')
| -rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 47 |
1 files changed, 21 insertions, 26 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index a3a9d3898a6e..5993c7e2d723 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
| @@ -40,18 +40,21 @@ | |||
| 40 | 40 | ||
| 41 | #include "hyperv_net.h" | 41 | #include "hyperv_net.h" |
| 42 | 42 | ||
| 43 | struct net_device_context { | ||
| 44 | /* point back to our device context */ | ||
| 45 | struct hv_device *device_ctx; | ||
| 46 | struct delayed_work dwork; | ||
| 47 | struct work_struct work; | ||
| 48 | }; | ||
| 49 | 43 | ||
| 50 | #define RING_SIZE_MIN 64 | 44 | #define RING_SIZE_MIN 64 |
| 51 | static int ring_size = 128; | 45 | static int ring_size = 128; |
| 52 | module_param(ring_size, int, S_IRUGO); | 46 | module_param(ring_size, int, S_IRUGO); |
| 53 | MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); | 47 | MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); |
| 54 | 48 | ||
| 49 | static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | | ||
| 50 | NETIF_MSG_LINK | NETIF_MSG_IFUP | | ||
| 51 | NETIF_MSG_IFDOWN | NETIF_MSG_RX_ERR | | ||
| 52 | NETIF_MSG_TX_ERR; | ||
| 53 | |||
| 54 | static int debug = -1; | ||
| 55 | module_param(debug, int, S_IRUGO); | ||
| 56 | MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); | ||
| 57 | |||
| 55 | static void do_set_multicast(struct work_struct *w) | 58 | static void do_set_multicast(struct work_struct *w) |
| 56 | { | 59 | { |
| 57 | struct net_device_context *ndevctx = | 60 | struct net_device_context *ndevctx = |
| @@ -235,9 +238,6 @@ void netvsc_xmit_completion(void *context) | |||
| 235 | struct sk_buff *skb = (struct sk_buff *) | 238 | struct sk_buff *skb = (struct sk_buff *) |
| 236 | (unsigned long)packet->send_completion_tid; | 239 | (unsigned long)packet->send_completion_tid; |
| 237 | 240 | ||
| 238 | if (!packet->part_of_skb) | ||
| 239 | kfree(packet); | ||
| 240 | |||
| 241 | if (skb) | 241 | if (skb) |
| 242 | dev_kfree_skb_any(skb); | 242 | dev_kfree_skb_any(skb); |
| 243 | } | 243 | } |
| @@ -389,7 +389,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
| 389 | u32 net_trans_info; | 389 | u32 net_trans_info; |
| 390 | u32 hash; | 390 | u32 hash; |
| 391 | u32 skb_length; | 391 | u32 skb_length; |
| 392 | u32 head_room; | ||
| 393 | u32 pkt_sz; | 392 | u32 pkt_sz; |
| 394 | struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT]; | 393 | struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT]; |
| 395 | 394 | ||
| @@ -402,7 +401,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
| 402 | 401 | ||
| 403 | check_size: | 402 | check_size: |
| 404 | skb_length = skb->len; | 403 | skb_length = skb->len; |
| 405 | head_room = skb_headroom(skb); | ||
| 406 | num_data_pgs = netvsc_get_slots(skb) + 2; | 404 | num_data_pgs = netvsc_get_slots(skb) + 2; |
| 407 | if (num_data_pgs > MAX_PAGE_BUFFER_COUNT && linear) { | 405 | if (num_data_pgs > MAX_PAGE_BUFFER_COUNT && linear) { |
| 408 | net_alert_ratelimited("packet too big: %u pages (%u bytes)\n", | 406 | net_alert_ratelimited("packet too big: %u pages (%u bytes)\n", |
| @@ -421,20 +419,14 @@ check_size: | |||
| 421 | 419 | ||
| 422 | pkt_sz = sizeof(struct hv_netvsc_packet) + RNDIS_AND_PPI_SIZE; | 420 | pkt_sz = sizeof(struct hv_netvsc_packet) + RNDIS_AND_PPI_SIZE; |
| 423 | 421 | ||
| 424 | if (head_room < pkt_sz) { | 422 | ret = skb_cow_head(skb, pkt_sz); |
| 425 | packet = kmalloc(pkt_sz, GFP_ATOMIC); | 423 | if (ret) { |
| 426 | if (!packet) { | 424 | netdev_err(net, "unable to alloc hv_netvsc_packet\n"); |
| 427 | /* out of memory, drop packet */ | 425 | ret = -ENOMEM; |
| 428 | netdev_err(net, "unable to alloc hv_netvsc_packet\n"); | 426 | goto drop; |
| 429 | ret = -ENOMEM; | ||
| 430 | goto drop; | ||
| 431 | } | ||
| 432 | packet->part_of_skb = false; | ||
| 433 | } else { | ||
| 434 | /* Use the headroom for building up the packet */ | ||
| 435 | packet = (struct hv_netvsc_packet *)skb->head; | ||
| 436 | packet->part_of_skb = true; | ||
| 437 | } | 427 | } |
| 428 | /* Use the headroom for building up the packet */ | ||
| 429 | packet = (struct hv_netvsc_packet *)skb->head; | ||
| 438 | 430 | ||
| 439 | packet->status = 0; | 431 | packet->status = 0; |
| 440 | packet->xmit_more = skb->xmit_more; | 432 | packet->xmit_more = skb->xmit_more; |
| @@ -591,8 +583,6 @@ drop: | |||
| 591 | net->stats.tx_bytes += skb_length; | 583 | net->stats.tx_bytes += skb_length; |
| 592 | net->stats.tx_packets++; | 584 | net->stats.tx_packets++; |
| 593 | } else { | 585 | } else { |
| 594 | if (packet && !packet->part_of_skb) | ||
| 595 | kfree(packet); | ||
| 596 | if (ret != -EAGAIN) { | 586 | if (ret != -EAGAIN) { |
| 597 | dev_kfree_skb_any(skb); | 587 | dev_kfree_skb_any(skb); |
| 598 | net->stats.tx_dropped++; | 588 | net->stats.tx_dropped++; |
| @@ -888,6 +878,11 @@ static int netvsc_probe(struct hv_device *dev, | |||
| 888 | 878 | ||
| 889 | net_device_ctx = netdev_priv(net); | 879 | net_device_ctx = netdev_priv(net); |
| 890 | net_device_ctx->device_ctx = dev; | 880 | net_device_ctx->device_ctx = dev; |
| 881 | net_device_ctx->msg_enable = netif_msg_init(debug, default_msg); | ||
| 882 | if (netif_msg_probe(net_device_ctx)) | ||
| 883 | netdev_dbg(net, "netvsc msg_enable: %d\n", | ||
| 884 | net_device_ctx->msg_enable); | ||
| 885 | |||
| 891 | hv_set_drvdata(dev, net); | 886 | hv_set_drvdata(dev, net); |
| 892 | INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); | 887 | INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); |
| 893 | INIT_WORK(&net_device_ctx->work, do_set_multicast); | 888 | INIT_WORK(&net_device_ctx->work, do_set_multicast); |
