diff options
Diffstat (limited to 'net/ipv4/ipconfig.c')
-rw-r--r-- | net/ipv4/ipconfig.c | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 10a6a604bf32..067ce9e043dc 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/root_dev.h> | 53 | #include <linux/root_dev.h> |
54 | #include <linux/delay.h> | 54 | #include <linux/delay.h> |
55 | #include <linux/nfs_fs.h> | 55 | #include <linux/nfs_fs.h> |
56 | #include <linux/slab.h> | ||
56 | #include <net/net_namespace.h> | 57 | #include <net/net_namespace.h> |
57 | #include <net/arp.h> | 58 | #include <net/arp.h> |
58 | #include <net/ip.h> | 59 | #include <net/ip.h> |
@@ -187,6 +188,16 @@ struct ic_device { | |||
187 | static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ | 188 | static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ |
188 | static struct net_device *ic_dev __initdata = NULL; /* Selected device */ | 189 | static struct net_device *ic_dev __initdata = NULL; /* Selected device */ |
189 | 190 | ||
191 | static bool __init ic_device_match(struct net_device *dev) | ||
192 | { | ||
193 | if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : | ||
194 | (!(dev->flags & IFF_LOOPBACK) && | ||
195 | (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && | ||
196 | strncmp(dev->name, "dummy", 5))) | ||
197 | return true; | ||
198 | return false; | ||
199 | } | ||
200 | |||
190 | static int __init ic_open_devs(void) | 201 | static int __init ic_open_devs(void) |
191 | { | 202 | { |
192 | struct ic_device *d, **last; | 203 | struct ic_device *d, **last; |
@@ -207,10 +218,7 @@ static int __init ic_open_devs(void) | |||
207 | for_each_netdev(&init_net, dev) { | 218 | for_each_netdev(&init_net, dev) { |
208 | if (dev->flags & IFF_LOOPBACK) | 219 | if (dev->flags & IFF_LOOPBACK) |
209 | continue; | 220 | continue; |
210 | if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : | 221 | if (ic_device_match(dev)) { |
211 | (!(dev->flags & IFF_LOOPBACK) && | ||
212 | (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && | ||
213 | strncmp(dev->name, "dummy", 5))) { | ||
214 | int able = 0; | 222 | int able = 0; |
215 | if (dev->mtu >= 364) | 223 | if (dev->mtu >= 364) |
216 | able |= IC_BOOTP; | 224 | able |= IC_BOOTP; |
@@ -228,7 +236,7 @@ static int __init ic_open_devs(void) | |||
228 | } | 236 | } |
229 | if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { | 237 | if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { |
230 | rtnl_unlock(); | 238 | rtnl_unlock(); |
231 | return -1; | 239 | return -ENOMEM; |
232 | } | 240 | } |
233 | d->dev = dev; | 241 | d->dev = dev; |
234 | *last = d; | 242 | *last = d; |
@@ -253,7 +261,7 @@ static int __init ic_open_devs(void) | |||
253 | printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name); | 261 | printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name); |
254 | else | 262 | else |
255 | printk(KERN_ERR "IP-Config: No network devices available.\n"); | 263 | printk(KERN_ERR "IP-Config: No network devices available.\n"); |
256 | return -1; | 264 | return -ENODEV; |
257 | } | 265 | } |
258 | return 0; | 266 | return 0; |
259 | } | 267 | } |
@@ -1303,6 +1311,32 @@ __be32 __init root_nfs_parse_addr(char *name) | |||
1303 | return addr; | 1311 | return addr; |
1304 | } | 1312 | } |
1305 | 1313 | ||
1314 | #define DEVICE_WAIT_MAX 12 /* 12 seconds */ | ||
1315 | |||
1316 | static int __init wait_for_devices(void) | ||
1317 | { | ||
1318 | int i; | ||
1319 | |||
1320 | msleep(CONF_PRE_OPEN); | ||
1321 | for (i = 0; i < DEVICE_WAIT_MAX; i++) { | ||
1322 | struct net_device *dev; | ||
1323 | int found = 0; | ||
1324 | |||
1325 | rtnl_lock(); | ||
1326 | for_each_netdev(&init_net, dev) { | ||
1327 | if (ic_device_match(dev)) { | ||
1328 | found = 1; | ||
1329 | break; | ||
1330 | } | ||
1331 | } | ||
1332 | rtnl_unlock(); | ||
1333 | if (found) | ||
1334 | return 0; | ||
1335 | ssleep(1); | ||
1336 | } | ||
1337 | return -ENODEV; | ||
1338 | } | ||
1339 | |||
1306 | /* | 1340 | /* |
1307 | * IP Autoconfig dispatcher. | 1341 | * IP Autoconfig dispatcher. |
1308 | */ | 1342 | */ |
@@ -1313,6 +1347,7 @@ static int __init ip_auto_config(void) | |||
1313 | #ifdef IPCONFIG_DYNAMIC | 1347 | #ifdef IPCONFIG_DYNAMIC |
1314 | int retries = CONF_OPEN_RETRIES; | 1348 | int retries = CONF_OPEN_RETRIES; |
1315 | #endif | 1349 | #endif |
1350 | int err; | ||
1316 | 1351 | ||
1317 | #ifdef CONFIG_PROC_FS | 1352 | #ifdef CONFIG_PROC_FS |
1318 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); | 1353 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); |
@@ -1325,12 +1360,15 @@ static int __init ip_auto_config(void) | |||
1325 | #ifdef IPCONFIG_DYNAMIC | 1360 | #ifdef IPCONFIG_DYNAMIC |
1326 | try_try_again: | 1361 | try_try_again: |
1327 | #endif | 1362 | #endif |
1328 | /* Give hardware a chance to settle */ | 1363 | /* Wait for devices to appear */ |
1329 | msleep(CONF_PRE_OPEN); | 1364 | err = wait_for_devices(); |
1365 | if (err) | ||
1366 | return err; | ||
1330 | 1367 | ||
1331 | /* Setup all network devices */ | 1368 | /* Setup all network devices */ |
1332 | if (ic_open_devs() < 0) | 1369 | err = ic_open_devs(); |
1333 | return -1; | 1370 | if (err) |
1371 | return err; | ||
1334 | 1372 | ||
1335 | /* Give drivers a chance to settle */ | 1373 | /* Give drivers a chance to settle */ |
1336 | ssleep(CONF_POST_OPEN); | 1374 | ssleep(CONF_POST_OPEN); |