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)
struct sock *s;
struct atm_vcc* vcc;
struct hlist_node *node;
int i;
read_lock(&vcc_sklist_lock);
......
......@@ -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);
}
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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;
}
}
......
......@@ -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)
......
......@@ -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");
......
......@@ -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,6 +801,12 @@ 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,
......@@ -829,7 +822,7 @@ static int __init skge_probe (void)
printk("%s: %s\n", dev->name, pAC->DeviceStr);
printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
}
}
......
......@@ -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 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
bp->bmac_block,
bp->bblock_dvma);
unregister_netdev(dev);
/* This also frees the co-located 'dev->priv' */
kfree(dev);
free_netdev(dev);
return -ENODEV;
}
......
......@@ -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)
dev = alloc_etherdev(sizeof(struct lance_private) + 8);
if (!dev)
return -ENOMEM;
memset(dev->priv, 0, sizeof (struct lance_private) + 8);
}
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 @@ static int __init sparc_lance_init(struct net_device *dev,
/* 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 @@ static int __init sparc_lance_init(struct net_device *dev,
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 @@ static int __init sparc_lance_init(struct net_device *dev,
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;
......
......@@ -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)
{
......
......@@ -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)
......
......@@ -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 */
};
......
......@@ -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
......
......@@ -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);
......
......@@ -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
......@@ -736,6 +749,14 @@ int dev_open(struct net_device *dev)
if (dev->flags & IFF_UP)
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?
*/
......@@ -752,6 +773,14 @@ int dev_open(struct net_device *dev)
clear_bit(__LINK_STATE_START, &dev->state);
}
/*
* 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;
......
......@@ -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;
......
......@@ -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 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
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 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
}
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;
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];
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)
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;
}
read_unlock_bh(&addrconf_hash_lock);
#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;
}
/* 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;
}
......
......@@ -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;
......
......@@ -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;
......
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