]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/net/xen-netfront.c
net: phy: phylink: fix uninitialized variable in phylink_get_mac_state
[mirror_ubuntu-bionic-kernel.git] / drivers / net / xen-netfront.c
index 9bd7ddeeb6a5c7b29569e51ad2f469d9fe493a76..c98766c324f04fc6254225df28a967ee94d68ad0 100644 (file)
@@ -87,7 +87,7 @@ struct netfront_cb {
 /* IRQ name is queue name with "-tx" or "-rx" appended */
 #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)
 
-static DECLARE_WAIT_QUEUE_HEAD(module_unload_q);
+static DECLARE_WAIT_QUEUE_HEAD(module_wq);
 
 struct netfront_stats {
        u64                     packets;
@@ -239,7 +239,7 @@ static void rx_refill_timeout(struct timer_list *t)
 static int netfront_tx_slot_available(struct netfront_queue *queue)
 {
        return (queue->tx.req_prod_pvt - queue->tx.rsp_cons) <
-               (NET_TX_RING_SIZE - MAX_SKB_FRAGS - 2);
+               (NET_TX_RING_SIZE - XEN_NETIF_NR_SLOTS_MIN - 1);
 }
 
 static void xennet_maybe_wake_tx(struct netfront_queue *queue)
@@ -351,6 +351,9 @@ static int xennet_open(struct net_device *dev)
        unsigned int i = 0;
        struct netfront_queue *queue = NULL;
 
+       if (!np->queues)
+               return -ENODEV;
+
        for (i = 0; i < num_queues; ++i) {
                queue = &np->queues[i];
                napi_enable(&queue->napi);
@@ -787,7 +790,7 @@ static int xennet_get_responses(struct netfront_queue *queue,
        RING_IDX cons = queue->rx.rsp_cons;
        struct sk_buff *skb = xennet_get_rx_skb(queue, cons);
        grant_ref_t ref = xennet_get_rx_ref(queue, cons);
-       int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
+       int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD);
        int slots = 1;
        int err = 0;
        unsigned long ret;
@@ -890,7 +893,6 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
                                  struct sk_buff *skb,
                                  struct sk_buff_head *list)
 {
-       struct skb_shared_info *shinfo = skb_shinfo(skb);
        RING_IDX cons = queue->rx.rsp_cons;
        struct sk_buff *nskb;
 
@@ -899,15 +901,20 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
                        RING_GET_RESPONSE(&queue->rx, ++cons);
                skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];
 
-               if (shinfo->nr_frags == MAX_SKB_FRAGS) {
+               if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) {
                        unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
 
-                       BUG_ON(pull_to <= skb_headlen(skb));
+                       BUG_ON(pull_to < skb_headlen(skb));
                        __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
                }
-               BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS);
+               if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) {
+                       queue->rx.rsp_cons = ++cons;
+                       kfree_skb(nskb);
+                       return ~0U;
+               }
 
-               skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag),
+               skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+                               skb_frag_page(nfrag),
                                rx->offset, rx->status, PAGE_SIZE);
 
                skb_shinfo(nskb)->nr_frags = 0;
@@ -1041,6 +1048,8 @@ err:
                skb->len += rx->status;
 
                i = xennet_fill_frags(queue, skb, &tmpq);
+               if (unlikely(i == ~0U))
+                       goto err;
 
                if (rx->flags & XEN_NETRXF_csum_blank)
                        skb->ip_summed = CHECKSUM_PARTIAL;
@@ -1327,6 +1336,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
        netif_carrier_off(netdev);
 
        xenbus_switch_state(dev, XenbusStateInitialising);
+       wait_event(module_wq,
+                  xenbus_read_driver_state(dev->otherend) !=
+                  XenbusStateClosed &&
+                  xenbus_read_driver_state(dev->otherend) !=
+                  XenbusStateUnknown);
        return netdev;
 
  exit:
@@ -1358,18 +1372,8 @@ static int netfront_probe(struct xenbus_device *dev,
 #ifdef CONFIG_SYSFS
        info->netdev->sysfs_groups[0] = &xennet_dev_group;
 #endif
-       err = register_netdev(info->netdev);
-       if (err) {
-               pr_warn("%s: register_netdev err=%d\n", __func__, err);
-               goto fail;
-       }
 
        return 0;
-
- fail:
-       xennet_free_netdev(netdev);
-       dev_set_drvdata(&dev->dev, NULL);
-       return err;
 }
 
 static void xennet_end_access(int ref, void *page)
@@ -1604,14 +1608,16 @@ static int xennet_init_queue(struct netfront_queue *queue)
 {
        unsigned short i;
        int err = 0;
+       char *devid;
 
        spin_lock_init(&queue->tx_lock);
        spin_lock_init(&queue->rx_lock);
 
        timer_setup(&queue->rx_refill_timer, rx_refill_timeout, 0);
 
-       snprintf(queue->name, sizeof(queue->name), "%s-q%u",
-                queue->info->netdev->name, queue->id);
+       devid = strrchr(queue->info->xbdev->nodename, '/') + 1;
+       snprintf(queue->name, sizeof(queue->name), "vif%s-q%u",
+                devid, queue->id);
 
        /* Initialise tx_skbs as a free chain containing every entry. */
        queue->tx_skb_freelist = 0;
@@ -1737,8 +1743,6 @@ static void xennet_destroy_queues(struct netfront_info *info)
 {
        unsigned int i;
 
-       rtnl_lock();
-
        for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
                struct netfront_queue *queue = &info->queues[i];
 
@@ -1747,8 +1751,6 @@ static void xennet_destroy_queues(struct netfront_info *info)
                netif_napi_del(&queue->napi);
        }
 
-       rtnl_unlock();
-
        kfree(info->queues);
        info->queues = NULL;
 }
@@ -1764,8 +1766,6 @@ static int xennet_create_queues(struct netfront_info *info,
        if (!info->queues)
                return -ENOMEM;
 
-       rtnl_lock();
-
        for (i = 0; i < *num_queues; i++) {
                struct netfront_queue *queue = &info->queues[i];
 
@@ -1774,7 +1774,7 @@ static int xennet_create_queues(struct netfront_info *info,
 
                ret = xennet_init_queue(queue);
                if (ret < 0) {
-                       dev_warn(&info->netdev->dev,
+                       dev_warn(&info->xbdev->dev,
                                 "only created %d queues\n", i);
                        *num_queues = i;
                        break;
@@ -1788,10 +1788,8 @@ static int xennet_create_queues(struct netfront_info *info,
 
        netif_set_real_num_tx_queues(info->netdev, *num_queues);
 
-       rtnl_unlock();
-
        if (*num_queues == 0) {
-               dev_err(&info->netdev->dev, "no queues\n");
+               dev_err(&info->xbdev->dev, "no queues\n");
                return -EINVAL;
        }
        return 0;
@@ -1825,9 +1823,10 @@ static int talk_to_netback(struct xenbus_device *dev,
        err = xen_net_read_mac(dev, info->netdev->dev_addr);
        if (err) {
                xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
-               goto out;
+               goto out_unlocked;
        }
 
+       rtnl_lock();
        if (info->queues)
                xennet_destroy_queues(info);
 
@@ -1838,6 +1837,7 @@ static int talk_to_netback(struct xenbus_device *dev,
                info->queues = NULL;
                goto out;
        }
+       rtnl_unlock();
 
        /* Create shared ring, alloc event channel -- for each queue */
        for (i = 0; i < num_queues; ++i) {
@@ -1934,8 +1934,11 @@ abort_transaction_no_dev_fatal:
        xenbus_transaction_end(xbt, 1);
  destroy_ring:
        xennet_disconnect_backend(info);
+       rtnl_lock();
        xennet_destroy_queues(info);
  out:
+       rtnl_unlock();
+out_unlocked:
        device_unregister(&dev->dev);
        return err;
 }
@@ -1961,6 +1964,15 @@ static int xennet_connect(struct net_device *dev)
        /* talk_to_netback() sets the correct number of queues */
        num_queues = dev->real_num_tx_queues;
 
+       if (dev->reg_state == NETREG_UNINITIALIZED) {
+               err = register_netdev(dev);
+               if (err) {
+                       pr_warn("%s: register_netdev err=%d\n", __func__, err);
+                       device_unregister(&np->xbdev->dev);
+                       return err;
+               }
+       }
+
        rtnl_lock();
        netdev_update_features(dev);
        rtnl_unlock();
@@ -2002,6 +2014,8 @@ static void netback_changed(struct xenbus_device *dev,
 
        dev_dbg(&dev->dev, "%s\n", xenbus_strstate(backend_state));
 
+       wake_up_all(&module_wq);
+
        switch (backend_state) {
        case XenbusStateInitialising:
        case XenbusStateInitialised:
@@ -2023,12 +2037,10 @@ static void netback_changed(struct xenbus_device *dev,
                break;
 
        case XenbusStateClosed:
-               wake_up_all(&module_unload_q);
                if (dev->state == XenbusStateClosed)
                        break;
                /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
-               wake_up_all(&module_unload_q);
                xenbus_frontend_closed(dev);
                break;
        }
@@ -2136,12 +2148,14 @@ static int xennet_remove(struct xenbus_device *dev)
 
        if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) {
                xenbus_switch_state(dev, XenbusStateClosing);
-               wait_event(module_unload_q,
+               wait_event(module_wq,
+                          xenbus_read_driver_state(dev->otherend) ==
+                          XenbusStateClosing ||
                           xenbus_read_driver_state(dev->otherend) ==
-                          XenbusStateClosing);
+                          XenbusStateUnknown);
 
                xenbus_switch_state(dev, XenbusStateClosed);
-               wait_event(module_unload_q,
+               wait_event(module_wq,
                           xenbus_read_driver_state(dev->otherend) ==
                           XenbusStateClosed ||
                           xenbus_read_driver_state(dev->otherend) ==
@@ -2150,10 +2164,14 @@ static int xennet_remove(struct xenbus_device *dev)
 
        xennet_disconnect_backend(info);
 
-       unregister_netdev(info->netdev);
+       if (info->netdev->reg_state == NETREG_REGISTERED)
+               unregister_netdev(info->netdev);
 
-       if (info->queues)
+       if (info->queues) {
+               rtnl_lock();
                xennet_destroy_queues(info);
+               rtnl_unlock();
+       }
        xennet_free_netdev(info->netdev);
 
        return 0;