aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-03-12 03:00:17 -0500
committerDavid S. Miller <davem@davemloft.net>2010-03-12 03:00:17 -0500
commit964ad81cbd933e5fa310faeec1e923c14651284b (patch)
tree35b2be921745d6a3077cb363d96eceea68eb318d /net/ipv4
parent717ea4b3474852057b1ce2c639ce219f4f8d3a8d (diff)
ipconfig: Handle devices which take some time to come up.
Some network devices, particularly USB ones, take several seconds to fully init and appear in the device list. If the user turned ipconfig on, they are using it for NFS root or some other early booting purpose. So it makes no sense to just flat out fail immediately if the device isn't found. It also doesn't make sense to just jack up the initial wait to something crazy like 10 seconds. Instead, poll immediately, and then periodically once a second, waiting for a usable device to appear. Fail after 12 seconds. Signed-off-by: David S. Miller <davem@davemloft.net> Tested-by: Christian Pellegrin <chripell@fsfe.org>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ipconfig.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 10a6a604bf32..678909281648 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -187,6 +187,16 @@ struct ic_device {
187static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ 187static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
188static struct net_device *ic_dev __initdata = NULL; /* Selected device */ 188static struct net_device *ic_dev __initdata = NULL; /* Selected device */
189 189
190static bool __init ic_device_match(struct net_device *dev)
191{
192 if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
193 (!(dev->flags & IFF_LOOPBACK) &&
194 (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
195 strncmp(dev->name, "dummy", 5)))
196 return true;
197 return false;
198}
199
190static int __init ic_open_devs(void) 200static int __init ic_open_devs(void)
191{ 201{
192 struct ic_device *d, **last; 202 struct ic_device *d, **last;
@@ -207,10 +217,7 @@ static int __init ic_open_devs(void)
207 for_each_netdev(&init_net, dev) { 217 for_each_netdev(&init_net, dev) {
208 if (dev->flags & IFF_LOOPBACK) 218 if (dev->flags & IFF_LOOPBACK)
209 continue; 219 continue;
210 if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : 220 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; 221 int able = 0;
215 if (dev->mtu >= 364) 222 if (dev->mtu >= 364)
216 able |= IC_BOOTP; 223 able |= IC_BOOTP;
@@ -228,7 +235,7 @@ static int __init ic_open_devs(void)
228 } 235 }
229 if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { 236 if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) {
230 rtnl_unlock(); 237 rtnl_unlock();
231 return -1; 238 return -ENOMEM;
232 } 239 }
233 d->dev = dev; 240 d->dev = dev;
234 *last = d; 241 *last = d;
@@ -253,7 +260,7 @@ static int __init ic_open_devs(void)
253 printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name); 260 printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name);
254 else 261 else
255 printk(KERN_ERR "IP-Config: No network devices available.\n"); 262 printk(KERN_ERR "IP-Config: No network devices available.\n");
256 return -1; 263 return -ENODEV;
257 } 264 }
258 return 0; 265 return 0;
259} 266}
@@ -1303,6 +1310,32 @@ __be32 __init root_nfs_parse_addr(char *name)
1303 return addr; 1310 return addr;
1304} 1311}
1305 1312
1313#define DEVICE_WAIT_MAX 12 /* 12 seconds */
1314
1315static int __init wait_for_devices(void)
1316{
1317 int i;
1318
1319 msleep(CONF_PRE_OPEN);
1320 for (i = 0; i < DEVICE_WAIT_MAX; i++) {
1321 struct net_device *dev;
1322 int found = 0;
1323
1324 rtnl_lock();
1325 for_each_netdev(&init_net, dev) {
1326 if (ic_device_match(dev)) {
1327 found = 1;
1328 break;
1329 }
1330 }
1331 rtnl_unlock();
1332 if (found)
1333 return 0;
1334 ssleep(1);
1335 }
1336 return -ENODEV;
1337}
1338
1306/* 1339/*
1307 * IP Autoconfig dispatcher. 1340 * IP Autoconfig dispatcher.
1308 */ 1341 */
@@ -1313,6 +1346,7 @@ static int __init ip_auto_config(void)
1313#ifdef IPCONFIG_DYNAMIC 1346#ifdef IPCONFIG_DYNAMIC
1314 int retries = CONF_OPEN_RETRIES; 1347 int retries = CONF_OPEN_RETRIES;
1315#endif 1348#endif
1349 int err;
1316 1350
1317#ifdef CONFIG_PROC_FS 1351#ifdef CONFIG_PROC_FS
1318 proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); 1352 proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops);
@@ -1325,12 +1359,15 @@ static int __init ip_auto_config(void)
1325#ifdef IPCONFIG_DYNAMIC 1359#ifdef IPCONFIG_DYNAMIC
1326 try_try_again: 1360 try_try_again:
1327#endif 1361#endif
1328 /* Give hardware a chance to settle */ 1362 /* Wait for devices to appear */
1329 msleep(CONF_PRE_OPEN); 1363 err = wait_for_devices();
1364 if (err)
1365 return err;
1330 1366
1331 /* Setup all network devices */ 1367 /* Setup all network devices */
1332 if (ic_open_devs() < 0) 1368 err = ic_open_devs();
1333 return -1; 1369 if (err)
1370 return err;
1334 1371
1335 /* Give drivers a chance to settle */ 1372 /* Give drivers a chance to settle */
1336 ssleep(CONF_POST_OPEN); 1373 ssleep(CONF_POST_OPEN);