Commit cb6d1611 authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.ninka.net:/disk1/davem/BK/net-2.5

into kernel.bkbits.net:/home/davem/net-2.5
parents 0068306f 21f6cbbb
...@@ -1071,7 +1071,6 @@ fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd) ...@@ -1071,7 +1071,6 @@ fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
struct sock *s; struct sock *s;
struct atm_vcc* vcc; struct atm_vcc* vcc;
struct hlist_node *node; struct hlist_node *node;
int i;
read_lock(&vcc_sklist_lock); read_lock(&vcc_sklist_lock);
......
...@@ -157,7 +157,7 @@ static short nvpibits = -1; ...@@ -157,7 +157,7 @@ static short nvpibits = -1;
static short nvcibits = -1; static short nvcibits = -1;
static short rx_skb_reserve = 16; static short rx_skb_reserve = 16;
static short irq_coalesce = 1; static short irq_coalesce = 1;
static short sdh = 1; static short sdh = 0;
static struct atmdev_ops he_ops = static struct atmdev_ops he_ops =
{ {
...@@ -1547,11 +1547,10 @@ he_start(struct atm_dev *dev) ...@@ -1547,11 +1547,10 @@ he_start(struct atm_dev *dev)
if (sdh) { if (sdh) {
/* this really should be in suni.c but for now... */ /* this really should be in suni.c but for now... */
int val; int val;
val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM); 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); he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM);
} }
......
...@@ -2432,11 +2432,11 @@ static int lanai_open(struct atm_vcc *atmvcc) ...@@ -2432,11 +2432,11 @@ static int lanai_open(struct atm_vcc *atmvcc)
return result; return result;
} }
#if 0
/* ioctl operations for card */ /* ioctl operations for card */
/* NOTE: these are all DEBUGGING ONLY currently */ /* NOTE: these are all DEBUGGING ONLY currently */
static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg) static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg)
{ {
#if 0
int result = 0; int result = 0;
struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
switch(cmd) { switch(cmd) {
...@@ -2514,11 +2514,10 @@ static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg) ...@@ -2514,11 +2514,10 @@ static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg)
result = -ENOIOCTLCMD; result = -ENOIOCTLCMD;
} }
return result; return result;
}
#else /* !0 */ #else /* !0 */
(void) atmdev; (void) cmd; (void) arg; /* no compiler warnings */ #define lanai_ioctl NULL
return -ENOIOCTLCMD;
#endif /* 0 */ #endif /* 0 */
}
static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb) static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb)
{ {
......
...@@ -1676,6 +1676,25 @@ static void ns_close(struct atm_vcc *vcc) ...@@ -1676,6 +1676,25 @@ static void ns_close(struct atm_vcc *vcc)
free_scq(vc->scq, 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; vcc->dev_data = NULL;
clear_bit(ATM_VF_PARTIAL,&vcc->flags); clear_bit(ATM_VF_PARTIAL,&vcc->flags);
clear_bit(ATM_VF_ADDR,&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) ...@@ -2074,7 +2093,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos)
if (skb != NULL) if (skb != NULL)
{ {
vcc = ATM_SKB(skb)->vcc; vcc = ATM_SKB(skb)->vcc;
if (vcc->pop != NULL) { if (vcc && vcc->pop != NULL) {
vcc->pop(vcc, skb); vcc->pop(vcc, skb);
} else { } else {
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
......
...@@ -888,15 +888,16 @@ static void dump_eeprom(struct myri_eth *mp) ...@@ -888,15 +888,16 @@ static void dump_eeprom(struct myri_eth *mp)
} }
#endif #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; static unsigned version_printed;
struct net_device *dev;
struct myri_eth *mp; struct myri_eth *mp;
unsigned char prop_buf[32]; unsigned char prop_buf[32];
int i; int i;
DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num)); DET(("myri_ether_init(%p,%d):\n", sdev, num));
dev = init_etherdev(0, sizeof(struct myri_eth)); dev = alloc_etherdev(sizeof(struct myri_eth));
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
...@@ -904,8 +905,6 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, ...@@ -904,8 +905,6 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
if (version_printed++ == 0) if (version_printed++ == 0)
printk(version); printk(version);
printk("%s: MyriCOM MyriNET Ethernet ", dev->name);
mp = (struct myri_eth *) dev->priv; mp = (struct myri_eth *) dev->priv;
spin_lock_init(&mp->irq_lock); spin_lock_init(&mp->irq_lock);
mp->myri_sdev = sdev; mp->myri_sdev = sdev;
...@@ -974,10 +973,7 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, ...@@ -974,10 +973,7 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
#endif #endif
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i] = mp->eeprom.id[i];
dev->dev_addr[i] = mp->eeprom.id[i],
i == 5 ? ' ' : ':');
printk("\n");
determine_reg_space_size(mp); determine_reg_space_size(mp);
...@@ -1072,9 +1068,6 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, ...@@ -1072,9 +1068,6 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
goto err; goto err;
} }
DET(("ether_setup()\n"));
ether_setup(dev);
dev->mtu = MYRINET_MTU; dev->mtu = MYRINET_MTU;
dev->change_mtu = myri_change_mtu; dev->change_mtu = myri_change_mtu;
dev->hard_header = myri_header; dev->hard_header = myri_header;
...@@ -1087,15 +1080,30 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, ...@@ -1087,15 +1080,30 @@ static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev,
DET(("Loading LANAI firmware\n")); DET(("Loading LANAI firmware\n"));
myri_load_lanai(mp); myri_load_lanai(mp);
if (register_netdev(dev)) {
printk("MyriCOM: Cannot register device.\n");
goto err_free_irq;
}
#ifdef MODULE #ifdef MODULE
dev->ifindex = dev_new_index();
mp->next_module = root_myri_dev; mp->next_module = root_myri_dev;
root_myri_dev = mp; root_myri_dev = mp;
#endif #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; return 0;
err: unregister_netdev(dev);
err_free_irq:
free_irq(dev->irq, dev);
err:
/* This will also free the co-allocated 'dev->priv' */ /* This will also free the co-allocated 'dev->priv' */
kfree(dev); free_netdev(dev);
return -ENODEV; return -ENODEV;
} }
...@@ -1112,7 +1120,6 @@ static int __init myri_sbus_match(struct sbus_dev *sdev) ...@@ -1112,7 +1120,6 @@ static int __init myri_sbus_match(struct sbus_dev *sdev)
static int __init myri_sbus_probe(void) static int __init myri_sbus_probe(void)
{ {
struct net_device *dev = NULL;
struct sbus_bus *bus; struct sbus_bus *bus;
struct sbus_dev *sdev = 0; struct sbus_dev *sdev = 0;
static int called; static int called;
...@@ -1128,12 +1135,10 @@ static int __init myri_sbus_probe(void) ...@@ -1128,12 +1135,10 @@ static int __init myri_sbus_probe(void)
for_each_sbus(bus) { for_each_sbus(bus) {
for_each_sbusdev(sdev, bus) { for_each_sbusdev(sdev, bus) {
if (cards)
dev = NULL;
if (myri_sbus_match(sdev)) { if (myri_sbus_match(sdev)) {
cards++; cards++;
DET(("Found myricom myrinet as %s\n", sdev->prom_name)); 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; return v;
} }
} }
......
...@@ -197,9 +197,13 @@ static struct net_device *init_netdev(struct net_device *dev, int sizeof_priv, ...@@ -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, * If an empty string area is passed as dev->name, or a new structure is made,
* a new name string is constructed. * 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); return init_netdev(dev, sizeof_priv, "eth%d", ether_setup);
} }
...@@ -222,7 +226,7 @@ struct net_device *alloc_etherdev(int sizeof_priv) ...@@ -222,7 +226,7 @@ struct net_device *alloc_etherdev(int sizeof_priv)
return alloc_netdev(sizeof_priv, "eth%d", ether_setup); return alloc_netdev(sizeof_priv, "eth%d", ether_setup);
} }
EXPORT_SYMBOL(init_etherdev); EXPORT_SYMBOL(__init_etherdev);
EXPORT_SYMBOL(alloc_etherdev); EXPORT_SYMBOL(alloc_etherdev);
static int eth_mac_addr(struct net_device *dev, void *p) static int eth_mac_addr(struct net_device *dev, void *p)
......
...@@ -451,8 +451,6 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out, ...@@ -451,8 +451,6 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out,
*ioaddr_out = NULL; *ioaddr_out = NULL;
*dev_out = NULL; *dev_out = NULL;
// dev zeroed in init_etherdev
dev = alloc_etherdev(sizeof (*tp)); dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) { if (dev == NULL) {
printk(KERN_ERR PFX "unable to alloc new ethernet\n"); printk(KERN_ERR PFX "unable to alloc new ethernet\n");
......
...@@ -653,24 +653,16 @@ static int __init skge_probe (void) ...@@ -653,24 +653,16 @@ static int __init skge_probe (void)
continue; 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 " printk(KERN_ERR "Unable to allocate etherdev "
"structure!\n"); "structure!\n");
break; break;
} }
if (dev->priv == NULL) {
printk(KERN_ERR "Unable to allocate adapter "
"structure!\n");
break;
}
pNet = dev->priv; pNet = dev->priv;
pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
if (pNet->pAC == NULL){ if (pNet->pAC == NULL){
dev->get_stats = NULL; free_netdev(dev);
unregister_netdev(dev);
kfree(dev->priv);
printk(KERN_ERR "Unable to allocate adapter " printk(KERN_ERR "Unable to allocate adapter "
"structure!\n"); "structure!\n");
break; break;
...@@ -699,9 +691,7 @@ static int __init skge_probe (void) ...@@ -699,9 +691,7 @@ static int __init skge_probe (void)
retval = SkGeInitPCI(pAC); retval = SkGeInitPCI(pAC);
if (retval) { if (retval) {
printk("SKGE: PCI setup failed: %i\n", retval); printk("SKGE: PCI setup failed: %i\n", retval);
dev->get_stats = NULL; free_netdev(dev);
unregister_netdev(dev);
kfree(dev);
continue; continue;
} }
...@@ -730,13 +720,20 @@ static int __init skge_probe (void) ...@@ -730,13 +720,20 @@ static int __init skge_probe (void)
pAC->Index = boards_found; pAC->Index = boards_found;
if (SkGeBoardInit(dev, pAC)) { if (SkGeBoardInit(dev, pAC)) {
FreeResources(dev); FreeResources(dev);
kfree(dev); free_netdev(dev);
continue; continue;
} }
memcpy((caddr_t) &dev->dev_addr, memcpy((caddr_t) &dev->dev_addr,
(caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); (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 */ /* First adapter... Create proc and print message */
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
if (!DeviceFound) { if (!DeviceFound) {
...@@ -767,21 +764,11 @@ static int __init skge_probe (void) ...@@ -767,21 +764,11 @@ static int __init skge_probe (void)
pNet->PortNr = 0; pNet->PortNr = 0;
pNet->NetNr = 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++; boards_found++;
/* More then one port found */ /* More then one port found */
if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { 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 " printk(KERN_ERR "Unable to allocate etherdev "
"structure!\n"); "structure!\n");
break; break;
...@@ -814,22 +801,28 @@ static int __init skge_probe (void) ...@@ -814,22 +801,28 @@ static int __init skge_probe (void)
#endif #endif
#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 #ifdef CONFIG_PROC_FS
if (pSkRootDir if (pSkRootDir
&& (pProcFile = create_proc_entry(dev->name, && (pProcFile = create_proc_entry(dev->name,
S_IRUGO, S_IRUGO,
pSkRootDir))) { pSkRootDir))) {
pProcFile->proc_fops = &sk_proc_fops; pProcFile->proc_fops = &sk_proc_fops;
pProcFile->data = dev; pProcFile->data = dev;
} }
#endif #endif
memcpy((caddr_t) &dev->dev_addr, memcpy((caddr_t) &dev->dev_addr,
(caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
printk("%s: %s\n", dev->name, pAC->DeviceStr); printk("%s: %s\n", dev->name, pAC->DeviceStr);
printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
}
} }
......
...@@ -1072,7 +1072,7 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) ...@@ -1072,7 +1072,7 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
int i; int i;
/* Get a new device struct for this interface. */ /* Get a new device struct for this interface. */
dev = init_etherdev(NULL, sizeof(struct bigmac)); dev = alloc_etherdev(sizeof(struct bigmac));
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
...@@ -1080,13 +1080,9 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) ...@@ -1080,13 +1080,9 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
if (version_printed++ == 0) if (version_printed++ == 0)
printk(KERN_INFO "%s", version); 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; dev->base_addr = (long) qec_sdev;
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i], dev->dev_addr[i] = idprom->id_ethaddr[i];
i == 5 ? ' ' : ':');
printk("\n");
/* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */ /* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */
bp = dev->priv; bp = dev->priv;
...@@ -1210,12 +1206,23 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) ...@@ -1210,12 +1206,23 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
dev->irq = bp->bigmac_sdev->irqs[0]; dev->irq = bp->bigmac_sdev->irqs[0];
dev->dma = 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 /* Put us into the list of instances attached for later driver
* exit. * exit.
*/ */
bp->next_module = root_bigmac_dev; bp->next_module = root_bigmac_dev;
root_bigmac_dev = bp; 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; return 0;
fail_and_cleanup: fail_and_cleanup:
...@@ -1236,9 +1243,8 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) ...@@ -1236,9 +1243,8 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
bp->bmac_block, bp->bmac_block,
bp->bblock_dvma); bp->bblock_dvma);
unregister_netdev(dev);
/* This also frees the co-located 'dev->priv' */ /* This also frees the co-located 'dev->priv' */
kfree(dev); free_netdev(dev);
return -ENODEV; return -ENODEV;
} }
......
...@@ -1312,32 +1312,24 @@ static struct ethtool_ops sparc_lance_ethtool_ops = { ...@@ -1312,32 +1312,24 @@ static struct ethtool_ops sparc_lance_ethtool_ops = {
.get_link = sparc_lance_get_link, .get_link = sparc_lance_get_link,
}; };
static int __init sparc_lance_init(struct net_device *dev, static int __init sparc_lance_init(struct sbus_dev *sdev,
struct sbus_dev *sdev,
struct sbus_dma *ledma, struct sbus_dma *ledma,
struct sbus_dev *lebuffer) struct sbus_dev *lebuffer)
{ {
static unsigned version_printed; static unsigned version_printed;
struct lance_private *lp = NULL; struct net_device *dev;
struct lance_private *lp;
int i; int i;
if (dev == NULL) { dev = alloc_etherdev(sizeof(struct lance_private) + 8);
dev = init_etherdev (0, sizeof (struct lance_private) + 8); if (!dev)
} else { return -ENOMEM;
dev->priv = kmalloc(sizeof (struct lance_private) + 8,
GFP_KERNEL); lp = dev->priv;
if (dev->priv == NULL)
return -ENOMEM;
memset(dev->priv, 0, sizeof (struct lance_private) + 8);
}
if (sparc_lance_debug && version_printed++ == 0) if (sparc_lance_debug && version_printed++ == 0)
printk (KERN_INFO "%s", version); 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); spin_lock_init(&lp->lock);
/* Copy the IDPROM ethernet address to the device structure, later we /* 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, ...@@ -1345,16 +1337,13 @@ static int __init sparc_lance_init(struct net_device *dev,
* initialization block. * initialization block.
*/ */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i], dev->dev_addr[i] = idprom->id_ethaddr[i];
i == 5 ? ' ': ':');
printk("\n");
/* Get the IO region */ /* Get the IO region */
lp->lregs = sbus_ioremap(&sdev->resource[0], 0, lp->lregs = sbus_ioremap(&sdev->resource[0], 0,
LANCE_REG_SIZE, lancestr); LANCE_REG_SIZE, lancestr);
if (lp->lregs == 0UL) { if (lp->lregs == 0UL) {
printk(KERN_ERR "%s: Cannot map SunLance registers.\n", printk(KERN_ERR "SunLance: Cannot map registers.\n");
dev->name);
goto fail; goto fail;
} }
...@@ -1364,8 +1353,7 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1364,8 +1353,7 @@ static int __init sparc_lance_init(struct net_device *dev,
sbus_ioremap(&lebuffer->resource[0], 0, sbus_ioremap(&lebuffer->resource[0], 0,
sizeof(struct lance_init_block), "lebuffer"); sizeof(struct lance_init_block), "lebuffer");
if (lp->init_block == NULL) { if (lp->init_block == NULL) {
printk(KERN_ERR "%s: Cannot map SunLance PIO buffer.\n", printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n");
dev->name);
goto fail; goto fail;
} }
lp->init_block_dvma = 0; lp->init_block_dvma = 0;
...@@ -1379,8 +1367,7 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1379,8 +1367,7 @@ static int __init sparc_lance_init(struct net_device *dev,
&lp->init_block_dvma); &lp->init_block_dvma);
if (lp->init_block == NULL || if (lp->init_block == NULL ||
lp->init_block_dvma == 0) { lp->init_block_dvma == 0) {
printk(KERN_ERR "%s: Cannot allocate consistent DMA memory.\n", printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n");
dev->name);
goto fail; goto fail;
} }
lp->pio_buffer = 0; lp->pio_buffer = 0;
...@@ -1418,8 +1405,7 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1418,8 +1405,7 @@ static int __init sparc_lance_init(struct net_device *dev,
if (prop[0] == 0) { if (prop[0] == 0) {
int topnd, nd; int topnd, nd;
printk(KERN_INFO "%s: using auto-carrier-detection.\n", printk(KERN_INFO "SunLance: using auto-carrier-detection.\n");
dev->name);
/* Is this found at /options .attributes in all /* Is this found at /options .attributes in all
* Prom versions? XXX * Prom versions? XXX
...@@ -1438,10 +1424,10 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1438,10 +1424,10 @@ static int __init sparc_lance_init(struct net_device *dev,
sizeof(prop)); sizeof(prop));
if (strcmp(prop, "true")) { if (strcmp(prop, "true")) {
printk(KERN_NOTICE "%s: warning: overriding option " printk(KERN_NOTICE "SunLance: warning: overriding option "
"'tpe-link-test?'\n", dev->name); "'tpe-link-test?'\n");
printk(KERN_NOTICE "%s: warning: mail any problems " printk(KERN_NOTICE "SunLance: warning: mail any problems "
"to ecd@skynet.be\n", dev->name); "to ecd@skynet.be\n");
auxio_set_lte(AUXIO_LTE_ON); auxio_set_lte(AUXIO_LTE_ON);
} }
no_link_test: no_link_test:
...@@ -1467,8 +1453,7 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1467,8 +1453,7 @@ static int __init sparc_lance_init(struct net_device *dev,
/* This should never happen. */ /* This should never happen. */
if ((unsigned long)(lp->init_block->brx_ring) & 0x07) { if ((unsigned long)(lp->init_block->brx_ring) & 0x07) {
printk(KERN_ERR "%s: ERROR: Rx and Tx rings not on even boundary.\n", printk(KERN_ERR "SunLance: ERROR: Rx and Tx rings not on even boundary.\n");
dev->name);
goto fail; goto fail;
} }
...@@ -1486,7 +1471,6 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1486,7 +1471,6 @@ static int __init sparc_lance_init(struct net_device *dev,
dev->irq = sdev->irqs[0]; dev->irq = sdev->irqs[0];
dev->dma = 0; dev->dma = 0;
ether_setup(dev);
/* We cannot sleep if the chip is busy during a /* We cannot sleep if the chip is busy during a
* multicast list update event, because such events * multicast list update event, because such events
...@@ -1497,15 +1481,27 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1497,15 +1481,27 @@ static int __init sparc_lance_init(struct net_device *dev,
lp->multicast_timer.data = (unsigned long) dev; lp->multicast_timer.data = (unsigned long) dev;
lp->multicast_timer.function = &lance_set_multicast_retry; 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; lp->next_module = root_lance_dev;
root_lance_dev = lp; 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; return 0;
fail: fail:
if (lp != NULL) if (lp != NULL)
lance_free_hwresources(lp); lance_free_hwresources(lp);
free_netdev(dev);
return -ENODEV; return -ENODEV;
} }
...@@ -1543,7 +1539,7 @@ static int __init sparc_lance_probe(void) ...@@ -1543,7 +1539,7 @@ static int __init sparc_lance_probe(void)
memset(&sdev, 0, sizeof(sdev)); memset(&sdev, 0, sizeof(sdev));
sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
sdev.irqs[0] = 6; sdev.irqs[0] = 6;
return sparc_lance_init(NULL, &sdev, 0, 0); return sparc_lance_init(&sdev, 0, 0);
} }
return -ENODEV; return -ENODEV;
} }
...@@ -1555,7 +1551,6 @@ static int __init sparc_lance_probe(void) ...@@ -1555,7 +1551,6 @@ static int __init sparc_lance_probe(void)
{ {
struct sbus_bus *bus; struct sbus_bus *bus;
struct sbus_dev *sdev = 0; struct sbus_dev *sdev = 0;
struct net_device *dev = NULL;
struct sbus_dma *ledma = 0; struct sbus_dma *ledma = 0;
static int called; static int called;
int cards = 0, v; int cards = 0, v;
...@@ -1568,25 +1563,23 @@ static int __init sparc_lance_probe(void) ...@@ -1568,25 +1563,23 @@ static int __init sparc_lance_probe(void)
for_each_sbus (bus) { for_each_sbus (bus) {
for_each_sbusdev (sdev, bus) { for_each_sbusdev (sdev, bus) {
if (cards)
dev = NULL;
if (strcmp(sdev->prom_name, "le") == 0) { if (strcmp(sdev->prom_name, "le") == 0) {
cards++; cards++;
if ((v = sparc_lance_init(dev, sdev, 0, 0))) if ((v = sparc_lance_init(sdev, 0, 0)))
return v; return v;
continue; continue;
} }
if (strcmp(sdev->prom_name, "ledma") == 0) { if (strcmp(sdev->prom_name, "ledma") == 0) {
cards++; cards++;
ledma = find_ledma(sdev); ledma = find_ledma(sdev);
if ((v = sparc_lance_init(dev, sdev->child, if ((v = sparc_lance_init(sdev->child,
ledma, 0))) ledma, 0)))
return v; return v;
continue; continue;
} }
if (strcmp(sdev->prom_name, "lebuffer") == 0){ if (strcmp(sdev->prom_name, "lebuffer") == 0){
cards++; cards++;
if ((v = sparc_lance_init(dev, sdev->child, if ((v = sparc_lance_init(sdev->child,
0, sdev))) 0, sdev)))
return v; return v;
continue; continue;
......
...@@ -38,7 +38,13 @@ extern int eth_header_cache(struct neighbour *neigh, ...@@ -38,7 +38,13 @@ extern int eth_header_cache(struct neighbour *neigh,
struct hh_cache *hh); struct hh_cache *hh);
extern int eth_header_parse(struct sk_buff *skb, extern int eth_header_parse(struct sk_buff *skb,
unsigned char *haddr); 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); 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) static inline void eth_copy_and_sum (struct sk_buff *dest, unsigned char *src, int len, int base)
{ {
......
...@@ -469,6 +469,7 @@ struct net_device ...@@ -469,6 +469,7 @@ struct net_device
/* class/net/name entry */ /* class/net/name entry */
struct class_device class_dev; struct class_device class_dev;
struct net_device_stats* (*last_stats)(struct net_device *);
}; };
#define SET_MODULE_OWNER(dev) do { } while (0) #define SET_MODULE_OWNER(dev) do { } while (0)
......
...@@ -352,8 +352,10 @@ enum ...@@ -352,8 +352,10 @@ enum
struct ifa_cacheinfo struct ifa_cacheinfo
{ {
__s32 ifa_prefered; __u32 ifa_prefered;
__s32 ifa_valid; __u32 ifa_valid;
__u32 cstamp; /* created timestamp, hundredths of seconds */
__u32 tstamp; /* updated timestamp, hundredths of seconds */
}; };
......
...@@ -34,7 +34,8 @@ struct inet6_ifaddr ...@@ -34,7 +34,8 @@ struct inet6_ifaddr
__u32 valid_lft; __u32 valid_lft;
__u32 prefered_lft; __u32 prefered_lft;
unsigned long tstamp; unsigned long cstamp; /* created timestamp */
unsigned long tstamp; /* updated timestamp */
atomic_t refcnt; atomic_t refcnt;
spinlock_t lock; spinlock_t lock;
...@@ -111,6 +112,8 @@ struct ifmcaddr6 ...@@ -111,6 +112,8 @@ struct ifmcaddr6
atomic_t mca_refcnt; atomic_t mca_refcnt;
spinlock_t mca_lock; spinlock_t mca_lock;
unsigned char mca_crcount; unsigned char mca_crcount;
unsigned long mca_cstamp;
unsigned long mca_tstamp;
}; };
/* Anycast stuff */ /* Anycast stuff */
...@@ -130,6 +133,8 @@ struct ifacaddr6 ...@@ -130,6 +133,8 @@ struct ifacaddr6
int aca_users; int aca_users;
atomic_t aca_refcnt; atomic_t aca_refcnt;
spinlock_t aca_lock; spinlock_t aca_lock;
unsigned long aca_cstamp;
unsigned long aca_tstamp;
}; };
#define IFA_HOST IPV6_ADDR_LOOPBACK #define IFA_HOST IPV6_ADDR_LOOPBACK
......
...@@ -219,10 +219,10 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc) ...@@ -219,10 +219,10 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
default: default:
seq_printf(seq, "%3d", vcc->sk->sk_family); 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_wmem_alloc),vcc->sk->sk_sndbuf,
atomic_read(&vcc->sk->sk_rmem_alloc),vcc->sk->sk_rcvbuf, 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) 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) ...@@ -320,7 +320,7 @@ static int vcc_seq_show(struct seq_file *seq, void *v)
if (v == (void *)1) { if (v == (void *)1) {
seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s", seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
"Address ", "Itf VPI VCI Fam Flags Reply " "Address ", "Itf VPI VCI Fam Flags Reply "
"Send buffer Recv buffer\n"); "Send buffer Recv buffer [refcnt]\n");
} else { } else {
struct vcc_state *state = seq->private; struct vcc_state *state = seq->private;
struct atm_vcc *vcc = atm_sk(state->sk); struct atm_vcc *vcc = atm_sk(state->sk);
......
...@@ -713,6 +713,19 @@ static int default_rebuild_header(struct sk_buff *skb) ...@@ -713,6 +713,19 @@ static int default_rebuild_header(struct sk_buff *skb)
return 1; 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_open - prepare an interface for use.
* @dev: device to open * @dev: device to open
...@@ -736,6 +749,14 @@ int dev_open(struct net_device *dev) ...@@ -736,6 +749,14 @@ int dev_open(struct net_device *dev)
if (dev->flags & IFF_UP) if (dev->flags & IFF_UP)
return 0; 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? * Is it even present?
*/ */
...@@ -753,6 +774,14 @@ int dev_open(struct net_device *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: * If it went open OK then:
*/ */
...@@ -943,7 +972,8 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) ...@@ -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) * they originated from - MvS (miquels@drinkel.ow.org)
*/ */
if ((ptype->dev == dev || !ptype->dev) && 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); struct sk_buff *skb2= skb_clone(skb, GFP_ATOMIC);
if (!skb2) if (!skb2)
break; break;
......
...@@ -419,6 +419,7 @@ int netdev_register_sysfs(struct net_device *net) ...@@ -419,6 +419,7 @@ int netdev_register_sysfs(struct net_device *net)
} }
net->last_stats = net->get_stats;
if (net->get_stats && if (net->get_stats &&
(ret = sysfs_create_group(&class_dev->kobj, &netstat_group))) (ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
goto out_unreg; goto out_unreg;
......
...@@ -92,6 +92,9 @@ ...@@ -92,6 +92,9 @@
#define ADBG(x) #define ADBG(x)
#endif #endif
#define INFINITY_LIFE_TIME 0xFFFFFFFF
#define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b)))
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p); static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p);
static void addrconf_sysctl_unregister(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, ...@@ -505,6 +508,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
ifa->scope = scope; ifa->scope = scope;
ifa->prefix_len = pfxlen; ifa->prefix_len = pfxlen;
ifa->flags = flags | IFA_F_TENTATIVE; ifa->flags = flags | IFA_F_TENTATIVE;
ifa->cstamp = ifa->tstamp = jiffies;
read_lock(&addrconf_lock); read_lock(&addrconf_lock);
if (idev->dead) { if (idev->dead) {
...@@ -707,6 +711,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i ...@@ -707,6 +711,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ift->ifpub = ifp; ift->ifpub = ifp;
ift->valid_lft = tmp_valid_lft; ift->valid_lft = tmp_valid_lft;
ift->prefered_lft = tmp_prefered_lft; ift->prefered_lft = tmp_prefered_lft;
ift->cstamp = ifp->cstamp;
ift->tstamp = ifp->tstamp; ift->tstamp = ifp->tstamp;
spin_unlock_bh(&ift->lock); spin_unlock_bh(&ift->lock);
addrconf_dad_start(ift, 0); addrconf_dad_start(ift, 0);
...@@ -1412,6 +1417,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1412,6 +1417,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
} }
update_lft = create = 1; update_lft = create = 1;
ifp->cstamp = jiffies;
addrconf_dad_start(ifp, RTF_ADDRCONF|RTF_PREFIX_RT); 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, ...@@ -2447,14 +2453,95 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
if (!(ifa->flags&IFA_F_PERMANENT)) { if (!(ifa->flags&IFA_F_PERMANENT)) {
ci.ifa_prefered = ifa->prefered_lft; ci.ifa_prefered = ifa->prefered_lft;
ci.ifa_valid = ifa->valid_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; long tval = (jiffies - ifa->tstamp)/HZ;
ci.ifa_prefered -= tval; ci.ifa_prefered -= tval;
if (ci.ifa_valid != 0xFFFFFFFF) if (ci.ifa_valid != INFINITY_LIFE_TIME)
ci.ifa_valid -= tval; 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; nlh->nlmsg_len = skb->tail - b;
return skb->len; return skb->len;
...@@ -2468,33 +2555,79 @@ static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2468,33 +2555,79 @@ static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
{ {
int idx, ip_idx; int idx, ip_idx;
int s_idx, s_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_idx = cb->args[0];
s_ip_idx = ip_idx = cb->args[1]; s_ip_idx = ip_idx = cb->args[1];
read_lock(&dev_base_lock);
for (idx=0; idx < IN6_ADDR_HSIZE; idx++) {
for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
if (idx < s_idx) if (idx < s_idx)
continue; continue;
if (idx > s_idx) if (idx > s_idx)
s_ip_idx = 0; s_ip_idx = 0;
read_lock_bh(&addrconf_hash_lock); ip_idx = 0;
for (ifa=inet6_addr_lst[idx], ip_idx = 0; ifa; if ((idev = in6_dev_get(dev)) == NULL)
ifa = ifa->lst_next, ip_idx++) { 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) if (ip_idx < s_ip_idx)
continue; continue;
if (inet6_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, if ((err = inet6_fill_ifaddr(skb, ifa,
cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0) { NETLINK_CB(cb->skb).pid,
read_unlock_bh(&addrconf_hash_lock); 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; 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: done:
if (err <= 0) {
read_unlock_bh(&idev->lock);
in6_dev_put(idev);
}
read_unlock(&dev_base_lock);
cb->args[0] = idx; cb->args[0] = idx;
cb->args[1] = ip_idx; cb->args[1] = ip_idx;
return skb->len; return skb->len;
} }
......
...@@ -343,6 +343,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) ...@@ -343,6 +343,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
ipv6_addr_copy(&aca->aca_addr, addr); ipv6_addr_copy(&aca->aca_addr, addr);
aca->aca_idev = idev; aca->aca_idev = idev;
aca->aca_users = 1; aca->aca_users = 1;
/* aca_tstamp should be updated upon changes */
aca->aca_cstamp = aca->aca_tstamp = jiffies;
atomic_set(&aca->aca_refcnt, 2); atomic_set(&aca->aca_refcnt, 2);
aca->aca_lock = SPIN_LOCK_UNLOCKED; aca->aca_lock = SPIN_LOCK_UNLOCKED;
......
...@@ -830,6 +830,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) ...@@ -830,6 +830,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
ipv6_addr_copy(&mc->mca_addr, addr); ipv6_addr_copy(&mc->mca_addr, addr);
mc->idev = idev; mc->idev = idev;
mc->mca_users = 1; mc->mca_users = 1;
/* mca_stamp should be updated upon changes */
mc->mca_cstamp = mc->mca_tstamp = jiffies;
atomic_set(&mc->mca_refcnt, 2); atomic_set(&mc->mca_refcnt, 2);
mc->mca_lock = SPIN_LOCK_UNLOCKED; mc->mca_lock = SPIN_LOCK_UNLOCKED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment