net/mlx4_en: Fix mixed PFC and Global pause user control requests
[pandora-kernel.git] / net / tipc / eth_media.c
index e728d4c..2e79e84 100644 (file)
@@ -53,6 +53,7 @@ struct eth_bearer {
        struct tipc_bearer *bearer;
        struct net_device *dev;
        struct packet_type tipc_packet_type;
+       struct work_struct setup;
 };
 
 static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
@@ -120,6 +121,17 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
        return 0;
 }
 
+/**
+ * setup_bearer - setup association between Ethernet bearer and interface
+ */
+static void setup_bearer(struct work_struct *work)
+{
+       struct eth_bearer *eb_ptr =
+               container_of(work, struct eth_bearer, setup);
+
+       dev_add_pack(&eb_ptr->tipc_packet_type);
+}
+
 /**
  * enable_bearer - attach TIPC bearer to an Ethernet interface
  */
@@ -155,6 +167,10 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
        read_unlock(&dev_base_lock);
        if (!dev)
                return -ENODEV;
+       if (tipc_mtu_bad(dev, 0)) {
+               dev_put(dev);
+               return -EINVAL;
+       }
 
        /* Create Ethernet bearer for device */
 
@@ -164,7 +180,8 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
        eb_ptr->tipc_packet_type.func = recv_msg;
        eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
        INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
-       dev_add_pack(&eb_ptr->tipc_packet_type);
+       INIT_WORK(&eb_ptr->setup, setup_bearer);
+       schedule_work(&eb_ptr->setup);
 
        /* Associate TIPC bearer with Ethernet bearer */
 
@@ -214,8 +231,6 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
        if (!eb_ptr->bearer)
                return NOTIFY_DONE;             /* bearer had been disabled */
 
-       eb_ptr->bearer->mtu = dev->mtu;
-
        switch (evt) {
        case NETDEV_CHANGE:
                if (netif_carrier_ok(dev))
@@ -230,6 +245,12 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
                tipc_block_bearer(eb_ptr->bearer->name);
                break;
        case NETDEV_CHANGEMTU:
+               if (tipc_mtu_bad(dev, 0)) {
+                       tipc_disable_bearer(eb_ptr->bearer->name);
+                       break;
+               }
+               eb_ptr->bearer->mtu = dev->mtu;
+               /* fall through */
        case NETDEV_CHANGEADDR:
                tipc_block_bearer(eb_ptr->bearer->name);
                tipc_continue(eb_ptr->bearer);