Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@kernel.bkbits.net>2003-10-16 13:50:27 -0700
committerDavid S. Miller <davem@kernel.bkbits.net>2003-10-16 13:50:27 -0700
commitcb6d16119a649503e74d6c2b0493ff70e3737ed1 (patch)
treec1cfd301f4c9397a3be7a550a471d6669f3a5926
parent0068306ff7243e3499b6190740555693313e409b (diff)
parent21f6cbbba9b518f69b90bfdb4efd3a8c916b83ac (diff)
Merge davem@nuts.ninka.net:/disk1/davem/BK/net-2.5
into kernel.bkbits.net:/home/davem/net-2.5
-rw-r--r--drivers/atm/fore200e.c1
-rw-r--r--drivers/atm/he.c5
-rw-r--r--drivers/atm/lanai.c7
-rw-r--r--drivers/atm/nicstar.c21
-rw-r--r--drivers/net/myri_sbus.c43
-rw-r--r--drivers/net/net_init.c8
-rw-r--r--drivers/net/sis190.c2
-rw-r--r--drivers/net/sk98lin/skge.c67
-rw-r--r--drivers/net/sunbmac.c22
-rw-r--r--drivers/net/sunlance.c79
-rw-r--r--include/linux/etherdevice.h8
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/linux/rtnetlink.h6
-rw-r--r--include/net/if_inet6.h7
-rw-r--r--net/atm/proc.c6
-rw-r--r--net/core/dev.c32
-rw-r--r--net/core/net-sysfs.c1
-rw-r--r--net/ipv6/addrconf.c167
-rw-r--r--net/ipv6/anycast.c2
-rw-r--r--net/ipv6/mcast.c2
20 files changed, 342 insertions, 145 deletions
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 2193396a1a20..c699a20b4fb8 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -1071,7 +1071,6 @@ fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
struct sock *s;
struct atm_vcc* vcc;
struct hlist_node *node;
- int i;
read_lock(&vcc_sklist_lock);
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 253775c1019f..91cb2893aad9 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -157,7 +157,7 @@ static short nvpibits = -1;
static short nvcibits = -1;
static short rx_skb_reserve = 16;
static short irq_coalesce = 1;
-static short sdh = 1;
+static short sdh = 0;
static struct atmdev_ops he_ops =
{
@@ -1547,11 +1547,10 @@ he_start(struct atm_dev *dev)
if (sdh) {
/* this really should be in suni.c but for now... */
-
int val;
val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM);
- val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT);
+ val = (val & ~SUNI_TPOP_APM_S) | (SUNI_TPOP_S_SDH << SUNI_TPOP_APM_S_SHIFT);
he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);
}
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index cb99c67b5aba..402e78a5ac97 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -2432,11 +2432,11 @@ static int lanai_open(struct atm_vcc *atmvcc)
return result;
}
+#if 0
/* ioctl operations for card */
/* NOTE: these are all DEBUGGING ONLY currently */
static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg)
{
-#if 0
int result = 0;
struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
switch(cmd) {
@@ -2514,11 +2514,10 @@ static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg)
result = -ENOIOCTLCMD;
}
return result;
+}
#else /* !0 */
- (void) atmdev; (void) cmd; (void) arg; /* no compiler warnings */
- return -ENOIOCTLCMD;
+#define lanai_ioctl NULL
#endif /* 0 */
-}
static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb)
{
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 4fd82600163c..2473dc58e52a 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -1676,6 +1676,25 @@ static void ns_close(struct atm_vcc *vcc)
free_scq(vc->scq, vcc);
}
+ /* remove all references to vcc before deleting it */
+ if (vcc->qos.txtp.traffic_class != ATM_NONE)
+ {
+ unsigned long flags;
+ scq_info *scq = card->scq0;
+
+ ns_grab_scq_lock(card, scq, flags);
+
+ for(i = 0; i < scq->num_entries; i++) {
+ if(scq->skb[i] && ATM_SKB(scq->skb[i])->vcc == vcc) {
+ ATM_SKB(scq->skb[i])->vcc = NULL;
+ atm_return(vcc, scq->skb[i]->truesize);
+ PRINTK("nicstar: deleted pending vcc mapping\n");
+ }
+ }
+
+ spin_unlock_irqrestore(&scq->lock, flags);
+ }
+
vcc->dev_data = NULL;
clear_bit(ATM_VF_PARTIAL,&vcc->flags);
clear_bit(ATM_VF_ADDR,&vcc->flags);
@@ -2074,7 +2093,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos)
if (skb != NULL)
{
vcc = ATM_SKB(skb)->vcc;
- if (vcc->pop != NULL) {
+ if (vcc && vcc->pop != NULL) {
vcc->pop(vcc, skb);
} else {
dev_kfree_skb_irq(skb);
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 07ab72c68a5d..936f69f0e378 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -888,15 +888,16 @@ static void dump_eeprom(struct myri_eth *mp)
}
#endif
-static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, int num)
+static int __init myri_ether_init(struct sbus_dev *sdev, int num)
{
static unsigned version_printed;
+ struct net_device *dev;
struct myri_eth *mp;
unsigned char prop_buf[32];
int i;
- DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num));
- dev = init_etherdev(0, sizeof(struct myri_eth));
+ DET(("myri_ether_init(%p,%d):\n", sdev, num));
+ dev = alloc_etherdev(sizeof(struct myri_eth));
if (!dev)
return -ENOMEM;
@@ -904,8 +905,6 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
if (version_printed++ == 0)
printk(version);
- printk("%s: MyriCOM MyriNET Ethernet ", dev->name);
-
mp = (struct myri_eth *) dev->priv;
spin_lock_init(&mp->irq_lock);
mp->myri_sdev = sdev;
@@ -974,10 +973,7 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
#endif
for (i = 0; i < 6; i++)
- printk("%2.2x%c",
- dev->dev_addr[i] = mp->eeprom.id[i],
- i == 5 ? ' ' : ':');
- printk("\n");
+ dev->dev_addr[i] = mp->eeprom.id[i];
determine_reg_space_size(mp);
@@ -1072,9 +1068,6 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
goto err;
}
- DET(("ether_setup()\n"));
- ether_setup(dev);
-
dev->mtu = MYRINET_MTU;
dev->change_mtu = myri_change_mtu;
dev->hard_header = myri_header;
@@ -1087,15 +1080,30 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
DET(("Loading LANAI firmware\n"));
myri_load_lanai(mp);
+ if (register_netdev(dev)) {
+ printk("MyriCOM: Cannot register device.\n");
+ goto err_free_irq;
+ }
+
#ifdef MODULE
- dev->ifindex = dev_new_index();
mp->next_module = root_myri_dev;
root_myri_dev = mp;
#endif
+
+ printk("%s: MyriCOM MyriNET Ethernet ", dev->name);
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ i == 5 ? ' ' : ':');
+ printk("\n");
+
return 0;
-err: unregister_netdev(dev);
+
+err_free_irq:
+ free_irq(dev->irq, dev);
+err:
/* This will also free the co-allocated 'dev->priv' */
- kfree(dev);
+ free_netdev(dev);
return -ENODEV;
}
@@ -1112,7 +1120,6 @@ static int __init myri_sbus_match(struct sbus_dev *sdev)
static int __init myri_sbus_probe(void)
{
- struct net_device *dev = NULL;
struct sbus_bus *bus;
struct sbus_dev *sdev = 0;
static int called;
@@ -1128,12 +1135,10 @@ static int __init myri_sbus_probe(void)
for_each_sbus(bus) {
for_each_sbusdev(sdev, bus) {
- if (cards)
- dev = NULL;
if (myri_sbus_match(sdev)) {
cards++;
DET(("Found myricom myrinet as %s\n", sdev->prom_name));
- if ((v = myri_ether_init(dev, sdev, (cards - 1))))
+ if ((v = myri_ether_init(sdev, (cards - 1))))
return v;
}
}
diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c
index 0a5706e6c41d..a61eac6cc10e 100644
--- a/drivers/net/net_init.c
+++ b/drivers/net/net_init.c
@@ -197,9 +197,13 @@ static struct net_device *init_netdev(struct net_device *dev, int sizeof_priv,
*
* If an empty string area is passed as dev->name, or a new structure is made,
* a new name string is constructed.
+ *
+ * Deprecated because of exposed window between device registration
+ * and interfaces pointers that need to be set by driver.
+ * Use alloc_etherdev and register_netdev instead.
*/
-struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv)
+struct net_device *__init_etherdev(struct net_device *dev, int sizeof_priv)
{
return init_netdev(dev, sizeof_priv, "eth%d", ether_setup);
}
@@ -222,7 +226,7 @@ struct net_device *alloc_etherdev(int sizeof_priv)
return alloc_netdev(sizeof_priv, "eth%d", ether_setup);
}
-EXPORT_SYMBOL(init_etherdev);
+EXPORT_SYMBOL(__init_etherdev);
EXPORT_SYMBOL(alloc_etherdev);
static int eth_mac_addr(struct net_device *dev, void *p)
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 9f421480b233..aabe5f3bdd71 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -451,8 +451,6 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out,
*ioaddr_out = NULL;
*dev_out = NULL;
- // dev zeroed in init_etherdev
-
dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) {
printk(KERN_ERR PFX "unable to alloc new ethernet\n");
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 60cbb3d85690..5da46110913f 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -653,24 +653,16 @@ static int __init skge_probe (void)
continue;
- if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) {
+ if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
printk(KERN_ERR "Unable to allocate etherdev "
"structure!\n");
break;
}
- if (dev->priv == NULL) {
- printk(KERN_ERR "Unable to allocate adapter "
- "structure!\n");
- break;
- }
-
pNet = dev->priv;
pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
if (pNet->pAC == NULL){
- dev->get_stats = NULL;
- unregister_netdev(dev);
- kfree(dev->priv);
+ free_netdev(dev);
printk(KERN_ERR "Unable to allocate adapter "
"structure!\n");
break;
@@ -699,9 +691,7 @@ static int __init skge_probe (void)
retval = SkGeInitPCI(pAC);
if (retval) {
printk("SKGE: PCI setup failed: %i\n", retval);
- dev->get_stats = NULL;
- unregister_netdev(dev);
- kfree(dev);
+ free_netdev(dev);
continue;
}
@@ -730,13 +720,20 @@ static int __init skge_probe (void)
pAC->Index = boards_found;
if (SkGeBoardInit(dev, pAC)) {
FreeResources(dev);
- kfree(dev);
+ free_netdev(dev);
continue;
}
memcpy((caddr_t) &dev->dev_addr,
(caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
+ if (register_netdev(dev)) {
+ printk(KERN_ERR "SKGE: Could not register device.\n");
+ FreeResources(dev);
+ free_netdev(dev);
+ continue;
+ }
+
/* First adapter... Create proc and print message */
#ifdef CONFIG_PROC_FS
if (!DeviceFound) {
@@ -767,21 +764,11 @@ static int __init skge_probe (void)
pNet->PortNr = 0;
pNet->NetNr = 0;
-
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
- if (pAC->ChipsetType) {
- /* SG and ZEROCOPY - fly baby... */
- dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
- }
-#endif
-#endif
-
boards_found++;
/* More then one port found */
if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- if ((dev = init_etherdev(NULL, sizeof(DEV_NET))) == 0) {
+ if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
printk(KERN_ERR "Unable to allocate etherdev "
"structure!\n");
break;
@@ -814,22 +801,28 @@ static int __init skge_probe (void)
#endif
#endif
+ if (register_netdev(dev)) {
+ printk(KERN_ERR "SKGE: Could not register "
+ "second port.\n");
+ free_netdev(dev);
+ pAC->dev[1] = pAC->dev[0];
+ } else {
#ifdef CONFIG_PROC_FS
- if (pSkRootDir
- && (pProcFile = create_proc_entry(dev->name,
- S_IRUGO,
- pSkRootDir))) {
- pProcFile->proc_fops = &sk_proc_fops;
- pProcFile->data = dev;
- }
+ if (pSkRootDir
+ && (pProcFile = create_proc_entry(dev->name,
+ S_IRUGO,
+ pSkRootDir))) {
+ pProcFile->proc_fops = &sk_proc_fops;
+ pProcFile->data = dev;
+ }
#endif
- memcpy((caddr_t) &dev->dev_addr,
- (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
+ memcpy((caddr_t) &dev->dev_addr,
+ (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
- printk("%s: %s\n", dev->name, pAC->DeviceStr);
- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
-
+ printk("%s: %s\n", dev->name, pAC->DeviceStr);
+ printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+ }
}
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 03fca8b18282..323dbdd5acbc 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -1072,7 +1072,7 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
int i;
/* Get a new device struct for this interface. */
- dev = init_etherdev(NULL, sizeof(struct bigmac));
+ dev = alloc_etherdev(sizeof(struct bigmac));
if (!dev)
return -ENOMEM;
SET_MODULE_OWNER(dev);
@@ -1080,13 +1080,9 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
if (version_printed++ == 0)
printk(KERN_INFO "%s", version);
- /* Report what we have found to the user. */
- printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name);
dev->base_addr = (long) qec_sdev;
for (i = 0; i < 6; i++)
- printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i],
- i == 5 ? ' ' : ':');
- printk("\n");
+ dev->dev_addr[i] = idprom->id_ethaddr[i];
/* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */
bp = dev->priv;
@@ -1210,12 +1206,23 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
dev->irq = bp->bigmac_sdev->irqs[0];
dev->dma = 0;
+ if (register_netdev(dev)) {
+ printk(KERN_ERR "BIGMAC: Cannot register device.\n");
+ goto fail_and_cleanup;
+ }
+
/* Put us into the list of instances attached for later driver
* exit.
*/
bp->next_module = root_bigmac_dev;
root_bigmac_dev = bp;
+ printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name);
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ i == 5 ? ' ' : ':');
+ printk("\n");
+
return 0;
fail_and_cleanup:
@@ -1236,9 +1243,8 @@ fail_and_cleanup:
bp->bmac_block,
bp->bblock_dvma);
- unregister_netdev(dev);
/* This also frees the co-located 'dev->priv' */
- kfree(dev);
+ free_netdev(dev);
return -ENODEV;
}
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 232e4e947a5a..acb55250c3d8 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1312,32 +1312,24 @@ static struct ethtool_ops sparc_lance_ethtool_ops = {
.get_link = sparc_lance_get_link,
};
-static int __init sparc_lance_init(struct net_device *dev,
- struct sbus_dev *sdev,
+static int __init sparc_lance_init(struct sbus_dev *sdev,
struct sbus_dma *ledma,
struct sbus_dev *lebuffer)
{
static unsigned version_printed;
- struct lance_private *lp = NULL;
+ struct net_device *dev;
+ struct lance_private *lp;
int i;
- if (dev == NULL) {
- dev = init_etherdev (0, sizeof (struct lance_private) + 8);
- } else {
- dev->priv = kmalloc(sizeof (struct lance_private) + 8,
- GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
- memset(dev->priv, 0, sizeof (struct lance_private) + 8);
- }
+ dev = alloc_etherdev(sizeof(struct lance_private) + 8);
+ if (!dev)
+ return -ENOMEM;
+
+ lp = dev->priv;
+
if (sparc_lance_debug && version_printed++ == 0)
printk (KERN_INFO "%s", version);
- printk(KERN_INFO "%s: LANCE ", dev->name);
-
- /* Make certain the data structures used by the LANCE are aligned. */
- dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7);
- lp = (struct lance_private *) dev->priv;
spin_lock_init(&lp->lock);
/* Copy the IDPROM ethernet address to the device structure, later we
@@ -1345,16 +1337,13 @@ static int __init sparc_lance_init(struct net_device *dev,
* initialization block.
*/
for (i = 0; i < 6; i++)
- printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i],
- i == 5 ? ' ': ':');
- printk("\n");
+ dev->dev_addr[i] = idprom->id_ethaddr[i];
/* Get the IO region */
lp->lregs = sbus_ioremap(&sdev->resource[0], 0,
LANCE_REG_SIZE, lancestr);
if (lp->lregs == 0UL) {
- printk(KERN_ERR "%s: Cannot map SunLance registers.\n",
- dev->name);
+ printk(KERN_ERR "SunLance: Cannot map registers.\n");
goto fail;
}
@@ -1364,8 +1353,7 @@ static int __init sparc_lance_init(struct net_device *dev,
sbus_ioremap(&lebuffer->resource[0], 0,
sizeof(struct lance_init_block), "lebuffer");
if (lp->init_block == NULL) {
- printk(KERN_ERR "%s: Cannot map SunLance PIO buffer.\n",
- dev->name);
+ printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n");
goto fail;
}
lp->init_block_dvma = 0;
@@ -1379,8 +1367,7 @@ static int __init sparc_lance_init(struct net_device *dev,
&lp->init_block_dvma);
if (lp->init_block == NULL ||
lp->init_block_dvma == 0) {
- printk(KERN_ERR "%s: Cannot allocate consistent DMA memory.\n",
- dev->name);
+ printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n");
goto fail;
}
lp->pio_buffer = 0;
@@ -1418,8 +1405,7 @@ static int __init sparc_lance_init(struct net_device *dev,
if (prop[0] == 0) {
int topnd, nd;
- printk(KERN_INFO "%s: using auto-carrier-detection.\n",
- dev->name);
+ printk(KERN_INFO "SunLance: using auto-carrier-detection.\n");
/* Is this found at /options .attributes in all
* Prom versions? XXX
@@ -1438,10 +1424,10 @@ static int __init sparc_lance_init(struct net_device *dev,
sizeof(prop));
if (strcmp(prop, "true")) {
- printk(KERN_NOTICE "%s: warning: overriding option "
- "'tpe-link-test?'\n", dev->name);
- printk(KERN_NOTICE "%s: warning: mail any problems "
- "to ecd@skynet.be\n", dev->name);
+ printk(KERN_NOTICE "SunLance: warning: overriding option "
+ "'tpe-link-test?'\n");
+ printk(KERN_NOTICE "SunLance: warning: mail any problems "
+ "to ecd@skynet.be\n");
auxio_set_lte(AUXIO_LTE_ON);
}
no_link_test:
@@ -1467,8 +1453,7 @@ no_link_test:
/* This should never happen. */
if ((unsigned long)(lp->init_block->brx_ring) & 0x07) {
- printk(KERN_ERR "%s: ERROR: Rx and Tx rings not on even boundary.\n",
- dev->name);
+ printk(KERN_ERR "SunLance: ERROR: Rx and Tx rings not on even boundary.\n");
goto fail;
}
@@ -1486,7 +1471,6 @@ no_link_test:
dev->irq = sdev->irqs[0];
dev->dma = 0;
- ether_setup(dev);
/* We cannot sleep if the chip is busy during a
* multicast list update event, because such events
@@ -1497,15 +1481,27 @@ no_link_test:
lp->multicast_timer.data = (unsigned long) dev;
lp->multicast_timer.function = &lance_set_multicast_retry;
- dev->ifindex = dev_new_index();
+ if (register_netdev(dev)) {
+ printk(KERN_ERR "SunLance: Cannot register device.\n");
+ goto fail;
+ }
+
lp->next_module = root_lance_dev;
root_lance_dev = lp;
+ printk(KERN_INFO "%s: LANCE ", dev->name);
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ i == 5 ? ' ': ':');
+ printk("\n");
+
return 0;
fail:
if (lp != NULL)
lance_free_hwresources(lp);
+ free_netdev(dev);
return -ENODEV;
}
@@ -1543,7 +1539,7 @@ static int __init sparc_lance_probe(void)
memset(&sdev, 0, sizeof(sdev));
sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
sdev.irqs[0] = 6;
- return sparc_lance_init(NULL, &sdev, 0, 0);
+ return sparc_lance_init(&sdev, 0, 0);
}
return -ENODEV;
}
@@ -1555,7 +1551,6 @@ static int __init sparc_lance_probe(void)
{
struct sbus_bus *bus;
struct sbus_dev *sdev = 0;
- struct net_device *dev = NULL;
struct sbus_dma *ledma = 0;
static int called;
int cards = 0, v;
@@ -1568,25 +1563,23 @@ static int __init sparc_lance_probe(void)
for_each_sbus (bus) {
for_each_sbusdev (sdev, bus) {
- if (cards)
- dev = NULL;
if (strcmp(sdev->prom_name, "le") == 0) {
cards++;
- if ((v = sparc_lance_init(dev, sdev, 0, 0)))
+ if ((v = sparc_lance_init(sdev, 0, 0)))
return v;
continue;
}
if (strcmp(sdev->prom_name, "ledma") == 0) {
cards++;
ledma = find_ledma(sdev);
- if ((v = sparc_lance_init(dev, sdev->child,
+ if ((v = sparc_lance_init(sdev->child,
ledma, 0)))
return v;
continue;
}
if (strcmp(sdev->prom_name, "lebuffer") == 0){
cards++;
- if ((v = sparc_lance_init(dev, sdev->child,
+ if ((v = sparc_lance_init(sdev->child,
0, sdev)))
return v;
continue;
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index d3b49237ed50..9cba9322d850 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -38,7 +38,13 @@ extern int eth_header_cache(struct neighbour *neigh,
struct hh_cache *hh);
extern int eth_header_parse(struct sk_buff *skb,
unsigned char *haddr);
-extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv);
+extern struct net_device *__init_etherdev(struct net_device *dev, int sizeof_priv);
+static inline __deprecated struct net_device *init_etherdev(struct net_device *dev,
+ int sizeof_priv)
+{
+ return __init_etherdev(dev, sizeof_priv);
+}
+
extern struct net_device *alloc_etherdev(int sizeof_priv);
static inline void eth_copy_and_sum (struct sk_buff *dest, unsigned char *src, int len, int base)
{
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2a53de551b53..cf00126c50ed 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -469,6 +469,7 @@ struct net_device
/* class/net/name entry */
struct class_device class_dev;
+ struct net_device_stats* (*last_stats)(struct net_device *);
};
#define SET_MODULE_OWNER(dev) do { } while (0)
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 1141ec3c5321..aadba39502cc 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -352,8 +352,10 @@ enum
struct ifa_cacheinfo
{
- __s32 ifa_prefered;
- __s32 ifa_valid;
+ __u32 ifa_prefered;
+ __u32 ifa_valid;
+ __u32 cstamp; /* created timestamp, hundredths of seconds */
+ __u32 tstamp; /* updated timestamp, hundredths of seconds */
};
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 98f5c9663799..1cba818bc6e6 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -34,7 +34,8 @@ struct inet6_ifaddr
__u32 valid_lft;
__u32 prefered_lft;
- unsigned long tstamp;
+ unsigned long cstamp; /* created timestamp */
+ unsigned long tstamp; /* updated timestamp */
atomic_t refcnt;
spinlock_t lock;
@@ -111,6 +112,8 @@ struct ifmcaddr6
atomic_t mca_refcnt;
spinlock_t mca_lock;
unsigned char mca_crcount;
+ unsigned long mca_cstamp;
+ unsigned long mca_tstamp;
};
/* Anycast stuff */
@@ -130,6 +133,8 @@ struct ifacaddr6
int aca_users;
atomic_t aca_refcnt;
spinlock_t aca_lock;
+ unsigned long aca_cstamp;
+ unsigned long aca_tstamp;
};
#define IFA_HOST IPV6_ADDR_LOOPBACK
diff --git a/net/atm/proc.c b/net/atm/proc.c
index dbfa6c1ee107..fffc39bc1395 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -219,10 +219,10 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
default:
seq_printf(seq, "%3d", vcc->sk->sk_family);
}
- seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d] 0x%x\n", vcc->flags, vcc->sk->sk_err,
+ seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, vcc->sk->sk_err,
atomic_read(&vcc->sk->sk_wmem_alloc),vcc->sk->sk_sndbuf,
atomic_read(&vcc->sk->sk_rmem_alloc),vcc->sk->sk_rcvbuf,
- atomic_read(&vcc->sk->sk_refcnt), vcc->sk->sk_hashent);
+ atomic_read(&vcc->sk->sk_refcnt));
}
static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
@@ -320,7 +320,7 @@ static int vcc_seq_show(struct seq_file *seq, void *v)
if (v == (void *)1) {
seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
"Address ", "Itf VPI VCI Fam Flags Reply "
- "Send buffer Recv buffer\n");
+ "Send buffer Recv buffer [refcnt]\n");
} else {
struct vcc_state *state = seq->private;
struct atm_vcc *vcc = atm_sk(state->sk);
diff --git a/net/core/dev.c b/net/core/dev.c
index 74d7342e045f..7ba82b6a6429 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -713,6 +713,19 @@ static int default_rebuild_header(struct sk_buff *skb)
return 1;
}
+
+/*
+ * Some old buggy device drivers change get_stats after registering
+ * the device. Try and trap them here.
+ * This can be elimnated when all devices are known fixed.
+ */
+static inline int get_stats_changed(struct net_device *dev)
+{
+ int changed = dev->last_stats != dev->get_stats;
+ dev->last_stats = dev->get_stats;
+ return changed;
+}
+
/**
* dev_open - prepare an interface for use.
* @dev: device to open
@@ -737,6 +750,14 @@ int dev_open(struct net_device *dev)
return 0;
/*
+ * Check for broken device drivers.
+ */
+ if (get_stats_changed(dev) && net_ratelimit()) {
+ printk(KERN_ERR "%s: driver changed get_stats after register\n",
+ dev->name);
+ }
+
+ /*
* Is it even present?
*/
if (!netif_device_present(dev))
@@ -753,6 +774,14 @@ int dev_open(struct net_device *dev)
}
/*
+ * Check for more broken device drivers.
+ */
+ if (get_stats_changed(dev) && net_ratelimit()) {
+ printk(KERN_ERR "%s: driver changed get_stats in open\n",
+ dev->name);
+ }
+
+ /*
* If it went open OK then:
*/
@@ -943,7 +972,8 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
* they originated from - MvS (miquels@drinkel.ow.org)
*/
if ((ptype->dev == dev || !ptype->dev) &&
- (struct sock *)ptype->af_packet_priv != skb->sk) {
+ (ptype->af_packet_priv == NULL ||
+ (struct sock *)ptype->af_packet_priv != skb->sk)) {
struct sk_buff *skb2= skb_clone(skb, GFP_ATOMIC);
if (!skb2)
break;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b1fa8f6ccc2a..ae9b5c8e8098 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -419,6 +419,7 @@ int netdev_register_sysfs(struct net_device *net)
}
+ net->last_stats = net->get_stats;
if (net->get_stats &&
(ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
goto out_unreg;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index aa5a099a74ec..cd37719491af 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -92,6 +92,9 @@
#define ADBG(x)
#endif
+#define INFINITY_LIFE_TIME 0xFFFFFFFF
+#define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b)))
+
#ifdef CONFIG_SYSCTL
static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p);
static void addrconf_sysctl_unregister(struct ipv6_devconf *p);
@@ -505,6 +508,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
ifa->scope = scope;
ifa->prefix_len = pfxlen;
ifa->flags = flags | IFA_F_TENTATIVE;
+ ifa->cstamp = ifa->tstamp = jiffies;
read_lock(&addrconf_lock);
if (idev->dead) {
@@ -707,6 +711,7 @@ retry:
ift->ifpub = ifp;
ift->valid_lft = tmp_valid_lft;
ift->prefered_lft = tmp_prefered_lft;
+ ift->cstamp = ifp->cstamp;
ift->tstamp = ifp->tstamp;
spin_unlock_bh(&ift->lock);
addrconf_dad_start(ift, 0);
@@ -1412,6 +1417,7 @@ ok:
}
update_lft = create = 1;
+ ifp->cstamp = jiffies;
addrconf_dad_start(ifp, RTF_ADDRCONF|RTF_PREFIX_RT);
}
@@ -2447,14 +2453,95 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
if (!(ifa->flags&IFA_F_PERMANENT)) {
ci.ifa_prefered = ifa->prefered_lft;
ci.ifa_valid = ifa->valid_lft;
- if (ci.ifa_prefered != 0xFFFFFFFF) {
+ if (ci.ifa_prefered != INFINITY_LIFE_TIME) {
long tval = (jiffies - ifa->tstamp)/HZ;
ci.ifa_prefered -= tval;
- if (ci.ifa_valid != 0xFFFFFFFF)
+ if (ci.ifa_valid != INFINITY_LIFE_TIME)
ci.ifa_valid -= tval;
}
- RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
- }
+ } else {
+ ci.ifa_prefered = INFINITY_LIFE_TIME;
+ ci.ifa_valid = INFINITY_LIFE_TIME;
+ }
+ ci.cstamp = (__u32)(TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) / HZ * 100
+ + TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
+ ci.tstamp = (__u32)(TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) / HZ * 100
+ + TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
+ RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
+ u32 pid, u32 seq, int event)
+{
+ struct ifaddrmsg *ifm;
+ struct nlmsghdr *nlh;
+ struct ifa_cacheinfo ci;
+ unsigned char *b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
+ if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ ifm = NLMSG_DATA(nlh);
+ ifm->ifa_family = AF_INET6;
+ ifm->ifa_prefixlen = 128;
+ ifm->ifa_flags = IFA_F_PERMANENT;
+ ifm->ifa_scope = RT_SCOPE_UNIVERSE;
+ if (ipv6_addr_scope(&ifmca->mca_addr)&IFA_SITE)
+ ifm->ifa_scope = RT_SCOPE_SITE;
+ ifm->ifa_index = ifmca->idev->dev->ifindex;
+ RTA_PUT(skb, IFA_ADDRESS, 16, &ifmca->mca_addr);
+ ci.cstamp = (__u32)(TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) / HZ
+ * 100 + TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) % HZ
+ * 100 / HZ);
+ ci.tstamp = (__u32)(TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) / HZ
+ * 100 + TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) % HZ
+ * 100 / HZ);
+ ci.ifa_prefered = INFINITY_LIFE_TIME;
+ ci.ifa_valid = INFINITY_LIFE_TIME;
+ RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
+ nlh->nlmsg_len = skb->tail - b;
+ return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
+ u32 pid, u32 seq, int event)
+{
+ struct ifaddrmsg *ifm;
+ struct nlmsghdr *nlh;
+ struct ifa_cacheinfo ci;
+ unsigned char *b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
+ if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ ifm = NLMSG_DATA(nlh);
+ ifm->ifa_family = AF_INET6;
+ ifm->ifa_prefixlen = 128;
+ ifm->ifa_flags = IFA_F_PERMANENT;
+ ifm->ifa_scope = RT_SCOPE_UNIVERSE;
+ if (ipv6_addr_scope(&ifaca->aca_addr)&IFA_SITE)
+ ifm->ifa_scope = RT_SCOPE_SITE;
+ ifm->ifa_index = ifaca->aca_idev->dev->ifindex;
+ RTA_PUT(skb, IFA_ADDRESS, 16, &ifaca->aca_addr);
+ ci.cstamp = (__u32)(TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) / HZ
+ * 100 + TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) % HZ
+ * 100 / HZ);
+ ci.tstamp = (__u32)(TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) / HZ
+ * 100 + TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) % HZ
+ * 100 / HZ);
+ ci.ifa_prefered = INFINITY_LIFE_TIME;
+ ci.ifa_valid = INFINITY_LIFE_TIME;
+ RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
nlh->nlmsg_len = skb->tail - b;
return skb->len;
@@ -2468,33 +2555,79 @@ static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx, ip_idx;
int s_idx, s_ip_idx;
- struct inet6_ifaddr *ifa;
-
+ int err = 1;
+ struct net_device *dev;
+ struct inet6_dev *idev = NULL;
+ struct inet6_ifaddr *ifa;
+ struct ifmcaddr6 *ifmca;
+ struct ifacaddr6 *ifaca;
+
s_idx = cb->args[0];
s_ip_idx = ip_idx = cb->args[1];
-
- for (idx=0; idx < IN6_ADDR_HSIZE; idx++) {
+ read_lock(&dev_base_lock);
+
+ for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
if (idx > s_idx)
s_ip_idx = 0;
- read_lock_bh(&addrconf_hash_lock);
- for (ifa=inet6_addr_lst[idx], ip_idx = 0; ifa;
- ifa = ifa->lst_next, ip_idx++) {
+ ip_idx = 0;
+ if ((idev = in6_dev_get(dev)) == NULL)
+ continue;
+ read_lock_bh(&idev->lock);
+ /* unicast address */
+ for (ifa = idev->addr_list; ifa;
+ ifa = ifa->if_next, ip_idx++) {
if (ip_idx < s_ip_idx)
continue;
- if (inet6_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0) {
- read_unlock_bh(&addrconf_hash_lock);
+ if ((err = inet6_fill_ifaddr(skb, ifa,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0)
+ goto done;
+ }
+ /* temp addr */
+#ifdef CONFIG_IPV6_PRIVACY
+ for (ifa = idev->tempaddr_list; ifa;
+ ifa = ifa->tmp_next, ip_idx++) {
+ if (ip_idx < s_ip_idx)
+ continue;
+ if ((err = inet6_fill_ifaddr(skb, ifa,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0)
+ goto done;
+ }
+#endif
+ /* multicast address */
+ for (ifmca = idev->mc_list; ifmca;
+ ifmca = ifmca->next, ip_idx++) {
+ if (ip_idx < s_ip_idx)
+ continue;
+ if ((err = inet6_fill_ifmcaddr(skb, ifmca,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0)
goto done;
- }
}
- read_unlock_bh(&addrconf_hash_lock);
+ /* anycast address */
+ for (ifaca = idev->ac_list; ifaca;
+ ifaca = ifaca->aca_next, ip_idx++) {
+ if (ip_idx < s_ip_idx)
+ continue;
+ if ((err = inet6_fill_ifacaddr(skb, ifaca,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0)
+ goto done;
+ }
+ read_unlock_bh(&idev->lock);
+ in6_dev_put(idev);
}
done:
+ if (err <= 0) {
+ read_unlock_bh(&idev->lock);
+ in6_dev_put(idev);
+ }
+ read_unlock(&dev_base_lock);
cb->args[0] = idx;
cb->args[1] = ip_idx;
-
return skb->len;
}
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index dcb1424f6327..fc10df7d327d 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -343,6 +343,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
ipv6_addr_copy(&aca->aca_addr, addr);
aca->aca_idev = idev;
aca->aca_users = 1;
+ /* aca_tstamp should be updated upon changes */
+ aca->aca_cstamp = aca->aca_tstamp = jiffies;
atomic_set(&aca->aca_refcnt, 2);
aca->aca_lock = SPIN_LOCK_UNLOCKED;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 40d6e9d9b695..8e0a18eb8514 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -830,6 +830,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
ipv6_addr_copy(&mc->mca_addr, addr);
mc->idev = idev;
mc->mca_users = 1;
+ /* mca_stamp should be updated upon changes */
+ mc->mca_cstamp = mc->mca_tstamp = jiffies;
atomic_set(&mc->mca_refcnt, 2);
mc->mca_lock = SPIN_LOCK_UNLOCKED;