Staging: hv: vmbus: Introduce a utility function to match hv_vmbus_device_id
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / hv / netvsc_drv.c
index 61989f0d9f0d34faf68d25d637aea35b0392fef9..30b9c80e2009db8bbe2cd8a833ec0818b4d4b61d 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/in.h>
 #include <linux/slab.h>
-#include <linux/dmi.h>
-#include <linux/pci.h>
 #include <net/arp.h>
 #include <net/route.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
-#include "hyperv.h"
 #include "hyperv_net.h"
 
 struct net_device_context {
@@ -143,12 +140,12 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
                         (num_pages * sizeof(struct hv_page_buffer)) +
                         sizeof(struct rndis_filter_packet), GFP_ATOMIC);
        if (!packet) {
-               /* out of memory, silently drop packet */
+               /* out of memory, drop packet */
                netdev_err(net, "unable to allocate hv_netvsc_packet\n");
 
                dev_kfree_skb(skb);
                net->stats.tx_dropped++;
-               return NETDEV_TX_OK;
+               return NETDEV_TX_BUSY;
        }
 
        packet->extension = (void *)(unsigned long)packet +
@@ -193,10 +190,11 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
        } else {
                /* we are shutting down or bus overloaded, just drop packet */
                net->stats.tx_dropped++;
-               netvsc_xmit_completion(packet);
+               kfree(packet);
+               dev_kfree_skb_any(skb);
        }
 
-       return NETDEV_TX_OK;
+       return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
 }
 
 /*
@@ -217,8 +215,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
        if (status == 1) {
                netif_carrier_on(net);
                netif_wake_queue(net);
-               netif_notify_peers(net);
                ndev_ctx = netdev_priv(net);
+               schedule_delayed_work(&ndev_ctx->dwork, 0);
                schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
        } else {
                netif_carrier_off(net);
@@ -340,7 +338,7 @@ static int netvsc_probe(struct hv_device *dev)
 
        net = alloc_etherdev(sizeof(struct net_device_context));
        if (!net)
-               return -1;
+               return -ENOMEM;
 
        /* Set initial state */
        netif_carrier_off(net);
@@ -351,21 +349,6 @@ static int netvsc_probe(struct hv_device *dev)
        dev_set_drvdata(&dev->device, net);
        INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
 
-       /* Notify the netvsc driver of the new device */
-       device_info.ring_size = ring_size;
-       ret = rndis_filter_device_add(dev, &device_info);
-       if (ret != 0) {
-               free_netdev(net);
-               dev_set_drvdata(&dev->device, NULL);
-
-               netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
-               return ret;
-       }
-
-       netif_carrier_on(net);
-
-       memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
-
        net->netdev_ops = &device_ops;
 
        /* TODO: Add GSO and Checksum offload */
@@ -377,11 +360,26 @@ static int netvsc_probe(struct hv_device *dev)
 
        ret = register_netdev(net);
        if (ret != 0) {
-               /* Remove the device and release the resource */
-               rndis_filter_device_remove(dev);
+               pr_err("Unable to register netdev.\n");
                free_netdev(net);
+               goto out;
        }
 
+       /* Notify the netvsc driver of the new device */
+       device_info.ring_size = ring_size;
+       ret = rndis_filter_device_add(dev, &device_info);
+       if (ret != 0) {
+               netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
+               unregister_netdev(net);
+               free_netdev(net);
+               dev_set_drvdata(&dev->device, NULL);
+               return ret;
+       }
+       memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+
+       netif_carrier_on(net);
+
+out:
        return ret;
 }
 
@@ -413,61 +411,33 @@ static int netvsc_remove(struct hv_device *dev)
        return 0;
 }
 
+static const struct hv_vmbus_device_id id_table[] = {
+       /* Network guid */
+       { VMBUS_DEVICE(0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
+                      0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E) },
+       { },
+};
+
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
 /* The one and only one */
 static struct  hv_driver netvsc_drv = {
+       .name = "netvsc",
+       .id_table = id_table,
        .probe = netvsc_probe,
        .remove = netvsc_remove,
 };
 
 static void __exit netvsc_drv_exit(void)
 {
-       vmbus_child_driver_unregister(&netvsc_drv.driver);
+       vmbus_driver_unregister(&netvsc_drv);
 }
 
-
-static const struct dmi_system_id __initconst
-hv_netvsc_dmi_table[] __maybe_unused  = {
-       {
-               .ident = "Hyper-V",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
-                       DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
-               },
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(dmi, hv_netvsc_dmi_table);
-
 static int __init netvsc_drv_init(void)
 {
-       struct hv_driver *drv = &netvsc_drv;
-       int ret;
-
-       pr_info("initializing....");
-
-       if (!dmi_check_system(hv_netvsc_dmi_table))
-               return -ENODEV;
-
-
-       /* Callback to client driver to complete the initialization */
-       netvsc_initialize(drv);
-
-       drv->driver.name = drv->name;
-
-       /* The driver belongs to vmbus */
-       ret = vmbus_child_driver_register(&drv->driver);
-
-       return ret;
+       return vmbus_driver_register(&netvsc_drv);
 }
 
-static const struct pci_device_id __initconst
-hv_netvsc_pci_table[] __maybe_unused = {
-       { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
-       { 0 }
-};
-MODULE_DEVICE_TABLE(pci, hv_netvsc_pci_table);
-
 MODULE_LICENSE("GPL");
 MODULE_VERSION(HV_DRV_VERSION);
 MODULE_DESCRIPTION("Microsoft Hyper-V network driver");