Merge branch 'drm-ttm-unmappable' into drm-core-next
[pandora-kernel.git] / net / ipv4 / ipconfig.c
index 10a6a60..067ce9e 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/root_dev.h>
 #include <linux/delay.h>
 #include <linux/nfs_fs.h>
+#include <linux/slab.h>
 #include <net/net_namespace.h>
 #include <net/arp.h>
 #include <net/ip.h>
@@ -187,6 +188,16 @@ struct ic_device {
 static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
 static struct net_device *ic_dev __initdata = NULL;    /* Selected device */
 
+static bool __init ic_device_match(struct net_device *dev)
+{
+       if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
+           (!(dev->flags & IFF_LOOPBACK) &&
+            (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
+            strncmp(dev->name, "dummy", 5)))
+               return true;
+       return false;
+}
+
 static int __init ic_open_devs(void)
 {
        struct ic_device *d, **last;
@@ -207,10 +218,7 @@ static int __init ic_open_devs(void)
        for_each_netdev(&init_net, dev) {
                if (dev->flags & IFF_LOOPBACK)
                        continue;
-               if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
-                   (!(dev->flags & IFF_LOOPBACK) &&
-                    (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
-                    strncmp(dev->name, "dummy", 5))) {
+               if (ic_device_match(dev)) {
                        int able = 0;
                        if (dev->mtu >= 364)
                                able |= IC_BOOTP;
@@ -228,7 +236,7 @@ static int __init ic_open_devs(void)
                        }
                        if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
                                rtnl_unlock();
-                               return -1;
+                               return -ENOMEM;
                        }
                        d->dev = dev;
                        *last = d;
@@ -253,7 +261,7 @@ static int __init ic_open_devs(void)
                        printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name);
                else
                        printk(KERN_ERR "IP-Config: No network devices available.\n");
-               return -1;
+               return -ENODEV;
        }
        return 0;
 }
@@ -1303,6 +1311,32 @@ __be32 __init root_nfs_parse_addr(char *name)
        return addr;
 }
 
+#define DEVICE_WAIT_MAX                12 /* 12 seconds */
+
+static int __init wait_for_devices(void)
+{
+       int i;
+
+       msleep(CONF_PRE_OPEN);
+       for (i = 0; i < DEVICE_WAIT_MAX; i++) {
+               struct net_device *dev;
+               int found = 0;
+
+               rtnl_lock();
+               for_each_netdev(&init_net, dev) {
+                       if (ic_device_match(dev)) {
+                               found = 1;
+                               break;
+                       }
+               }
+               rtnl_unlock();
+               if (found)
+                       return 0;
+               ssleep(1);
+       }
+       return -ENODEV;
+}
+
 /*
  *     IP Autoconfig dispatcher.
  */
@@ -1313,6 +1347,7 @@ static int __init ip_auto_config(void)
 #ifdef IPCONFIG_DYNAMIC
        int retries = CONF_OPEN_RETRIES;
 #endif
+       int err;
 
 #ifdef CONFIG_PROC_FS
        proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops);
@@ -1325,12 +1360,15 @@ static int __init ip_auto_config(void)
 #ifdef IPCONFIG_DYNAMIC
  try_try_again:
 #endif
-       /* Give hardware a chance to settle */
-       msleep(CONF_PRE_OPEN);
+       /* Wait for devices to appear */
+       err = wait_for_devices();
+       if (err)
+               return err;
 
        /* Setup all network devices */
-       if (ic_open_devs() < 0)
-               return -1;
+       err = ic_open_devs();
+       if (err)
+               return err;
 
        /* Give drivers a chance to settle */
        ssleep(CONF_POST_OPEN);