[linux-next] LinuxNextTracking branch, master, updated. next-20111219

batman at open-mesh.org batman at open-mesh.org
Tue Dec 20 00:17:33 CET 2011


The following commit has been merged in the master branch:
commit b26e478f8fd5b575684f021b05a5c6236ebb911a
Merge: bcebcc468a6bcd3820fe9ad36b34220563efc93a bb3c36863e8001fc21a88bebfdead4da4c23e848
Author: David S. Miller <davem at davemloft.net>
Date:   Fri Dec 16 02:11:14 2011 -0500

    Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
    
    Conflicts:
    	drivers/net/ethernet/freescale/fsl_pq_mdio.c
    	net/batman-adv/translation-table.c
    	net/ipv6/route.c

diff --combined drivers/net/ethernet/freescale/fec.c
index 01ee9cc,c136230..4ea2bdc
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@@ -99,7 -99,7 +99,7 @@@ static struct platform_device_id fec_de
  MODULE_DEVICE_TABLE(platform, fec_devtype);
  
  enum imx_fec_type {
 -	IMX25_FEC = 1, 	/* runs on i.mx25/50/53 */
 +	IMX25_FEC = 1,	/* runs on i.mx25/50/53 */
  	IMX27_FEC,	/* runs on i.mx27/35/51 */
  	IMX28_FEC,
  	IMX6Q_FEC,
@@@ -132,7 -132,7 +132,7 @@@ MODULE_PARM_DESC(macaddr, "FEC Etherne
  #elif defined (CONFIG_M5272C3)
  #define	FEC_FLASHMAC	(0xffe04000 + 4)
  #elif defined(CONFIG_MOD5272)
 -#define FEC_FLASHMAC 	0xffc0406b
 +#define FEC_FLASHMAC	0xffc0406b
  #else
  #define	FEC_FLASHMAC	0
  #endif
@@@ -232,6 -232,7 +232,7 @@@ struct fec_enet_private 
  	struct	platform_device *pdev;
  
  	int	opened;
+ 	int	dev_id;
  
  	/* Phylib and MDIO interface */
  	struct	mii_bus *mii_bus;
@@@ -259,8 -260,6 +260,8 @@@
  /* Transmitter timeout */
  #define TX_TIMEOUT (2 * HZ)
  
 +static int mii_cnt;
 +
  static void *swap_buffer(void *bufaddr, int len)
  {
  	int i;
@@@ -517,7 -516,6 +518,7 @@@ fec_stop(struct net_device *ndev
  	struct fec_enet_private *fep = netdev_priv(ndev);
  	const struct platform_device_id *id_entry =
  				platform_get_device_id(fep->pdev);
 +	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
  
  	/* We cannot expect a graceful transmit stop without link !!! */
  	if (fep->link) {
@@@ -534,10 -532,8 +535,10 @@@
  	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
  
  	/* We have to keep ENET enabled to have MII interrupt stay working */
 -	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
 +	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
  		writel(2, fep->hwp + FEC_ECNTRL);
 +		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
 +	}
  }
  
  
@@@ -823,7 -819,7 +824,7 @@@ static void __inline__ fec_get_mac(stru
  			iap = (unsigned char *)FEC_FLASHMAC;
  #else
  		if (pdata)
 -			memcpy(iap, pdata->mac, ETH_ALEN);
 +			iap = (unsigned char *)&pdata->mac;
  #endif
  	}
  
@@@ -842,7 -838,7 +843,7 @@@
  
  	/* Adjust MAC if using macaddr */
  	if (iap == macaddr)
- 		 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
+ 		 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id;
  }
  
  /* ------------------------------------------------------------------------- */
@@@ -870,8 -866,6 +871,8 @@@ static void fec_enet_adjust_link(struc
  	if (phy_dev->link) {
  		if (fep->full_duplex != phy_dev->duplex) {
  			fec_restart(ndev, phy_dev->duplex);
 +			/* prevent unnecessary second fec_restart() below */
 +			fep->link = phy_dev->link;
  			status_change = 1;
  		}
  	}
@@@ -960,7 -954,7 +961,7 @@@ static int fec_enet_mii_probe(struct ne
  	char mdio_bus_id[MII_BUS_ID_SIZE];
  	char phy_name[MII_BUS_ID_SIZE + 3];
  	int phy_id;
- 	int dev_id = fep->pdev->id;
+ 	int dev_id = fep->dev_id;
  
  	fep->phy_dev = NULL;
  
@@@ -979,9 -973,8 +980,9 @@@
  	}
  
  	if (phy_id >= PHY_MAX_ADDR) {
 -		printk(KERN_INFO "%s: no PHY, assuming direct connection "
 -			"to switch\n", ndev->name);
 +		printk(KERN_INFO
 +			"%s: no PHY, assuming direct connection to switch\n",
 +			ndev->name);
  		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
  		phy_id = 0;
  	}
@@@ -1006,9 -999,8 +1007,9 @@@
  	fep->link = 0;
  	fep->full_duplex = 0;
  
 -	printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
 -		"(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name,
 +	printk(KERN_INFO
 +		"%s: Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
 +		ndev->name,
  		fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
  		fep->phy_dev->irq);
  
@@@ -1040,14 -1032,10 +1041,14 @@@ static int fec_enet_mii_init(struct pla
  	 * mdio interface in board design, and need to be configured by
  	 * fec0 mii_bus.
  	 */
- 	if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id > 0) {
+ 	if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) {
  		/* fec1 uses fec0 mii_bus */
 -		fep->mii_bus = fec0_mii_bus;
 -		return 0;
 +		if (mii_cnt && fec0_mii_bus) {
 +			fep->mii_bus = fec0_mii_bus;
 +			mii_cnt++;
 +			return 0;
 +		}
 +		return -ENOENT;
  	}
  
  	fep->mii_timeout = 0;
@@@ -1076,7 -1064,7 +1077,7 @@@
  	fep->mii_bus->read = fec_enet_mdio_read;
  	fep->mii_bus->write = fec_enet_mdio_write;
  	fep->mii_bus->reset = fec_enet_mdio_reset;
- 	snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1);
+ 	snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", fep->dev_id + 1);
  	fep->mii_bus->priv = fep;
  	fep->mii_bus->parent = &pdev->dev;
  
@@@ -1092,8 -1080,6 +1093,8 @@@
  	if (mdiobus_register(fep->mii_bus))
  		goto err_out_free_mdio_irq;
  
 +	mii_cnt++;
 +
  	/* save fec0 mii_bus */
  	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
  		fec0_mii_bus = fep->mii_bus;
@@@ -1110,11 -1096,11 +1111,11 @@@ err_out
  
  static void fec_enet_mii_remove(struct fec_enet_private *fep)
  {
 -	if (fep->phy_dev)
 -		phy_disconnect(fep->phy_dev);
 -	mdiobus_unregister(fep->mii_bus);
 -	kfree(fep->mii_bus->irq);
 -	mdiobus_free(fep->mii_bus);
 +	if (--mii_cnt == 0) {
 +		mdiobus_unregister(fep->mii_bus);
 +		kfree(fep->mii_bus->irq);
 +		mdiobus_free(fep->mii_bus);
 +	}
  }
  
  static int fec_enet_get_settings(struct net_device *ndev,
@@@ -1536,6 -1522,7 +1537,7 @@@ fec_probe(struct platform_device *pdev
  	int i, irq, ret = 0;
  	struct resource *r;
  	const struct of_device_id *of_id;
+ 	static int dev_id;
  
  	of_id = of_match_device(fec_dt_ids, &pdev->dev);
  	if (of_id)
@@@ -1563,6 -1550,7 +1565,7 @@@
  
  	fep->hwp = ioremap(r->start, resource_size(r));
  	fep->pdev = pdev;
+ 	fep->dev_id = dev_id++;
  
  	if (!fep->hwp) {
  		ret = -ENOMEM;
@@@ -1586,12 -1574,8 +1589,12 @@@
  
  	for (i = 0; i < FEC_IRQ_NUM; i++) {
  		irq = platform_get_irq(pdev, i);
 -		if (i && irq < 0)
 -			break;
 +		if (irq < 0) {
 +			if (i)
 +				break;
 +			ret = irq;
 +			goto failed_irq;
 +		}
  		ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
  		if (ret) {
  			while (--i >= 0) {
@@@ -1602,7 -1586,7 +1605,7 @@@
  		}
  	}
  
 -	fep->clk = clk_get(&pdev->dev, "fec_clk");
 +	fep->clk = clk_get(&pdev->dev, NULL);
  	if (IS_ERR(fep->clk)) {
  		ret = PTR_ERR(fep->clk);
  		goto failed_clk;
@@@ -1654,18 -1638,13 +1657,18 @@@ fec_drv_remove(struct platform_device *
  	struct net_device *ndev = platform_get_drvdata(pdev);
  	struct fec_enet_private *fep = netdev_priv(ndev);
  	struct resource *r;
 +	int i;
  
 -	fec_stop(ndev);
 +	unregister_netdev(ndev);
  	fec_enet_mii_remove(fep);
 +	for (i = 0; i < FEC_IRQ_NUM; i++) {
 +		int irq = platform_get_irq(pdev, i);
 +		if (irq > 0)
 +			free_irq(irq, ndev);
 +	}
  	clk_disable(fep->clk);
  	clk_put(fep->clk);
  	iounmap(fep->hwp);
 -	unregister_netdev(ndev);
  	free_netdev(ndev);
  
  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --combined drivers/net/ethernet/freescale/fsl_pq_mdio.c
index f109602,4d9f84b..9eb8159
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@@ -356,16 -356,16 +356,15 @@@ static int fsl_pq_mdio_probe(struct pla
  
  		if (prop)
  			tbiaddr = *prop;
+ 	}
  
- 		if (tbiaddr == -1) {
- 			err = -EBUSY;
- 
- 			goto err_free_irqs;
- 		} else {
- 			out_be32(tbipa, tbiaddr);
- 		}
+ 	if (tbiaddr == -1) {
+ 		err = -EBUSY;
 -
+ 		goto err_free_irqs;
++	} else {
++		out_be32(tbipa, tbiaddr);
  	}
  
 -	out_be32(tbipa, tbiaddr);
 -
  	err = of_mdiobus_register(new_bus, np);
  	if (err) {
  		printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
@@@ -443,6 -443,15 +442,6 @@@ static struct platform_driver fsl_pq_md
  	.remove = fsl_pq_mdio_remove,
  };
  
 -int __init fsl_pq_mdio_init(void)
 -{
 -	return platform_driver_register(&fsl_pq_mdio_driver);
 -}
 -module_init(fsl_pq_mdio_init);
 +module_platform_driver(fsl_pq_mdio_driver);
  
 -void fsl_pq_mdio_exit(void)
 -{
 -	platform_driver_unregister(&fsl_pq_mdio_driver);
 -}
 -module_exit(fsl_pq_mdio_exit);
  MODULE_LICENSE("GPL");
diff --combined drivers/net/ppp/pptp.c
index ede899c,f8a6853..c1c9293
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@@ -162,7 -162,7 +162,7 @@@ static void del_chan(struct pppox_sock 
  {
  	spin_lock(&chan_lock);
  	clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
 -	rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL);
 +	RCU_INIT_POINTER(callid_sock[sock->proto.pptp.src_addr.call_id], NULL);
  	spin_unlock(&chan_lock);
  	synchronize_rcu();
  }
@@@ -423,10 -423,8 +423,8 @@@ static int pptp_bind(struct socket *soc
  	lock_sock(sk);
  
  	opt->src_addr = sp->sa_addr.pptp;
- 	if (add_chan(po)) {
- 		release_sock(sk);
+ 	if (add_chan(po))
  		error = -EBUSY;
- 	}
  
  	release_sock(sk);
  	return error;
diff --combined drivers/net/wireless/ath/ath9k/main.c
index 5007297,d2348a5..7d92004
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@@ -118,7 -118,7 +118,7 @@@ void ath9k_ps_restore(struct ath_softc 
  	if (--sc->ps_usecount != 0)
  		goto unlock;
  
 -	if (sc->ps_idle)
 +	if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
  		mode = ATH9K_PM_FULL_SLEEP;
  	else if (sc->ps_enabled &&
  		 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
@@@ -286,7 -286,7 +286,7 @@@ static bool ath_complete_reset(struct a
  			ath_start_ani(common);
  	}
  
- 	if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) {
+ 	if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) {
  		struct ath_hw_antcomb_conf div_ant_conf;
  		u8 lna_conf;
  
@@@ -332,8 -332,7 +332,8 @@@ static int ath_reset_internal(struct at
  		hchan = ah->curchan;
  	}
  
 -	if (fastcc && !ath9k_hw_check_alive(ah))
 +	if (fastcc && (ah->chip_fullsleep ||
 +	    !ath9k_hw_check_alive(ah)))
  		fastcc = false;
  
  	if (!ath_prepare_reset(sc, retry_tx, flush))
@@@ -562,6 -561,7 +562,6 @@@ void ath_ani_calibrate(unsigned long da
  	/* Long calibration runs independently of short calibration. */
  	if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
  		longcal = true;
 -		ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
  		common->ani.longcal_timer = timestamp;
  	}
  
@@@ -569,6 -569,8 +569,6 @@@
  	if (!common->ani.caldone) {
  		if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
  			shortcal = true;
 -			ath_dbg(common, ATH_DBG_ANI,
 -				"shortcal @%lu\n", jiffies);
  			common->ani.shortcal_timer = timestamp;
  			common->ani.resetcal_timer = timestamp;
  		}
@@@ -582,9 -584,8 +582,9 @@@
  	}
  
  	/* Verify whether we must check ANI */
 -	if ((timestamp - common->ani.checkani_timer) >=
 -	     ah->config.ani_poll_interval) {
 +	if (sc->sc_ah->config.enable_ani
 +	    && (timestamp - common->ani.checkani_timer) >=
 +	    ah->config.ani_poll_interval) {
  		aniflag = true;
  		common->ani.checkani_timer = timestamp;
  	}
@@@ -604,11 -605,6 +604,11 @@@
  						ah->rxchainmask, longcal);
  	}
  
 +	ath_dbg(common, ATH_DBG_ANI,
 +		"Calibration @%lu finished: %s %s %s, caldone: %s\n", jiffies,
 +		longcal ? "long" : "", shortcal ? "short" : "",
 +		aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
 +
  	ath9k_ps_restore(sc);
  
  set_timer:
@@@ -634,8 -630,7 +634,8 @@@
  	}
  }
  
 -static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
 +static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
 +			    struct ieee80211_vif *vif)
  {
  	struct ath_node *an;
  	an = (struct ath_node *)sta->drv_priv;
@@@ -645,7 -640,6 +645,7 @@@
  	list_add(&an->list, &sc->nodes);
  	spin_unlock(&sc->nodes_lock);
  	an->sta = sta;
 +	an->vif = vif;
  #endif
  	if (sc->sc_flags & SC_OP_TXAGGR) {
  		ath_tx_node_init(sc, an);
@@@ -746,9 -740,6 +746,9 @@@ void ath9k_tasklet(unsigned long data
  		if (status & ATH9K_INT_GENTIMER)
  			ath_gen_timer_isr(sc->sc_ah);
  
 +	if (status & ATH9K_INT_MCI)
 +		ath_mci_intr(sc);
 +
  out:
  	/* re-enable hardware interrupt */
  	ath9k_hw_enable_interrupts(ah);
@@@ -771,8 -762,7 +771,8 @@@ irqreturn_t ath_isr(int irq, void *dev
  		ATH9K_INT_BMISS |		\
  		ATH9K_INT_CST |			\
  		ATH9K_INT_TSFOOR |		\
 -		ATH9K_INT_GENTIMER)
 +		ATH9K_INT_GENTIMER |		\
 +		ATH9K_INT_MCI)
  
  	struct ath_softc *sc = dev;
  	struct ath_hw *ah = sc->sc_ah;
@@@ -890,6 -880,82 +890,6 @@@ chip_reset
  #undef SCHED_INTR
  }
  
 -static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 -{
 -	struct ath_hw *ah = sc->sc_ah;
 -	struct ath_common *common = ath9k_hw_common(ah);
 -	struct ieee80211_channel *channel = hw->conf.channel;
 -	int r;
 -
 -	ath9k_ps_wakeup(sc);
 -	spin_lock_bh(&sc->sc_pcu_lock);
 -	atomic_set(&ah->intr_ref_cnt, -1);
 -
 -	ath9k_hw_configpcipowersave(ah, false);
 -
 -	if (!ah->curchan)
 -		ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
 -
 -	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 -	if (r) {
 -		ath_err(common,
 -			"Unable to reset channel (%u MHz), reset status %d\n",
 -			channel->center_freq, r);
 -	}
 -
 -	ath_complete_reset(sc, true);
 -
 -	/* Enable LED */
 -	ath9k_hw_cfg_output(ah, ah->led_pin,
 -			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 -	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 -
 -	spin_unlock_bh(&sc->sc_pcu_lock);
 -
 -	ath9k_ps_restore(sc);
 -}
 -
 -void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
 -{
 -	struct ath_hw *ah = sc->sc_ah;
 -	struct ieee80211_channel *channel = hw->conf.channel;
 -	int r;
 -
 -	ath9k_ps_wakeup(sc);
 -
 -	ath_cancel_work(sc);
 -
 -	spin_lock_bh(&sc->sc_pcu_lock);
 -
 -	/*
 -	 * Keep the LED on when the radio is disabled
 -	 * during idle unassociated state.
 -	 */
 -	if (!sc->ps_idle) {
 -		ath9k_hw_set_gpio(ah, ah->led_pin, 1);
 -		ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
 -	}
 -
 -	ath_prepare_reset(sc, false, true);
 -
 -	if (!ah->curchan)
 -		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
 -
 -	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 -	if (r) {
 -		ath_err(ath9k_hw_common(sc->sc_ah),
 -			"Unable to reset channel (%u MHz), reset status %d\n",
 -			channel->center_freq, r);
 -	}
 -
 -	ath9k_hw_phy_disable(ah);
 -
 -	ath9k_hw_configpcipowersave(ah, true);
 -
 -	spin_unlock_bh(&sc->sc_pcu_lock);
 -	ath9k_ps_restore(sc);
 -}
 -
  static int ath_reset(struct ath_softc *sc, bool retry_tx)
  {
  	int r;
@@@ -1025,9 -1091,6 +1025,9 @@@ static int ath9k_start(struct ieee80211
  	 * and then setup of the interrupt mask.
  	 */
  	spin_lock_bh(&sc->sc_pcu_lock);
 +
 +	atomic_set(&ah->intr_ref_cnt, -1);
 +
  	r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
  	if (r) {
  		ath_err(common,
@@@ -1054,9 -1117,6 +1054,9 @@@
  	if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
  		ah->imask |= ATH9K_INT_CST;
  
 +	if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
 +		ah->imask |= ATH9K_INT_MCI;
 +
  	sc->sc_flags &= ~SC_OP_INVALID;
  	sc->sc_ah->is_monitoring = false;
  
@@@ -1069,25 -1129,12 +1069,25 @@@
  		goto mutex_unlock;
  	}
  
 +	if (ah->led_pin >= 0) {
 +		ath9k_hw_cfg_output(ah, ah->led_pin,
 +				    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 +		ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 +	}
 +
 +	/*
 +	 * Reset key cache to sane defaults (all entries cleared) instead of
 +	 * semi-random values after suspend/resume.
 +	 */
 +	ath9k_cmn_init_crypto(sc->sc_ah);
 +
  	spin_unlock_bh(&sc->sc_pcu_lock);
  
  	if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
  	    !ah->btcoex_hw.enabled) {
 -		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
 -					   AR_STOMP_LOW_WLAN_WGHT);
 +		if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
 +			ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
 +						   AR_STOMP_LOW_WLAN_WGHT);
  		ath9k_hw_btcoex_enable(ah);
  
  		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
@@@ -1126,13 -1173,6 +1126,13 @@@ static void ath9k_tx(struct ieee80211_h
  		}
  	}
  
 +	/*
 +	 * Cannot tx while the hardware is in full sleep, it first needs a full
 +	 * chip reset to recover from that
 +	 */
 +	if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP))
 +		goto exit;
 +
  	if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
  		/*
  		 * We are using PS-Poll and mac80211 can request TX while in
@@@ -1179,7 -1219,6 +1179,7 @@@ static void ath9k_stop(struct ieee80211
  	struct ath_softc *sc = hw->priv;
  	struct ath_hw *ah = sc->sc_ah;
  	struct ath_common *common = ath9k_hw_common(ah);
 +	bool prev_idle;
  
  	mutex_lock(&sc->mutex);
  
@@@ -1198,7 -1237,6 +1198,7 @@@
  		ath9k_hw_btcoex_disable(ah);
  		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
  			ath9k_btcoex_timer_pause(sc);
 +		ath_mci_flush_profile(&sc->btcoex.mci);
  	}
  
  	spin_lock_bh(&sc->sc_pcu_lock);
@@@ -1210,45 -1248,35 +1210,45 @@@
  	 * before setting the invalid flag. */
  	ath9k_hw_disable_interrupts(ah);
  
 -	if (!(sc->sc_flags & SC_OP_INVALID)) {
 -		ath_drain_all_txq(sc, false);
 -		ath_stoprecv(sc);
 -		ath9k_hw_phy_disable(ah);
 -	} else
 -		sc->rx.rxlink = NULL;
 +	spin_unlock_bh(&sc->sc_pcu_lock);
 +
 +	/* we can now sync irq and kill any running tasklets, since we already
 +	 * disabled interrupts and not holding a spin lock */
 +	synchronize_irq(sc->irq);
 +	tasklet_kill(&sc->intr_tq);
 +	tasklet_kill(&sc->bcon_tasklet);
 +
 +	prev_idle = sc->ps_idle;
 +	sc->ps_idle = true;
 +
 +	spin_lock_bh(&sc->sc_pcu_lock);
 +
 +	if (ah->led_pin >= 0) {
 +		ath9k_hw_set_gpio(ah, ah->led_pin, 1);
 +		ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
 +	}
 +
 +	ath_prepare_reset(sc, false, true);
  
  	if (sc->rx.frag) {
  		dev_kfree_skb_any(sc->rx.frag);
  		sc->rx.frag = NULL;
  	}
  
 -	/* disable HAL and put h/w to sleep */
 -	ath9k_hw_disable(ah);
 +	if (!ah->curchan)
 +		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
  
 -	spin_unlock_bh(&sc->sc_pcu_lock);
 +	ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 +	ath9k_hw_phy_disable(ah);
  
 -	/* we can now sync irq and kill any running tasklets, since we already
 -	 * disabled interrupts and not holding a spin lock */
 -	synchronize_irq(sc->irq);
 -	tasklet_kill(&sc->intr_tq);
 -	tasklet_kill(&sc->bcon_tasklet);
 +	ath9k_hw_configpcipowersave(ah, true);
  
 -	ath9k_ps_restore(sc);
 +	spin_unlock_bh(&sc->sc_pcu_lock);
  
 -	sc->ps_idle = true;
 -	ath_radio_disable(sc, hw);
 +	ath9k_ps_restore(sc);
  
  	sc->sc_flags |= SC_OP_INVALID;
 +	sc->ps_idle = prev_idle;
  
  	mutex_unlock(&sc->mutex);
  
@@@ -1588,8 -1616,8 +1588,8 @@@ static int ath9k_config(struct ieee8021
  	struct ath_hw *ah = sc->sc_ah;
  	struct ath_common *common = ath9k_hw_common(ah);
  	struct ieee80211_conf *conf = &hw->conf;
 -	bool disable_radio = false;
  
 +	ath9k_ps_wakeup(sc);
  	mutex_lock(&sc->mutex);
  
  	/*
@@@ -1600,8 -1628,13 +1600,8 @@@
  	 */
  	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
  		sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 -		if (!sc->ps_idle) {
 -			ath_radio_enable(sc, hw);
 -			ath_dbg(common, ATH_DBG_CONFIG,
 -				"not-idle: enabling radio\n");
 -		} else {
 -			disable_radio = true;
 -		}
 +		if (sc->ps_idle)
 +			ath_cancel_work(sc);
  	}
  
  	/*
@@@ -1708,12 -1741,18 +1708,12 @@@
  		ath_dbg(common, ATH_DBG_CONFIG,
  			"Set power: %d\n", conf->power_level);
  		sc->config.txpowlimit = 2 * conf->power_level;
 -		ath9k_ps_wakeup(sc);
  		ath9k_cmn_update_txpow(ah, sc->curtxpow,
  				       sc->config.txpowlimit, &sc->curtxpow);
  	}
  
  	mutex_unlock(&sc->mutex);
 +	ath9k_ps_restore(sc);
  
  	return 0;
  }
@@@ -1759,7 -1798,7 +1759,7 @@@ static int ath9k_sta_add(struct ieee802
  	struct ath_node *an = (struct ath_node *) sta->drv_priv;
  	struct ieee80211_key_conf ps_key = { };
  
 -	ath_node_attach(sc, sta);
 +	ath_node_attach(sc, sta, vif);
  
  	if (vif->type != NL80211_IFTYPE_AP &&
  	    vif->type != NL80211_IFTYPE_AP_VLAN)
@@@ -2281,6 -2320,9 +2281,6 @@@ static void ath9k_flush(struct ieee8021
  		return;
  	}
  
 -	if (drop)
 -		timeout = 1;
 -
  	for (j = 0; j < timeout; j++) {
  		bool npend = false;
  
@@@ -2298,22 -2340,21 +2298,22 @@@
  		}
  
  		if (!npend)
 -		    goto out;
 +		    break;
  	}
  
 -	ath9k_ps_wakeup(sc);
 -	spin_lock_bh(&sc->sc_pcu_lock);
 -	drain_txq = ath_drain_all_txq(sc, false);
 -	spin_unlock_bh(&sc->sc_pcu_lock);
 +	if (drop) {
 +		ath9k_ps_wakeup(sc);
 +		spin_lock_bh(&sc->sc_pcu_lock);
 +		drain_txq = ath_drain_all_txq(sc, false);
 +		spin_unlock_bh(&sc->sc_pcu_lock);
  
 -	if (!drain_txq)
 -		ath_reset(sc, false);
 +		if (!drain_txq)
 +			ath_reset(sc, false);
  
 -	ath9k_ps_restore(sc);
 -	ieee80211_wake_queues(hw);
 +		ath9k_ps_restore(sc);
 +		ieee80211_wake_queues(hw);
 +	}
  
 -out:
  	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
  	mutex_unlock(&sc->mutex);
  }
diff --combined net/batman-adv/translation-table.c
index cc87acf,5f09a57..46a2b37
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@@ -36,9 -36,18 +36,9 @@@ static void _tt_global_del(struct bat_p
  static void tt_purge(struct work_struct *work);
  
  /* returns 1 if they are the same mac addr */
 -static int compare_ltt(const struct hlist_node *node, const void *data2)
 +static int compare_tt(const struct hlist_node *node, const void *data2)
  {
 -	const void *data1 = container_of(node, struct tt_local_entry,
 -					 hash_entry);
 -
 -	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
 -}
 -
 -/* returns 1 if they are the same mac addr */
 -static int compare_gtt(const struct hlist_node *node, const void *data2)
 -{
 -	const void *data1 = container_of(node, struct tt_global_entry,
 +	const void *data1 = container_of(node, struct tt_common_entry,
  					 hash_entry);
  
  	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
@@@ -51,13 -60,14 +51,13 @@@ static void tt_start_timer(struct bat_p
  			   msecs_to_jiffies(5000));
  }
  
 -static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
 -						 const void *data)
 +static struct tt_common_entry *tt_hash_find(struct hashtable_t *hash,
 +					    const void *data)
  {
 -	struct hashtable_t *hash = bat_priv->tt_local_hash;
  	struct hlist_head *head;
  	struct hlist_node *node;
 -	struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL;
 -	int index;
 +	struct tt_common_entry *tt_common_entry, *tt_common_entry_tmp = NULL;
 +	uint32_t index;
  
  	if (!hash)
  		return NULL;
@@@ -66,46 -76,51 +66,46 @@@
  	head = &hash->table[index];
  
  	rcu_read_lock();
 -	hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) {
 -		if (!compare_eth(tt_local_entry, data))
 +	hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) {
 +		if (!compare_eth(tt_common_entry, data))
  			continue;
  
 -		if (!atomic_inc_not_zero(&tt_local_entry->refcount))
 +		if (!atomic_inc_not_zero(&tt_common_entry->refcount))
  			continue;
  
 -		tt_local_entry_tmp = tt_local_entry;
 +		tt_common_entry_tmp = tt_common_entry;
  		break;
  	}
  	rcu_read_unlock();
  
 -	return tt_local_entry_tmp;
 +	return tt_common_entry_tmp;
  }
  
 -static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
 -						   const void *data)
 +static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
 +						 const void *data)
  {
 -	struct hashtable_t *hash = bat_priv->tt_global_hash;
 -	struct hlist_head *head;
 -	struct hlist_node *node;
 -	struct tt_global_entry *tt_global_entry;
 -	struct tt_global_entry *tt_global_entry_tmp = NULL;
 -	int index;
 -
 -	if (!hash)
 -		return NULL;
 -
 -	index = choose_orig(data, hash->size);
 -	head = &hash->table[index];
 +	struct tt_common_entry *tt_common_entry;
 +	struct tt_local_entry *tt_local_entry = NULL;
  
 -	rcu_read_lock();
 -	hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) {
 -		if (!compare_eth(tt_global_entry, data))
 -			continue;
 +	tt_common_entry = tt_hash_find(bat_priv->tt_local_hash, data);
 +	if (tt_common_entry)
 +		tt_local_entry = container_of(tt_common_entry,
 +					      struct tt_local_entry, common);
 +	return tt_local_entry;
 +}
  
 -		if (!atomic_inc_not_zero(&tt_global_entry->refcount))
 -			continue;
 +static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
 +						   const void *data)
 +{
 +	struct tt_common_entry *tt_common_entry;
 +	struct tt_global_entry *tt_global_entry = NULL;
  
 -		tt_global_entry_tmp = tt_global_entry;
 -		break;
 -	}
 -	rcu_read_unlock();
 +	tt_common_entry = tt_hash_find(bat_priv->tt_global_hash, data);
 +	if (tt_common_entry)
 +		tt_global_entry = container_of(tt_common_entry,
 +					       struct tt_global_entry, common);
 +	return tt_global_entry;
  
 -	return tt_global_entry_tmp;
  }
  
  static bool is_out_of_time(unsigned long starting_time, unsigned long timeout)
@@@ -118,18 -133,15 +118,18 @@@
  
  static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry)
  {
 -	if (atomic_dec_and_test(&tt_local_entry->refcount))
 -		kfree_rcu(tt_local_entry, rcu);
 +	if (atomic_dec_and_test(&tt_local_entry->common.refcount))
 +		kfree_rcu(tt_local_entry, common.rcu);
  }
  
  static void tt_global_entry_free_rcu(struct rcu_head *rcu)
  {
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_global_entry *tt_global_entry;
  
 -	tt_global_entry = container_of(rcu, struct tt_global_entry, rcu);
 +	tt_common_entry = container_of(rcu, struct tt_common_entry, rcu);
 +	tt_global_entry = container_of(tt_common_entry, struct tt_global_entry,
 +				       common);
  
  	if (tt_global_entry->orig_node)
  		orig_node_free_ref(tt_global_entry->orig_node);
@@@ -139,9 -151,8 +139,9 @@@
  
  static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry)
  {
 -	if (atomic_dec_and_test(&tt_global_entry->refcount))
 -		call_rcu(&tt_global_entry->rcu, tt_global_entry_free_rcu);
 +	if (atomic_dec_and_test(&tt_global_entry->common.refcount))
 +		call_rcu(&tt_global_entry->common.rcu,
 +			 tt_global_entry_free_rcu);
  }
  
  static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr,
@@@ -190,7 -201,6 +190,7 @@@ void tt_local_add(struct net_device *so
  	struct bat_priv *bat_priv = netdev_priv(soft_iface);
  	struct tt_local_entry *tt_local_entry = NULL;
  	struct tt_global_entry *tt_global_entry = NULL;
 +	int hash_added;
  
  	tt_local_entry = tt_local_hash_find(bat_priv, addr);
  
@@@ -207,33 -217,26 +207,33 @@@
  		"Creating new local tt entry: %pM (ttvn: %d)\n", addr,
  		(uint8_t)atomic_read(&bat_priv->ttvn));
  
 -	memcpy(tt_local_entry->addr, addr, ETH_ALEN);
 -	tt_local_entry->last_seen = jiffies;
 -	tt_local_entry->flags = NO_FLAGS;
 +	memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
 +	tt_local_entry->common.flags = NO_FLAGS;
  	if (is_wifi_iface(ifindex))
 -		tt_local_entry->flags |= TT_CLIENT_WIFI;
 -	atomic_set(&tt_local_entry->refcount, 2);
 +		tt_local_entry->common.flags |= TT_CLIENT_WIFI;
 +	atomic_set(&tt_local_entry->common.refcount, 2);
 +	tt_local_entry->last_seen = jiffies;
  
  	/* the batman interface mac address should never be purged */
  	if (compare_eth(addr, soft_iface->dev_addr))
 -		tt_local_entry->flags |= TT_CLIENT_NOPURGE;
 +		tt_local_entry->common.flags |= TT_CLIENT_NOPURGE;
 +
 +	hash_added = hash_add(bat_priv->tt_local_hash, compare_tt, choose_orig,
 +			 &tt_local_entry->common,
 +			 &tt_local_entry->common.hash_entry);
 +
 +	if (unlikely(hash_added != 0)) {
 +		/* remove the reference for the hash */
 +		tt_local_entry_free_ref(tt_local_entry);
 +		goto out;
 +	}
  
 -	tt_local_event(bat_priv, addr, tt_local_entry->flags);
 +	tt_local_event(bat_priv, addr, tt_local_entry->common.flags);
  
  	/* The local entry has to be marked as NEW to avoid to send it in
  	 * a full table response going out before the next ttvn increment
  	 * (consistency check) */
 -	tt_local_entry->flags |= TT_CLIENT_NEW;
 -
 -	hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig,
 -		 tt_local_entry, &tt_local_entry->hash_entry);
 +	tt_local_entry->common.flags |= TT_CLIENT_NEW;
  
  	/* remove address from global hash if present */
  	tt_global_entry = tt_global_hash_find(bat_priv, addr);
@@@ -242,10 -245,12 +242,11 @@@
  	if (tt_global_entry) {
  		/* This node is probably going to update its tt table */
  		tt_global_entry->orig_node->tt_poss_change = true;
- 		/* The global entry has to be marked as PENDING and has to be
+ 		/* The global entry has to be marked as ROAMING and has to be
  		 * kept for consistency purpose */
 -		tt_global_entry->flags |= TT_CLIENT_ROAM;
 +		tt_global_entry->common.flags |= TT_CLIENT_PENDING;
+ 		tt_global_entry->roam_at = jiffies;
 -
 -		send_roam_adv(bat_priv, tt_global_entry->addr,
 +		send_roam_adv(bat_priv, tt_global_entry->common.addr,
  			      tt_global_entry->orig_node);
  	}
  out:
@@@ -307,12 -312,13 +308,12 @@@ int tt_local_seq_print_text(struct seq_
  	struct net_device *net_dev = (struct net_device *)seq->private;
  	struct bat_priv *bat_priv = netdev_priv(net_dev);
  	struct hashtable_t *hash = bat_priv->tt_local_hash;
 -	struct tt_local_entry *tt_local_entry;
 +	struct tt_common_entry *tt_common_entry;
  	struct hard_iface *primary_if;
  	struct hlist_node *node;
  	struct hlist_head *head;
 -	size_t buf_size, pos;
 -	char *buff;
 -	int i, ret = 0;
 +	uint32_t i;
 +	int ret = 0;
  
  	primary_if = primary_if_get_selected(bat_priv);
  	if (!primary_if) {
@@@ -333,27 -339,51 +334,27 @@@
  		   "announced via TT (TTVN: %u):\n",
  		   net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
  
 -	buf_size = 1;
 -	/* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
 -		__hlist_for_each_rcu(node, head)
 -			buf_size += 29;
 -		rcu_read_unlock();
 -	}
 -
 -	buff = kmalloc(buf_size, GFP_ATOMIC);
 -	if (!buff) {
 -		ret = -ENOMEM;
 -		goto out;
 -	}
 -
 -	buff[0] = '\0';
 -	pos = 0;
 -
 -	for (i = 0; i < hash->size; i++) {
 -		head = &hash->table[i];
 -
 -		rcu_read_lock();
 -		hlist_for_each_entry_rcu(tt_local_entry, node,
 +		hlist_for_each_entry_rcu(tt_common_entry, node,
  					 head, hash_entry) {
 -			pos += snprintf(buff + pos, 30, " * %pM "
 -					"[%c%c%c%c%c]\n",
 -					tt_local_entry->addr,
 -					(tt_local_entry->flags &
 +			seq_printf(seq, " * %pM [%c%c%c%c%c]\n",
 +					tt_common_entry->addr,
 +					(tt_common_entry->flags &
  					 TT_CLIENT_ROAM ? 'R' : '.'),
 -					(tt_local_entry->flags &
 +					(tt_common_entry->flags &
  					 TT_CLIENT_NOPURGE ? 'P' : '.'),
 -					(tt_local_entry->flags &
 +					(tt_common_entry->flags &
  					 TT_CLIENT_NEW ? 'N' : '.'),
 -					(tt_local_entry->flags &
 +					(tt_common_entry->flags &
  					 TT_CLIENT_PENDING ? 'X' : '.'),
 -					(tt_local_entry->flags &
 +					(tt_common_entry->flags &
  					 TT_CLIENT_WIFI ? 'W' : '.'));
  		}
  		rcu_read_unlock();
  	}
 -
 -	seq_printf(seq, "%s", buff);
 -	kfree(buff);
  out:
  	if (primary_if)
  		hardif_free_ref(primary_if);
@@@ -364,13 -394,13 +365,13 @@@ static void tt_local_set_pending(struc
  				 struct tt_local_entry *tt_local_entry,
  				 uint16_t flags)
  {
 -	tt_local_event(bat_priv, tt_local_entry->addr,
 -		       tt_local_entry->flags | flags);
 +	tt_local_event(bat_priv, tt_local_entry->common.addr,
 +		       tt_local_entry->common.flags | flags);
  
  	/* The local client has to be marked as "pending to be removed" but has
  	 * to be kept in the table in order to send it in a full table
  	 * response issued before the net ttvn increment (consistency check) */
 -	tt_local_entry->flags |= TT_CLIENT_PENDING;
 +	tt_local_entry->common.flags |= TT_CLIENT_PENDING;
  }
  
  void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
@@@ -386,7 -416,7 +387,7 @@@
  			     (roaming ? TT_CLIENT_ROAM : NO_FLAGS));
  
  	bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: "
 -		"%s\n", tt_local_entry->addr, message);
 +		"%s\n", tt_local_entry->common.addr, message);
  out:
  	if (tt_local_entry)
  		tt_local_entry_free_ref(tt_local_entry);
@@@ -396,27 -426,23 +397,27 @@@ static void tt_local_purge(struct bat_p
  {
  	struct hashtable_t *hash = bat_priv->tt_local_hash;
  	struct tt_local_entry *tt_local_entry;
 +	struct tt_common_entry *tt_common_entry;
  	struct hlist_node *node, *node_tmp;
  	struct hlist_head *head;
  	spinlock_t *list_lock; /* protects write access to the hash lists */
 -	int i;
 +	uint32_t i;
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
 -		hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
 +		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
  					  head, hash_entry) {
 -			if (tt_local_entry->flags & TT_CLIENT_NOPURGE)
 +			tt_local_entry = container_of(tt_common_entry,
 +						      struct tt_local_entry,
 +						      common);
 +			if (tt_local_entry->common.flags & TT_CLIENT_NOPURGE)
  				continue;
  
  			/* entry already marked for deletion */
 -			if (tt_local_entry->flags & TT_CLIENT_PENDING)
 +			if (tt_local_entry->common.flags & TT_CLIENT_PENDING)
  				continue;
  
  			if (!is_out_of_time(tt_local_entry->last_seen,
@@@ -427,7 -453,7 +428,7 @@@
  					     TT_CLIENT_DEL);
  			bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) "
  				"pending to be removed: timed out\n",
 -				tt_local_entry->addr);
 +				tt_local_entry->common.addr);
  		}
  		spin_unlock_bh(list_lock);
  	}
@@@ -438,11 -464,10 +439,11 @@@ static void tt_local_table_free(struct 
  {
  	struct hashtable_t *hash;
  	spinlock_t *list_lock; /* protects write access to the hash lists */
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_local_entry *tt_local_entry;
  	struct hlist_node *node, *node_tmp;
  	struct hlist_head *head;
 -	int i;
 +	uint32_t i;
  
  	if (!bat_priv->tt_local_hash)
  		return;
@@@ -454,12 -479,9 +455,12 @@@
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
 -		hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
 +		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
  					  head, hash_entry) {
  			hlist_del_rcu(node);
 +			tt_local_entry = container_of(tt_common_entry,
 +						      struct tt_local_entry,
 +						      common);
  			tt_local_entry_free_ref(tt_local_entry);
  		}
  		spin_unlock_bh(list_lock);
@@@ -507,7 -529,6 +508,7 @@@ int tt_global_add(struct bat_priv *bat_
  	struct tt_global_entry *tt_global_entry;
  	struct orig_node *orig_node_tmp;
  	int ret = 0;
 +	int hash_added;
  
  	tt_global_entry = tt_global_hash_find(bat_priv, tt_addr);
  
@@@ -518,24 -539,18 +519,24 @@@
  		if (!tt_global_entry)
  			goto out;
  
 -		memcpy(tt_global_entry->addr, tt_addr, ETH_ALEN);
 +		memcpy(tt_global_entry->common.addr, tt_addr, ETH_ALEN);
 +		tt_global_entry->common.flags = NO_FLAGS;
 +		atomic_set(&tt_global_entry->common.refcount, 2);
  		/* Assign the new orig_node */
  		atomic_inc(&orig_node->refcount);
  		tt_global_entry->orig_node = orig_node;
  		tt_global_entry->ttvn = ttvn;
 -		tt_global_entry->flags = NO_FLAGS;
  		tt_global_entry->roam_at = 0;
 -		atomic_set(&tt_global_entry->refcount, 2);
  
 -		hash_add(bat_priv->tt_global_hash, compare_gtt,
 -			 choose_orig, tt_global_entry,
 -			 &tt_global_entry->hash_entry);
 +		hash_added = hash_add(bat_priv->tt_global_hash, compare_tt,
 +				 choose_orig, &tt_global_entry->common,
 +				 &tt_global_entry->common.hash_entry);
 +
 +		if (unlikely(hash_added != 0)) {
 +			/* remove the reference for the hash */
 +			tt_global_entry_free_ref(tt_global_entry);
 +			goto out_remove;
 +		}
  		atomic_inc(&orig_node->tt_size);
  	} else {
  		if (tt_global_entry->orig_node != orig_node) {
@@@ -546,21 -561,20 +547,21 @@@
  			orig_node_free_ref(orig_node_tmp);
  			atomic_inc(&orig_node->tt_size);
  		}
 +		tt_global_entry->common.flags = NO_FLAGS;
  		tt_global_entry->ttvn = ttvn;
 -		tt_global_entry->flags = NO_FLAGS;
  		tt_global_entry->roam_at = 0;
  	}
  
  	if (wifi)
 -		tt_global_entry->flags |= TT_CLIENT_WIFI;
 +		tt_global_entry->common.flags |= TT_CLIENT_WIFI;
  
  	bat_dbg(DBG_TT, bat_priv,
  		"Creating new global tt entry: %pM (via %pM)\n",
 -		tt_global_entry->addr, orig_node->orig);
 +		tt_global_entry->common.addr, orig_node->orig);
  
 +out_remove:
  	/* remove address from local hash if present */
 -	tt_local_remove(bat_priv, tt_global_entry->addr,
 +	tt_local_remove(bat_priv, tt_global_entry->common.addr,
  			"global tt received", roaming);
  	ret = 1;
  out:
@@@ -574,13 -588,13 +575,13 @@@ int tt_global_seq_print_text(struct seq
  	struct net_device *net_dev = (struct net_device *)seq->private;
  	struct bat_priv *bat_priv = netdev_priv(net_dev);
  	struct hashtable_t *hash = bat_priv->tt_global_hash;
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_global_entry *tt_global_entry;
  	struct hard_iface *primary_if;
  	struct hlist_node *node;
  	struct hlist_head *head;
 -	size_t buf_size, pos;
 -	char *buff;
 -	int i, ret = 0;
 +	uint32_t i;
 +	int ret = 0;
  
  	primary_if = primary_if_get_selected(bat_priv);
  	if (!primary_if) {
@@@ -603,32 -617,53 +604,32 @@@
  	seq_printf(seq, "       %-13s %s       %-15s %s %s\n",
  		   "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
  
 -	buf_size = 1;
 -	/* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
 -	 * xx:xx:xx:xx:xx:xx (cur_ttvn)\n"*/
 -	for (i = 0; i < hash->size; i++) {
 -		head = &hash->table[i];
 -
 -		rcu_read_lock();
 -		__hlist_for_each_rcu(node, head)
 -			buf_size += 67;
 -		rcu_read_unlock();
 -	}
 -
 -	buff = kmalloc(buf_size, GFP_ATOMIC);
 -	if (!buff) {
 -		ret = -ENOMEM;
 -		goto out;
 -	}
 -
 -	buff[0] = '\0';
 -	pos = 0;
 -
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
 -		hlist_for_each_entry_rcu(tt_global_entry, node,
 +		hlist_for_each_entry_rcu(tt_common_entry, node,
  					 head, hash_entry) {
 -			pos += snprintf(buff + pos, 69,
 -					" * %pM  (%3u) via %pM     (%3u)   "
 -					"[%c%c%c]\n", tt_global_entry->addr,
 +			tt_global_entry = container_of(tt_common_entry,
 +						       struct tt_global_entry,
 +						       common);
 +			seq_printf(seq, " * %pM  (%3u) via %pM     (%3u)   "
 +					"[%c%c%c]\n",
 +					tt_global_entry->common.addr,
  					tt_global_entry->ttvn,
  					tt_global_entry->orig_node->orig,
  					(uint8_t) atomic_read(
  						&tt_global_entry->orig_node->
  						last_ttvn),
 -					(tt_global_entry->flags &
 +					(tt_global_entry->common.flags &
  					 TT_CLIENT_ROAM ? 'R' : '.'),
 -					(tt_global_entry->flags &
 +					(tt_global_entry->common.flags &
  					 TT_CLIENT_PENDING ? 'X' : '.'),
 -					(tt_global_entry->flags &
 +					(tt_global_entry->common.flags &
  					 TT_CLIENT_WIFI ? 'W' : '.'));
  		}
  		rcu_read_unlock();
  	}
 -
 -	seq_printf(seq, "%s", buff);
 -	kfree(buff);
  out:
  	if (primary_if)
  		hardif_free_ref(primary_if);
@@@ -644,13 -679,13 +645,13 @@@ static void _tt_global_del(struct bat_p
  
  	bat_dbg(DBG_TT, bat_priv,
  		"Deleting global tt entry %pM (via %pM): %s\n",
 -		tt_global_entry->addr, tt_global_entry->orig_node->orig,
 +		tt_global_entry->common.addr, tt_global_entry->orig_node->orig,
  		message);
  
  	atomic_dec(&tt_global_entry->orig_node->tt_size);
  
 -	hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig,
 -		    tt_global_entry->addr);
 +	hash_remove(bat_priv->tt_global_hash, compare_tt, choose_orig,
 +		    tt_global_entry->common.addr);
  out:
  	if (tt_global_entry)
  		tt_global_entry_free_ref(tt_global_entry);
@@@ -661,6 -696,7 +662,7 @@@ void tt_global_del(struct bat_priv *bat
  		   const char *message, bool roaming)
  {
  	struct tt_global_entry *tt_global_entry = NULL;
+ 	struct tt_local_entry *tt_local_entry = NULL;
  
  	tt_global_entry = tt_global_hash_find(bat_priv, addr);
  	if (!tt_global_entry)
@@@ -668,23 -704,36 +670,37 @@@
  
  	if (tt_global_entry->orig_node == orig_node) {
  		if (roaming) {
- 			tt_global_entry->common.flags |= TT_CLIENT_ROAM;
- 			tt_global_entry->roam_at = jiffies;
- 			goto out;
+ 			/* if we are deleting a global entry due to a roam
+ 			 * event, there are two possibilities:
+ 			 * 1) the client roamed from node A to node B => we mark
+ 			 *    it with TT_CLIENT_ROAM, we start a timer and we
+ 			 *    wait for node B to claim it. In case of timeout
+ 			 *    the entry is purged.
+ 			 * 2) the client roamed to us => we can directly delete
+ 			 *    the global entry, since it is useless now. */
+ 			tt_local_entry = tt_local_hash_find(bat_priv,
 -							tt_global_entry->addr);
++							    tt_global_entry->common.addr);
+ 			if (!tt_local_entry) {
 -				tt_global_entry->flags |= TT_CLIENT_ROAM;
++				tt_global_entry->common.flags |= TT_CLIENT_ROAM;
+ 				tt_global_entry->roam_at = jiffies;
+ 				goto out;
+ 			}
  		}
  		_tt_global_del(bat_priv, tt_global_entry, message);
  	}
  out:
  	if (tt_global_entry)
  		tt_global_entry_free_ref(tt_global_entry);
+ 	if (tt_local_entry)
+ 		tt_local_entry_free_ref(tt_local_entry);
  }
  
  void tt_global_del_orig(struct bat_priv *bat_priv,
  			struct orig_node *orig_node, const char *message)
  {
  	struct tt_global_entry *tt_global_entry;
 -	int i;
 +	struct tt_common_entry *tt_common_entry;
 +	uint32_t i;
  	struct hashtable_t *hash = bat_priv->tt_global_hash;
  	struct hlist_node *node, *safe;
  	struct hlist_head *head;
@@@ -698,18 -747,14 +714,18 @@@
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
 -		hlist_for_each_entry_safe(tt_global_entry, node, safe,
 +		hlist_for_each_entry_safe(tt_common_entry, node, safe,
  					 head, hash_entry) {
 +			tt_global_entry = container_of(tt_common_entry,
 +						       struct tt_global_entry,
 +						       common);
  			if (tt_global_entry->orig_node == orig_node) {
  				bat_dbg(DBG_TT, bat_priv,
  					"Deleting global tt entry %pM "
 -					"(via %pM): originator time out\n",
 -					tt_global_entry->addr,
 -					tt_global_entry->orig_node->orig);
 +					"(via %pM): %s\n",
 +					tt_global_entry->common.addr,
 +					tt_global_entry->orig_node->orig,
 +					message);
  				hlist_del_rcu(node);
  				tt_global_entry_free_ref(tt_global_entry);
  			}
@@@ -722,24 -767,20 +738,24 @@@
  static void tt_global_roam_purge(struct bat_priv *bat_priv)
  {
  	struct hashtable_t *hash = bat_priv->tt_global_hash;
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_global_entry *tt_global_entry;
  	struct hlist_node *node, *node_tmp;
  	struct hlist_head *head;
  	spinlock_t *list_lock; /* protects write access to the hash lists */
 -	int i;
 +	uint32_t i;
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
 -		hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
 +		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
  					  head, hash_entry) {
 -			if (!(tt_global_entry->flags & TT_CLIENT_ROAM))
 +			tt_global_entry = container_of(tt_common_entry,
 +						       struct tt_global_entry,
 +						       common);
 +			if (!(tt_global_entry->common.flags & TT_CLIENT_ROAM))
  				continue;
  			if (!is_out_of_time(tt_global_entry->roam_at,
  					    TT_CLIENT_ROAM_TIMEOUT * 1000))
@@@ -747,7 -788,7 +763,7 @@@
  
  			bat_dbg(DBG_TT, bat_priv, "Deleting global "
  				"tt entry (%pM): Roaming timeout\n",
 -				tt_global_entry->addr);
 +				tt_global_entry->common.addr);
  			atomic_dec(&tt_global_entry->orig_node->tt_size);
  			hlist_del_rcu(node);
  			tt_global_entry_free_ref(tt_global_entry);
@@@ -761,11 -802,10 +777,11 @@@ static void tt_global_table_free(struc
  {
  	struct hashtable_t *hash;
  	spinlock_t *list_lock; /* protects write access to the hash lists */
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_global_entry *tt_global_entry;
  	struct hlist_node *node, *node_tmp;
  	struct hlist_head *head;
 -	int i;
 +	uint32_t i;
  
  	if (!bat_priv->tt_global_hash)
  		return;
@@@ -777,12 -817,9 +793,12 @@@
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
 -		hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
 +		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
  					  head, hash_entry) {
  			hlist_del_rcu(node);
 +			tt_global_entry = container_of(tt_common_entry,
 +						       struct tt_global_entry,
 +						       common);
  			tt_global_entry_free_ref(tt_global_entry);
  		}
  		spin_unlock_bh(list_lock);
@@@ -798,8 -835,8 +814,8 @@@ static bool _is_ap_isolated(struct tt_l
  {
  	bool ret = false;
  
 -	if (tt_local_entry->flags & TT_CLIENT_WIFI &&
 -	    tt_global_entry->flags & TT_CLIENT_WIFI)
 +	if (tt_local_entry->common.flags & TT_CLIENT_WIFI &&
 +	    tt_global_entry->common.flags & TT_CLIENT_WIFI)
  		ret = true;
  
  	return ret;
@@@ -832,7 -869,7 +848,7 @@@ struct orig_node *transtable_search(str
  
  	/* A global client marked as PENDING has already moved from that
  	 * originator */
 -	if (tt_global_entry->flags & TT_CLIENT_PENDING)
 +	if (tt_global_entry->common.flags & TT_CLIENT_PENDING)
  		goto out;
  
  	orig_node = tt_global_entry->orig_node;
@@@ -851,34 -888,29 +867,34 @@@ uint16_t tt_global_crc(struct bat_priv 
  {
  	uint16_t total = 0, total_one;
  	struct hashtable_t *hash = bat_priv->tt_global_hash;
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_global_entry *tt_global_entry;
  	struct hlist_node *node;
  	struct hlist_head *head;
 -	int i, j;
 +	uint32_t i;
 +	int j;
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
 -		hlist_for_each_entry_rcu(tt_global_entry, node,
 +		hlist_for_each_entry_rcu(tt_common_entry, node,
  					 head, hash_entry) {
 +			tt_global_entry = container_of(tt_common_entry,
 +						       struct tt_global_entry,
 +						       common);
  			if (compare_eth(tt_global_entry->orig_node,
  					orig_node)) {
  				/* Roaming clients are in the global table for
  				 * consistency only. They don't have to be
  				 * taken into account while computing the
  				 * global crc */
 -				if (tt_global_entry->flags & TT_CLIENT_ROAM)
 +				if (tt_common_entry->flags & TT_CLIENT_ROAM)
  					continue;
  				total_one = 0;
  				for (j = 0; j < ETH_ALEN; j++)
  					total_one = crc16_byte(total_one,
 -						tt_global_entry->addr[j]);
 +						tt_common_entry->addr[j]);
  				total ^= total_one;
  			}
  		}
@@@ -893,26 -925,25 +909,26 @@@ uint16_t tt_local_crc(struct bat_priv *
  {
  	uint16_t total = 0, total_one;
  	struct hashtable_t *hash = bat_priv->tt_local_hash;
 -	struct tt_local_entry *tt_local_entry;
 +	struct tt_common_entry *tt_common_entry;
  	struct hlist_node *node;
  	struct hlist_head *head;
 -	int i, j;
 +	uint32_t i;
 +	int j;
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
 -		hlist_for_each_entry_rcu(tt_local_entry, node,
 +		hlist_for_each_entry_rcu(tt_common_entry, node,
  					 head, hash_entry) {
  			/* not yet committed clients have not to be taken into
  			 * account while computing the CRC */
 -			if (tt_local_entry->flags & TT_CLIENT_NEW)
 +			if (tt_common_entry->flags & TT_CLIENT_NEW)
  				continue;
  			total_one = 0;
  			for (j = 0; j < ETH_ALEN; j++)
  				total_one = crc16_byte(total_one,
 -						   tt_local_entry->addr[j]);
 +						   tt_common_entry->addr[j]);
  			total ^= total_one;
  		}
  		rcu_read_unlock();
@@@ -1001,25 -1032,21 +1017,25 @@@ unlock
  /* data_ptr is useless here, but has to be kept to respect the prototype */
  static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr)
  {
 -	const struct tt_local_entry *tt_local_entry = entry_ptr;
 +	const struct tt_common_entry *tt_common_entry = entry_ptr;
  
 -	if (tt_local_entry->flags & TT_CLIENT_NEW)
 +	if (tt_common_entry->flags & TT_CLIENT_NEW)
  		return 0;
  	return 1;
  }
  
  static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr)
  {
 -	const struct tt_global_entry *tt_global_entry = entry_ptr;
 +	const struct tt_common_entry *tt_common_entry = entry_ptr;
 +	const struct tt_global_entry *tt_global_entry;
  	const struct orig_node *orig_node = data_ptr;
  
 -	if (tt_global_entry->flags & TT_CLIENT_ROAM)
 +	if (tt_common_entry->flags & TT_CLIENT_ROAM)
  		return 0;
  
 +	tt_global_entry = container_of(tt_common_entry, struct tt_global_entry,
 +				       common);
 +
  	return (tt_global_entry->orig_node == orig_node);
  }
  
@@@ -1030,7 -1057,7 +1046,7 @@@ static struct sk_buff *tt_response_fill
  							      const void *),
  					      void *cb_data)
  {
 -	struct tt_local_entry *tt_local_entry;
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_query_packet *tt_response;
  	struct tt_change *tt_change;
  	struct hlist_node *node;
@@@ -1038,7 -1065,7 +1054,7 @@@
  	struct sk_buff *skb = NULL;
  	uint16_t tt_tot, tt_count;
  	ssize_t tt_query_size = sizeof(struct tt_query_packet);
 -	int i;
 +	uint32_t i;
  
  	if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
  		tt_len = primary_if->soft_iface->mtu - tt_query_size;
@@@ -1062,16 -1089,15 +1078,16 @@@
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
 -		hlist_for_each_entry_rcu(tt_local_entry, node,
 +		hlist_for_each_entry_rcu(tt_common_entry, node,
  					 head, hash_entry) {
  			if (tt_count == tt_tot)
  				break;
  
 -			if ((valid_cb) && (!valid_cb(tt_local_entry, cb_data)))
 +			if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
  				continue;
  
 -			memcpy(tt_change->addr, tt_local_entry->addr, ETH_ALEN);
 +			memcpy(tt_change->addr, tt_common_entry->addr,
 +			       ETH_ALEN);
  			tt_change->flags = NO_FLAGS;
  
  			tt_count++;
@@@ -1178,11 -1204,11 +1194,11 @@@ static bool send_other_tt_response(stru
  		(tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
  
  	/* Let's get the orig node of the REAL destination */
 -	req_dst_orig_node = get_orig_node(bat_priv, tt_request->dst);
 +	req_dst_orig_node = orig_hash_find(bat_priv, tt_request->dst);
  	if (!req_dst_orig_node)
  		goto out;
  
 -	res_dst_orig_node = get_orig_node(bat_priv, tt_request->src);
 +	res_dst_orig_node = orig_hash_find(bat_priv, tt_request->src);
  	if (!res_dst_orig_node)
  		goto out;
  
@@@ -1308,7 -1334,7 +1324,7 @@@ static bool send_my_tt_response(struct 
  	my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
  	req_ttvn = tt_request->ttvn;
  
 -	orig_node = get_orig_node(bat_priv, tt_request->src);
 +	orig_node = orig_hash_find(bat_priv, tt_request->src);
  	if (!orig_node)
  		goto out;
  
@@@ -1488,7 -1514,7 +1504,7 @@@ bool is_my_client(struct bat_priv *bat_
  		goto out;
  	/* Check if the client has been logically deleted (but is kept for
  	 * consistency purpose) */
 -	if (tt_local_entry->flags & TT_CLIENT_PENDING)
 +	if (tt_local_entry->common.flags & TT_CLIENT_PENDING)
  		goto out;
  	ret = true;
  out:
@@@ -1711,53 -1737,45 +1727,53 @@@ void tt_free(struct bat_priv *bat_priv
  	kfree(bat_priv->tt_buff);
  }
  
 -/* This function will reset the specified flags from all the entries in
 - * the given hash table and will increment num_local_tt for each involved
 - * entry */
 -static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags)
 +/* This function will enable or disable the specified flags for all the entries
 + * in the given hash table and returns the number of modified entries */
 +static uint16_t tt_set_flags(struct hashtable_t *hash, uint16_t flags,
 +			     bool enable)
  {
 -	int i;
 -	struct hashtable_t *hash = bat_priv->tt_local_hash;
 +	uint32_t i;
 +	uint16_t changed_num = 0;
  	struct hlist_head *head;
  	struct hlist_node *node;
 -	struct tt_local_entry *tt_local_entry;
 +	struct tt_common_entry *tt_common_entry;
  
  	if (!hash)
 -		return;
 +		goto out;
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
 -		hlist_for_each_entry_rcu(tt_local_entry, node,
 +		hlist_for_each_entry_rcu(tt_common_entry, node,
  					 head, hash_entry) {
 -			if (!(tt_local_entry->flags & flags))
 -				continue;
 -			tt_local_entry->flags &= ~flags;
 -			atomic_inc(&bat_priv->num_local_tt);
 +			if (enable) {
 +				if ((tt_common_entry->flags & flags) == flags)
 +					continue;
 +				tt_common_entry->flags |= flags;
 +			} else {
 +				if (!(tt_common_entry->flags & flags))
 +					continue;
 +				tt_common_entry->flags &= ~flags;
 +			}
 +			changed_num++;
  		}
  		rcu_read_unlock();
  	}
 -
 +out:
 +	return changed_num;
  }
  
  /* Purge out all the tt local entries marked with TT_CLIENT_PENDING */
  static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
  {
  	struct hashtable_t *hash = bat_priv->tt_local_hash;
 +	struct tt_common_entry *tt_common_entry;
  	struct tt_local_entry *tt_local_entry;
  	struct hlist_node *node, *node_tmp;
  	struct hlist_head *head;
  	spinlock_t *list_lock; /* protects write access to the hash lists */
 -	int i;
 +	uint32_t i;
  
  	if (!hash)
  		return;
@@@ -1767,19 -1785,16 +1783,19 @@@
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
 -		hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
 +		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
  					  head, hash_entry) {
 -			if (!(tt_local_entry->flags & TT_CLIENT_PENDING))
 +			if (!(tt_common_entry->flags & TT_CLIENT_PENDING))
  				continue;
  
  			bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry "
 -				"(%pM): pending\n", tt_local_entry->addr);
 +				"(%pM): pending\n", tt_common_entry->addr);
  
  			atomic_dec(&bat_priv->num_local_tt);
  			hlist_del_rcu(node);
 +			tt_local_entry = container_of(tt_common_entry,
 +						      struct tt_local_entry,
 +						      common);
  			tt_local_entry_free_ref(tt_local_entry);
  		}
  		spin_unlock_bh(list_lock);
@@@ -1789,11 -1804,7 +1805,11 @@@
  
  void tt_commit_changes(struct bat_priv *bat_priv)
  {
 -	tt_local_reset_flags(bat_priv, TT_CLIENT_NEW);
 +	uint16_t changed_num = tt_set_flags(bat_priv->tt_local_hash,
 +					    TT_CLIENT_NEW, false);
 +	/* all the reset entries have now to be effectively counted as local
 +	 * entries */
 +	atomic_add(changed_num, &bat_priv->num_local_tt);
  	tt_local_purge_pending_clients(bat_priv);
  
  	/* Increment the TTVN only once per OGM interval */
diff --combined net/ipv4/ipip.c
index 9490690,0b2e732..413ed1b
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@@ -148,7 -148,7 +148,7 @@@ struct pcpu_tstats 
  	unsigned long	rx_bytes;
  	unsigned long	tx_packets;
  	unsigned long	tx_bytes;
 -};
 +} __attribute__((aligned(4*sizeof(unsigned long))));
  
  static struct net_device_stats *ipip_get_stats(struct net_device *dev)
  {
@@@ -285,6 -285,8 +285,8 @@@ static struct ip_tunnel * ipip_tunnel_l
  	if (register_netdevice(dev) < 0)
  		goto failed_free;
  
+ 	strcpy(nt->parms.name, dev->name);
+ 
  	dev_hold(dev);
  	ipip_tunnel_link(ipn, nt);
  	return nt;
@@@ -759,7 -761,6 +761,6 @@@ static int ipip_tunnel_init(struct net_
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  
  	tunnel->dev = dev;
- 	strcpy(tunnel->parms.name, dev->name);
  
  	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
  	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
@@@ -825,6 -826,7 +826,7 @@@ static void ipip_destroy_tunnels(struc
  static int __net_init ipip_init_net(struct net *net)
  {
  	struct ipip_net *ipn = net_generic(net, ipip_net_id);
+ 	struct ip_tunnel *t;
  	int err;
  
  	ipn->tunnels[0] = ipn->tunnels_wc;
@@@ -848,6 -850,9 +850,9 @@@
  	if ((err = register_netdev(ipn->fb_tunnel_dev)))
  		goto err_reg_dev;
  
+ 	t = netdev_priv(ipn->fb_tunnel_dev);
+ 
+ 	strcpy(t->parms.name, ipn->fb_tunnel_dev->name);
  	return 0;
  
  err_reg_dev:
diff --combined net/ipv6/addrconf.c
index 94f3fd9,36806de..59a9d0e
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@@ -630,13 -630,13 +630,13 @@@ ipv6_add_addr(struct inet6_dev *idev, c
  		goto out;
  	}
  
 -	rt = addrconf_dst_alloc(idev, addr, 0);
 +	rt = addrconf_dst_alloc(idev, addr, false);
  	if (IS_ERR(rt)) {
  		err = PTR_ERR(rt);
  		goto out;
  	}
  
 -	ipv6_addr_copy(&ifa->addr, addr);
 +	ifa->addr = *addr;
  
  	spin_lock_init(&ifa->lock);
  	spin_lock_init(&ifa->state_lock);
@@@ -657,7 -657,7 +657,7 @@@
  	 * layer address of our nexhop router
  	 */
  
 -	if (dst_get_neighbour_raw(&rt->dst) == NULL)
 +	if (dst_get_neighbour_noref_raw(&rt->dst) == NULL)
  		ifa->flags &= ~IFA_F_OPTIMISTIC;
  
  	ifa->idev = idev;
@@@ -1228,7 -1228,7 +1228,7 @@@ try_nextdev
  	if (!hiscore->ifa)
  		return -EADDRNOTAVAIL;
  
 -	ipv6_addr_copy(saddr, &hiscore->ifa->addr);
 +	*saddr = hiscore->ifa->addr;
  	in6_ifa_put(hiscore->ifa);
  	return 0;
  }
@@@ -1249,7 -1249,7 +1249,7 @@@ int ipv6_get_lladdr(struct net_device *
  		list_for_each_entry(ifp, &idev->addr_list, if_list) {
  			if (ifp->scope == IFA_LINK &&
  			    !(ifp->flags & banned_flags)) {
 -				ipv6_addr_copy(addr, &ifp->addr);
 +				*addr = ifp->addr;
  				err = 0;
  				break;
  			}
@@@ -1700,7 -1700,7 +1700,7 @@@ addrconf_prefix_route(struct in6_addr *
  		.fc_protocol = RTPROT_KERNEL,
  	};
  
 -	ipv6_addr_copy(&cfg.fc_dst, pfx);
 +	cfg.fc_dst = *pfx;
  
  	/* Prevent useless cloning on PtP SIT.
  	   This thing is done here expecting that the whole
@@@ -1805,7 -1805,8 +1805,8 @@@ static struct inet6_dev *addrconf_add_d
  		return ERR_PTR(-EACCES);
  
  	/* Add default multicast route */
- 	addrconf_add_mroute(dev);
+ 	if (!(dev->flags & IFF_LOOPBACK))
+ 		addrconf_add_mroute(dev);
  
  	/* Add link local route */
  	addrconf_add_lroute(dev);
diff --combined net/ipv6/route.c
index 4bf362b,b582a0a..ad43854
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@@ -247,9 -247,9 +247,9 @@@ static inline struct rt6_info *ip6_dst_
  {
  	struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags);
  
 -	if (rt != NULL)
 +	if (rt)
  		memset(&rt->rt6i_table, 0,
 -			sizeof(*rt) - sizeof(struct dst_entry));
 +		       sizeof(*rt) - sizeof(struct dst_entry));
  
  	return rt;
  }
@@@ -263,7 -263,7 +263,7 @@@ static void ip6_dst_destroy(struct dst_
  	if (!(rt->dst.flags & DST_HOST))
  		dst_destroy_metrics_generic(dst);
  
 -	if (idev != NULL) {
 +	if (idev) {
  		rt->rt6i_idev = NULL;
  		in6_dev_put(idev);
  	}
@@@ -299,10 -299,10 +299,10 @@@ static void ip6_dst_ifdown(struct dst_e
  	struct net_device *loopback_dev =
  		dev_net(dev)->loopback_dev;
  
 -	if (dev != loopback_dev && idev != NULL && idev->dev == dev) {
 +	if (dev != loopback_dev && idev && idev->dev == dev) {
  		struct inet6_dev *loopback_idev =
  			in6_dev_get(loopback_dev);
 -		if (loopback_idev != NULL) {
 +		if (loopback_idev) {
  			rt->rt6i_idev = loopback_idev;
  			in6_dev_put(idev);
  		}
@@@ -344,7 -344,7 +344,7 @@@ static inline struct rt6_info *rt6_devi
  			if (dev->ifindex == oif)
  				return sprt;
  			if (dev->flags & IFF_LOOPBACK) {
 -				if (sprt->rt6i_idev == NULL ||
 +				if (!sprt->rt6i_idev ||
  				    sprt->rt6i_idev->dev->ifindex != oif) {
  					if (flags & RT6_LOOKUP_F_IFACE && oif)
  						continue;
@@@ -385,7 -385,7 +385,7 @@@ static void rt6_probe(struct rt6_info *
  	 * to no more than one per minute.
  	 */
  	rcu_read_lock();
 -	neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
 +	neigh = rt ? dst_get_neighbour_noref(&rt->dst) : NULL;
  	if (!neigh || (neigh->nud_state & NUD_VALID))
  		goto out;
  	read_lock_bh(&neigh->lock);
@@@ -432,7 -432,7 +432,7 @@@ static inline int rt6_check_neigh(struc
  	int m;
  
  	rcu_read_lock();
 -	neigh = dst_get_neighbour(&rt->dst);
 +	neigh = dst_get_neighbour_noref(&rt->dst);
  	if (rt->rt6i_flags & RTF_NONEXTHOP ||
  	    !(rt->rt6i_flags & RTF_GATEWAY))
  		m = 1;
@@@ -636,7 -636,7 +636,7 @@@ do { 
  				goto restart; \
  		} \
  	} \
 -} while(0)
 +} while (0)
  
  static struct rt6_info *ip6_pol_route_lookup(struct net *net,
  					     struct fib6_table *table,
@@@ -727,25 -727,24 +727,25 @@@ static struct rt6_info *rt6_alloc_cow(c
  		struct neighbour *neigh;
  		int attempts = !in_softirq();
  
 -		if (!(rt->rt6i_flags&RTF_GATEWAY)) {
 +		if (!(rt->rt6i_flags & RTF_GATEWAY)) {
- 			if (rt->rt6i_dst.plen != 128 &&
+ 			if (ort->rt6i_dst.plen != 128 &&
  			    ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
  				rt->rt6i_flags |= RTF_ANYCAST;
 -			ipv6_addr_copy(&rt->rt6i_gateway, daddr);
 +			rt->rt6i_gateway = *daddr;
  		}
  
  		rt->rt6i_flags |= RTF_CACHE;
  
  #ifdef CONFIG_IPV6_SUBTREES
  		if (rt->rt6i_src.plen && saddr) {
 -			ipv6_addr_copy(&rt->rt6i_src.addr, saddr);
 +			rt->rt6i_src.addr = *saddr;
  			rt->rt6i_src.plen = 128;
  		}
  #endif
  
  	retry:
 -		neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
 +		neigh = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway,
 +					     rt->rt6i_dev);
  		if (IS_ERR(neigh)) {
  			struct net *net = dev_net(rt->rt6i_dev);
  			int saved_rt_min_interval =
@@@ -786,7 -785,7 +786,7 @@@ static struct rt6_info *rt6_alloc_clone
  
  	if (rt) {
  		rt->rt6i_flags |= RTF_CACHE;
 -		dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst)));
 +		dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_noref_raw(&ort->dst)));
  	}
  	return rt;
  }
@@@ -820,7 -819,7 +820,7 @@@ restart
  	dst_hold(&rt->dst);
  	read_unlock_bh(&table->tb6_lock);
  
 -	if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
 +	if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
  		nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
  	else if (!(rt->dst.flags & DST_HOST))
  		nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@@ -876,7 -875,7 +876,7 @@@ void ip6_route_input(struct sk_buff *sk
  		.flowi6_iif = skb->dev->ifindex,
  		.daddr = iph->daddr,
  		.saddr = iph->saddr,
 -		.flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
 +		.flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK,
  		.flowi6_mark = skb->mark,
  		.flowi6_proto = iph->nexthdr,
  	};
@@@ -935,7 -934,7 +935,7 @@@ struct dst_entry *ip6_blackhole_route(s
  			in6_dev_hold(rt->rt6i_idev);
  		rt->rt6i_expires = 0;
  
 -		ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
 +		rt->rt6i_gateway = ort->rt6i_gateway;
  		rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
  		rt->rt6i_metric = 0;
  
@@@ -998,7 -997,7 +998,7 @@@ static void ip6_link_failure(struct sk_
  
  	rt = (struct rt6_info *) skb_dst(skb);
  	if (rt) {
 -		if (rt->rt6i_flags&RTF_CACHE) {
 +		if (rt->rt6i_flags & RTF_CACHE) {
  			dst_set_expires(&rt->dst, 0);
  			rt->rt6i_flags |= RTF_EXPIRES;
  		} else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))
@@@ -1068,38 -1067,34 +1068,38 @@@ static DEFINE_SPINLOCK(icmp6_dst_lock)
  
  struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
  				  struct neighbour *neigh,
 -				  const struct in6_addr *addr)
 +				  struct flowi6 *fl6)
  {
 +	struct dst_entry *dst;
  	struct rt6_info *rt;
  	struct inet6_dev *idev = in6_dev_get(dev);
  	struct net *net = dev_net(dev);
  
 -	if (unlikely(idev == NULL))
 +	if (unlikely(!idev))
  		return NULL;
  
  	rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0);
 -	if (unlikely(rt == NULL)) {
 +	if (unlikely(!rt)) {
  		in6_dev_put(idev);
 +		dst = ERR_PTR(-ENOMEM);
  		goto out;
  	}
  
  	if (neigh)
  		neigh_hold(neigh);
  	else {
 -		neigh = ndisc_get_neigh(dev, addr);
 -		if (IS_ERR(neigh))
 -			neigh = NULL;
 +		neigh = __neigh_lookup_errno(&nd_tbl, &fl6->daddr, dev);
 +		if (IS_ERR(neigh)) {
 +			dst_free(&rt->dst);
 +			return ERR_CAST(neigh);
 +		}
  	}
  
  	rt->dst.flags |= DST_HOST;
  	rt->dst.output  = ip6_output;
  	dst_set_neighbour(&rt->dst, neigh);
  	atomic_set(&rt->dst.__refcnt, 1);
 -	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 +	rt->rt6i_dst.addr = fl6->daddr;
  	rt->rt6i_dst.plen = 128;
  	rt->rt6i_idev     = idev;
  	dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
@@@ -1111,10 -1106,8 +1111,10 @@@
  
  	fib6_force_start_gc(net);
  
 +	dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0);
 +
  out:
 -	return &rt->dst;
 +	return dst;
  }
  
  int icmp6_dst_gc(void)
@@@ -1244,24 -1237,15 +1244,24 @@@ int ip6_route_add(struct fib6_config *c
  	if (cfg->fc_metric == 0)
  		cfg->fc_metric = IP6_RT_PRIO_USER;
  
 -	table = fib6_new_table(net, cfg->fc_table);
 -	if (table == NULL) {
 -		err = -ENOBUFS;
 -		goto out;
 +	err = -ENOBUFS;
 +	if (cfg->fc_nlinfo.nlh &&
 +	    !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
 +		table = fib6_get_table(net, cfg->fc_table);
 +		if (!table) {
 +			printk(KERN_WARNING "IPv6: NLM_F_CREATE should be specified when creating new route\n");
 +			table = fib6_new_table(net, cfg->fc_table);
 +		}
 +	} else {
 +		table = fib6_new_table(net, cfg->fc_table);
  	}
  
 +	if (!table)
 +		goto out;
 +
  	rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT);
  
 -	if (rt == NULL) {
 +	if (!rt) {
  		err = -ENOMEM;
  		goto out;
  	}
@@@ -1310,9 -1294,8 +1310,9 @@@
  	   they would result in kernel looping; promote them to reject routes
  	 */
  	if ((cfg->fc_flags & RTF_REJECT) ||
 -	    (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK)
 -					      && !(cfg->fc_flags&RTF_LOCAL))) {
 +	    (dev && (dev->flags & IFF_LOOPBACK) &&
 +	     !(addr_type & IPV6_ADDR_LOOPBACK) &&
 +	     !(cfg->fc_flags & RTF_LOCAL))) {
  		/* hold loopback dev/idev if we haven't done so. */
  		if (dev != net->loopback_dev) {
  			if (dev) {
@@@ -1339,7 -1322,7 +1339,7 @@@
  		int gwa_type;
  
  		gw_addr = &cfg->fc_gateway;
 -		ipv6_addr_copy(&rt->rt6i_gateway, gw_addr);
 +		rt->rt6i_gateway = *gw_addr;
  		gwa_type = ipv6_addr_type(gw_addr);
  
  		if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
@@@ -1353,13 -1336,13 +1353,13 @@@
  			   some exceptions. --ANK
  			 */
  			err = -EINVAL;
 -			if (!(gwa_type&IPV6_ADDR_UNICAST))
 +			if (!(gwa_type & IPV6_ADDR_UNICAST))
  				goto out;
  
  			grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
  
  			err = -EHOSTUNREACH;
 -			if (grt == NULL)
 +			if (!grt)
  				goto out;
  			if (dev) {
  				if (dev != grt->rt6i_dev) {
@@@ -1372,7 -1355,7 +1372,7 @@@
  				dev_hold(dev);
  				in6_dev_hold(grt->rt6i_idev);
  			}
 -			if (!(grt->rt6i_flags&RTF_GATEWAY))
 +			if (!(grt->rt6i_flags & RTF_GATEWAY))
  				err = 0;
  			dst_release(&grt->dst);
  
@@@ -1380,12 -1363,12 +1380,12 @@@
  				goto out;
  		}
  		err = -EINVAL;
 -		if (dev == NULL || (dev->flags&IFF_LOOPBACK))
 +		if (!dev || (dev->flags & IFF_LOOPBACK))
  			goto out;
  	}
  
  	err = -ENODEV;
 -	if (dev == NULL)
 +	if (!dev)
  		goto out;
  
  	if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
@@@ -1393,7 -1376,7 +1393,7 @@@
  			err = -EINVAL;
  			goto out;
  		}
 -		ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc);
 +		rt->rt6i_prefsrc.addr = cfg->fc_prefsrc;
  		rt->rt6i_prefsrc.plen = 128;
  	} else
  		rt->rt6i_prefsrc.plen = 0;
@@@ -1482,7 -1465,7 +1482,7 @@@ static int ip6_route_del(struct fib6_co
  	int err = -ESRCH;
  
  	table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table);
 -	if (table == NULL)
 +	if (!table)
  		return err;
  
  	read_lock_bh(&table->tb6_lock);
@@@ -1494,7 -1477,7 +1494,7 @@@
  	if (fn) {
  		for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
  			if (cfg->fc_ifindex &&
 -			    (rt->rt6i_dev == NULL ||
 +			    (!rt->rt6i_dev ||
  			     rt->rt6i_dev->ifindex != cfg->fc_ifindex))
  				continue;
  			if (cfg->fc_flags & RTF_GATEWAY &&
@@@ -1590,7 -1573,7 +1590,7 @@@ static struct rt6_info *ip6_route_redir
  		},
  	};
  
 -	ipv6_addr_copy(&rdfl.gateway, gateway);
 +	rdfl.gateway = *gateway;
  
  	if (rt6_need_strict(dest))
  		flags |= RT6_LOOKUP_F_IFACE;
@@@ -1635,18 -1618,18 +1635,18 @@@ void rt6_redirect(const struct in6_add
  	dst_confirm(&rt->dst);
  
  	/* Duplicate redirect: silently ignore. */
 -	if (neigh == dst_get_neighbour_raw(&rt->dst))
 +	if (neigh == dst_get_neighbour_noref_raw(&rt->dst))
  		goto out;
  
  	nrt = ip6_rt_copy(rt, dest);
 -	if (nrt == NULL)
 +	if (!nrt)
  		goto out;
  
  	nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE;
  	if (on_link)
  		nrt->rt6i_flags &= ~RTF_GATEWAY;
  
 -	ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
 +	nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
  	dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
  
  	if (ip6_ins_rt(nrt))
@@@ -1656,7 -1639,7 +1656,7 @@@
  	netevent.new = &nrt->dst;
  	call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
  
 -	if (rt->rt6i_flags&RTF_CACHE) {
 +	if (rt->rt6i_flags & RTF_CACHE) {
  		ip6_del_rt(rt);
  		return;
  	}
@@@ -1677,7 -1660,7 +1677,7 @@@ static void rt6_do_pmtu_disc(const stru
  	int allfrag = 0;
  again:
  	rt = rt6_lookup(net, daddr, saddr, ifindex, 0);
 -	if (rt == NULL)
 +	if (!rt)
  		return;
  
  	if (rt6_check_expired(rt)) {
@@@ -1727,7 -1710,7 +1727,7 @@@
  	   1. It is connected route. Action: COW
  	   2. It is gatewayed route or NONEXTHOP route. Action: clone it.
  	 */
 -	if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
 +	if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
  		nrt = rt6_alloc_cow(rt, daddr, saddr);
  	else
  		nrt = rt6_alloc_clone(rt, daddr);
@@@ -1792,7 -1775,7 +1792,7 @@@ static struct rt6_info *ip6_rt_copy(con
  		rt->dst.output = ort->dst.output;
  		rt->dst.flags |= DST_HOST;
  
 -		ipv6_addr_copy(&rt->rt6i_dst.addr, dest);
 +		rt->rt6i_dst.addr = *dest;
  		rt->rt6i_dst.plen = 128;
  		dst_copy_metrics(&rt->dst, &ort->dst);
  		rt->dst.error = ort->dst.error;
@@@ -1802,7 -1785,7 +1802,7 @@@
  		rt->dst.lastuse = jiffies;
  		rt->rt6i_expires = 0;
  
 -		ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
 +		rt->rt6i_gateway = ort->rt6i_gateway;
  		rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
  		rt->rt6i_metric = 0;
  
@@@ -1825,7 -1808,7 +1825,7 @@@ static struct rt6_info *rt6_get_route_i
  	struct fib6_table *table;
  
  	table = fib6_get_table(net, RT6_TABLE_INFO);
 -	if (table == NULL)
 +	if (!table)
  		return NULL;
  
  	write_lock_bh(&table->tb6_lock);
@@@ -1865,8 -1848,8 +1865,8 @@@ static struct rt6_info *rt6_add_route_i
  		.fc_nlinfo.nl_net = net,
  	};
  
 -	ipv6_addr_copy(&cfg.fc_dst, prefix);
 -	ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
 +	cfg.fc_dst = *prefix;
 +	cfg.fc_gateway = *gwaddr;
  
  	/* We should treat it as a default route if prefix length is 0. */
  	if (!prefixlen)
@@@ -1884,7 -1867,7 +1884,7 @@@ struct rt6_info *rt6_get_dflt_router(co
  	struct fib6_table *table;
  
  	table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
 -	if (table == NULL)
 +	if (!table)
  		return NULL;
  
  	write_lock_bh(&table->tb6_lock);
@@@ -1915,7 -1898,7 +1915,7 @@@ struct rt6_info *rt6_add_dflt_router(co
  		.fc_nlinfo.nl_net = dev_net(dev),
  	};
  
 -	ipv6_addr_copy(&cfg.fc_gateway, gwaddr);
 +	cfg.fc_gateway = *gwaddr;
  
  	ip6_route_add(&cfg);
  
@@@ -1929,7 -1912,7 +1929,7 @@@ void rt6_purge_dflt_routers(struct net 
  
  	/* NOTE: Keep consistent with rt6_get_dflt_router */
  	table = fib6_get_table(net, RT6_TABLE_DFLT);
 -	if (table == NULL)
 +	if (!table)
  		return;
  
  restart:
@@@ -1961,9 -1944,9 +1961,9 @@@ static void rtmsg_to_fib6_config(struc
  
  	cfg->fc_nlinfo.nl_net = net;
  
 -	ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
 -	ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
 -	ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
 +	cfg->fc_dst = rtmsg->rtmsg_dst;
 +	cfg->fc_src = rtmsg->rtmsg_src;
 +	cfg->fc_gateway = rtmsg->rtmsg_gateway;
  }
  
  int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
@@@ -2062,14 -2045,14 +2062,14 @@@ static int ip6_pkt_prohibit_out(struct 
  
  struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
  				    const struct in6_addr *addr,
 -				    int anycast)
 +				    bool anycast)
  {
  	struct net *net = dev_net(idev->dev);
  	struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
  					    net->loopback_dev, 0);
  	struct neighbour *neigh;
  
 -	if (rt == NULL) {
 +	if (!rt) {
  		if (net_ratelimit())
  			pr_warning("IPv6:  Maximum number of routes reached,"
  				   " consider increasing route/max_size.\n");
@@@ -2089,7 -2072,7 +2089,7 @@@
  		rt->rt6i_flags |= RTF_ANYCAST;
  	else
  		rt->rt6i_flags |= RTF_LOCAL;
 -	neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
 +	neigh = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, rt->rt6i_dev);
  	if (IS_ERR(neigh)) {
  		dst_free(&rt->dst);
  
@@@ -2097,7 -2080,7 +2097,7 @@@
  	}
  	dst_set_neighbour(&rt->dst, neigh);
  
 -	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 +	rt->rt6i_dst.addr = *addr;
  	rt->rt6i_dst.plen = 128;
  	rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
  
@@@ -2115,7 -2098,7 +2115,7 @@@ int ip6_route_get_saddr(struct net *net
  	struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt);
  	int err = 0;
  	if (rt->rt6i_prefsrc.plen)
 -		ipv6_addr_copy(saddr, &rt->rt6i_prefsrc.addr);
 +		*saddr = rt->rt6i_prefsrc.addr;
  	else
  		err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
  					 daddr, prefs, saddr);
@@@ -2135,7 -2118,7 +2135,7 @@@ static int fib6_remove_prefsrc(struct r
  	struct net *net = ((struct arg_dev_net_ip *)arg)->net;
  	struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
  
 -	if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
 +	if (((void *)rt->rt6i_dev == dev || !dev) &&
  	    rt != net->ipv6.ip6_null_entry &&
  	    ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
  		/* remove prefsrc entry */
@@@ -2165,7 -2148,7 +2165,7 @@@ static int fib6_ifdown(struct rt6_info 
  	const struct arg_dev_net *adn = arg;
  	const struct net_device *dev = adn->dev;
  
 -	if ((rt->rt6i_dev == dev || dev == NULL) &&
 +	if ((rt->rt6i_dev == dev || !dev) &&
  	    rt != adn->net->ipv6.ip6_null_entry) {
  		RT6_TRACE("deleted by ifdown %p\n", rt);
  		return -1;
@@@ -2202,7 -2185,7 +2202,7 @@@ static int rt6_mtu_change_route(struct 
  	*/
  
  	idev = __in6_dev_get(arg->dev);
 -	if (idev == NULL)
 +	if (!idev)
  		return 0;
  
  	/* For administrative MTU increase, there is no way to discover
@@@ -2382,7 -2365,7 +2382,7 @@@ static int rt6_fill_node(struct net *ne
  	}
  
  	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags);
 -	if (nlh == NULL)
 +	if (!nlh)
  		return -EMSGSIZE;
  
  	rtm = nlmsg_data(nlh);
@@@ -2396,25 -2379,25 +2396,25 @@@
  		table = RT6_TABLE_UNSPEC;
  	rtm->rtm_table = table;
  	NLA_PUT_U32(skb, RTA_TABLE, table);
 -	if (rt->rt6i_flags&RTF_REJECT)
 +	if (rt->rt6i_flags & RTF_REJECT)
  		rtm->rtm_type = RTN_UNREACHABLE;
 -	else if (rt->rt6i_flags&RTF_LOCAL)
 +	else if (rt->rt6i_flags & RTF_LOCAL)
  		rtm->rtm_type = RTN_LOCAL;
 -	else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))
 +	else if (rt->rt6i_dev && (rt->rt6i_dev->flags & IFF_LOOPBACK))
  		rtm->rtm_type = RTN_LOCAL;
  	else
  		rtm->rtm_type = RTN_UNICAST;
  	rtm->rtm_flags = 0;
  	rtm->rtm_scope = RT_SCOPE_UNIVERSE;
  	rtm->rtm_protocol = rt->rt6i_protocol;
 -	if (rt->rt6i_flags&RTF_DYNAMIC)
 +	if (rt->rt6i_flags & RTF_DYNAMIC)
  		rtm->rtm_protocol = RTPROT_REDIRECT;
  	else if (rt->rt6i_flags & RTF_ADDRCONF)
  		rtm->rtm_protocol = RTPROT_KERNEL;
 -	else if (rt->rt6i_flags&RTF_DEFAULT)
 +	else if (rt->rt6i_flags & RTF_DEFAULT)
  		rtm->rtm_protocol = RTPROT_RA;
  
 -	if (rt->rt6i_flags&RTF_CACHE)
 +	if (rt->rt6i_flags & RTF_CACHE)
  		rtm->rtm_flags |= RTM_F_CLONED;
  
  	if (dst) {
@@@ -2454,7 -2437,7 +2454,7 @@@
  
  	if (rt->rt6i_prefsrc.plen) {
  		struct in6_addr saddr_buf;
 -		ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
 +		saddr_buf = rt->rt6i_prefsrc.addr;
  		NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
  	}
  
@@@ -2462,7 -2445,7 +2462,7 @@@
  		goto nla_put_failure;
  
  	rcu_read_lock();
 -	n = dst_get_neighbour(&rt->dst);
 +	n = dst_get_neighbour_noref(&rt->dst);
  	if (n)
  		NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key);
  	rcu_read_unlock();
@@@ -2528,14 -2511,14 +2528,14 @@@ static int inet6_rtm_getroute(struct sk
  		if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
  			goto errout;
  
 -		ipv6_addr_copy(&fl6.saddr, nla_data(tb[RTA_SRC]));
 +		fl6.saddr = *(struct in6_addr *)nla_data(tb[RTA_SRC]);
  	}
  
  	if (tb[RTA_DST]) {
  		if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
  			goto errout;
  
 -		ipv6_addr_copy(&fl6.daddr, nla_data(tb[RTA_DST]));
 +		fl6.daddr = *(struct in6_addr *)nla_data(tb[RTA_DST]);
  	}
  
  	if (tb[RTA_IIF])
@@@ -2554,7 -2537,7 +2554,7 @@@
  	}
  
  	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 -	if (skb == NULL) {
 +	if (!skb) {
  		err = -ENOBUFS;
  		goto errout;
  	}
@@@ -2589,10 -2572,10 +2589,10 @@@ void inet6_rt_notify(int event, struct 
  	int err;
  
  	err = -ENOBUFS;
 -	seq = info->nlh != NULL ? info->nlh->nlmsg_seq : 0;
 +	seq = info->nlh ? info->nlh->nlmsg_seq : 0;
  
  	skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
 -	if (skb == NULL)
 +	if (!skb)
  		goto errout;
  
  	err = rt6_fill_node(net, skb, rt, NULL, NULL, 0,
@@@ -2659,7 -2642,7 +2659,7 @@@ static int rt6_info_route(struct rt6_in
  	seq_puts(m, "00000000000000000000000000000000 00 ");
  #endif
  	rcu_read_lock();
 -	n = dst_get_neighbour(&rt->dst);
 +	n = dst_get_neighbour_noref(&rt->dst);
  	if (n) {
  		seq_printf(m, "%pi6", n->primary_key);
  	} else {
diff --combined net/ipv6/sit.c
index b7d14cc,96f3623..3b6dac9
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@@ -91,7 -91,7 +91,7 @@@ struct pcpu_tstats 
  	unsigned long	rx_bytes;
  	unsigned long	tx_packets;
  	unsigned long	tx_bytes;
 -};
 +} __attribute__((aligned(4*sizeof(unsigned long))));
  
  static struct net_device_stats *ipip6_get_stats(struct net_device *dev)
  {
@@@ -263,6 -263,8 +263,8 @@@ static struct ip_tunnel *ipip6_tunnel_l
  	if (register_netdevice(dev) < 0)
  		goto failed_free;
  
+ 	strcpy(nt->parms.name, dev->name);
+ 
  	dev_hold(dev);
  
  	ipip6_tunnel_link(sitn, nt);
@@@ -680,7 -682,7 +682,7 @@@ static netdev_tx_t ipip6_tunnel_xmit(st
  		struct neighbour *neigh = NULL;
  
  		if (skb_dst(skb))
 -			neigh = dst_get_neighbour(skb_dst(skb));
 +			neigh = dst_get_neighbour_noref(skb_dst(skb));
  
  		if (neigh == NULL) {
  			if (net_ratelimit())
@@@ -705,7 -707,7 +707,7 @@@
  		struct neighbour *neigh = NULL;
  
  		if (skb_dst(skb))
 -			neigh = dst_get_neighbour(skb_dst(skb));
 +			neigh = dst_get_neighbour_noref(skb_dst(skb));
  
  		if (neigh == NULL) {
  			if (net_ratelimit())
@@@ -914,7 -916,7 +916,7 @@@ ipip6_tunnel_ioctl (struct net_device *
  				goto done;
  #ifdef CONFIG_IPV6_SIT_6RD
  		} else {
 -			ipv6_addr_copy(&ip6rd.prefix, &t->ip6rd.prefix);
 +			ip6rd.prefix = t->ip6rd.prefix;
  			ip6rd.relay_prefix = t->ip6rd.relay_prefix;
  			ip6rd.prefixlen = t->ip6rd.prefixlen;
  			ip6rd.relay_prefixlen = t->ip6rd.relay_prefixlen;
@@@ -1082,7 -1084,7 +1084,7 @@@
  			if (relay_prefix != ip6rd.relay_prefix)
  				goto done;
  
 -			ipv6_addr_copy(&t->ip6rd.prefix, &prefix);
 +			t->ip6rd.prefix = prefix;
  			t->ip6rd.relay_prefix = relay_prefix;
  			t->ip6rd.prefixlen = ip6rd.prefixlen;
  			t->ip6rd.relay_prefixlen = ip6rd.relay_prefixlen;
@@@ -1144,7 -1146,6 +1146,6 @@@ static int ipip6_tunnel_init(struct net
  	struct ip_tunnel *tunnel = netdev_priv(dev);
  
  	tunnel->dev = dev;
- 	strcpy(tunnel->parms.name, dev->name);
  
  	memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
  	memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
@@@ -1207,6 -1208,7 +1208,7 @@@ static void __net_exit sit_destroy_tunn
  static int __net_init sit_init_net(struct net *net)
  {
  	struct sit_net *sitn = net_generic(net, sit_net_id);
+ 	struct ip_tunnel *t;
  	int err;
  
  	sitn->tunnels[0] = sitn->tunnels_wc;
@@@ -1231,6 -1233,9 +1233,9 @@@
  	if ((err = register_netdev(sitn->fb_tunnel_dev)))
  		goto err_reg_dev;
  
+ 	t = netdev_priv(sitn->fb_tunnel_dev);
+ 
+ 	strcpy(t->parms.name, sitn->fb_tunnel_dev->name);
  	return 0;
  
  err_reg_dev:
diff --combined net/mac80211/agg-tx.c
index c45fa5d,2e4b961..7380287
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@@ -78,13 -78,10 +78,13 @@@ static void ieee80211_send_addba_reques
  	memcpy(mgmt->da, da, ETH_ALEN);
  	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
  	if (sdata->vif.type == NL80211_IFTYPE_AP ||
 -	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 +	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
 +	    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
  		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
  	else if (sdata->vif.type == NL80211_IFTYPE_STATION)
  		memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
 +	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 +		memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
  
  	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
  					  IEEE80211_STYPE_ACTION);
@@@ -188,7 -185,6 +188,7 @@@ int ___ieee80211_stop_tx_ba_session(str
  #endif /* CONFIG_MAC80211_HT_DEBUG */
  
  	del_timer_sync(&tid_tx->addba_resp_timer);
 +	del_timer_sync(&tid_tx->session_timer);
  
  	/*
  	 * After this packets are no longer handed right through
@@@ -307,6 -303,38 +307,38 @@@ ieee80211_wake_queue_agg(struct ieee802
  	__release(agg_queue);
  }
  
+ /*
+  * splice packets from the STA's pending to the local pending,
+  * requires a call to ieee80211_agg_splice_finish later
+  */
+ static void __acquires(agg_queue)
+ ieee80211_agg_splice_packets(struct ieee80211_local *local,
+ 			     struct tid_ampdu_tx *tid_tx, u16 tid)
+ {
+ 	int queue = ieee80211_ac_from_tid(tid);
+ 	unsigned long flags;
+ 
+ 	ieee80211_stop_queue_agg(local, tid);
+ 
+ 	if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
+ 			  " from the pending queue\n", tid))
+ 		return;
+ 
+ 	if (!skb_queue_empty(&tid_tx->pending)) {
+ 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ 		/* copy over remaining packets */
+ 		skb_queue_splice_tail_init(&tid_tx->pending,
+ 					   &local->pending[queue]);
+ 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ 	}
+ }
+ 
+ static void __releases(agg_queue)
+ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
+ {
+ 	ieee80211_wake_queue_agg(local, tid);
+ }
+ 
  void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
  {
  	struct tid_ampdu_tx *tid_tx;
@@@ -318,19 -346,17 +350,17 @@@
  	tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
  
  	/*
- 	 * While we're asking the driver about the aggregation,
- 	 * stop the AC queue so that we don't have to worry
- 	 * about frames that came in while we were doing that,
- 	 * which would require us to put them to the AC pending
- 	 * afterwards which just makes the code more complex.
+ 	 * Start queuing up packets for this aggregation session.
+ 	 * We're going to release them once the driver is OK with
+ 	 * that.
  	 */
  	clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
  
  	/*
- 	 * make sure no packets are being processed to get
- 	 * valid starting sequence number
+ 	 * Make sure no packets are being processed. This ensures that
+ 	 * we have a valid starting sequence number and that in-flight
+ 	 * packets have been flushed out and no packets for this TID
+ 	 * will go into the driver during the ampdu_action call.
  	 */
  	synchronize_net();
  
@@@ -344,17 -370,15 +374,15 @@@
  					" tid %d\n", tid);
  #endif
  		spin_lock_bh(&sta->lock);
+ 		ieee80211_agg_splice_packets(local, tid_tx, tid);
  		ieee80211_assign_tid_tx(sta, tid, NULL);
+ 		ieee80211_agg_splice_finish(local, tid);
  		spin_unlock_bh(&sta->lock);
  
- 		ieee80211_wake_queue_agg(local, tid);
  		kfree_rcu(tid_tx, rcu_head);
  		return;
  	}
  
- 	/* we can take packets again now */
- 	ieee80211_wake_queue_agg(local, tid);
- 
  	/* activate the timer for the recipient's addBA response */
  	mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
  #ifdef CONFIG_MAC80211_HT_DEBUG
@@@ -372,28 -396,6 +400,28 @@@
  				     tid_tx->timeout);
  }
  
 +/*
 + * After accepting the AddBA Response we activated a timer,
 + * resetting it after each frame that we send.
 + */
 +static void sta_tx_agg_session_timer_expired(unsigned long data)
 +{
 +	/* not an elegant detour, but there is no choice as the timer passes
 +	 * only one argument, and various sta_info are needed here, so init
 +	 * flow in sta_info_create gives the TID as data, while the timer_to_id
 +	 * array gives the sta through container_of */
 +	u8 *ptid = (u8 *)data;
 +	u8 *timer_to_id = ptid - *ptid;
 +	struct sta_info *sta = container_of(timer_to_id, struct sta_info,
 +					 timer_to_tid[0]);
 +
 +#ifdef CONFIG_MAC80211_HT_DEBUG
 +	printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid);
 +#endif
 +
 +	ieee80211_stop_tx_ba_session(&sta->sta, *ptid);
 +}
 +
  int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
  				  u16 timeout)
  {
@@@ -418,11 -420,15 +446,11 @@@
  	       pubsta->addr, tid);
  #endif /* CONFIG_MAC80211_HT_DEBUG */
  
 -	/*
 -	 * The aggregation code is not prepared to handle
 -	 * anything but STA/AP due to the BSSID handling.
 -	 * IBSS could work in the code but isn't supported
 -	 * by drivers or the standard.
 -	 */
  	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
 +	    sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
  	    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 -	    sdata->vif.type != NL80211_IFTYPE_AP)
 +	    sdata->vif.type != NL80211_IFTYPE_AP &&
 +	    sdata->vif.type != NL80211_IFTYPE_ADHOC)
  		return -EINVAL;
  
  	if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
@@@ -433,27 -439,6 +461,27 @@@
  		return -EINVAL;
  	}
  
 +	/*
 +	 * 802.11n-2009 11.5.1.1: If the initiating STA is an HT STA, is a
 +	 * member of an IBSS, and has no other existing Block Ack agreement
 +	 * with the recipient STA, then the initiating STA shall transmit a
 +	 * Probe Request frame to the recipient STA and shall not transmit an
 +	 * ADDBA Request frame unless it receives a Probe Response frame
 +	 * from the recipient within dot11ADDBAFailureTimeout.
 +	 *
 +	 * The probe request mechanism for ADDBA is currently not implemented,
 +	 * but we only build up Block Ack session with HT STAs. This information
 +	 * is set when we receive a bss info from a probe response or a beacon.
 +	 */
 +	if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC &&
 +	    !sta->sta.ht_cap.ht_supported) {
 +#ifdef CONFIG_MAC80211_HT_DEBUG
 +		printk(KERN_DEBUG "BA request denied - IBSS STA %pM"
 +		       "does not advertise HT support\n", pubsta->addr);
 +#endif /* CONFIG_MAC80211_HT_DEBUG */
 +		return -EINVAL;
 +	}
 +
  	spin_lock_bh(&sta->lock);
  
  	/* we have tried too many times, receiver does not want A-MPDU */
@@@ -485,16 -470,11 +513,16 @@@
  
  	tid_tx->timeout = timeout;
  
 -	/* Tx timer */
 +	/* response timer */
  	tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired;
  	tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid];
  	init_timer(&tid_tx->addba_resp_timer);
  
 +	/* tx timer */
 +	tid_tx->session_timer.function = sta_tx_agg_session_timer_expired;
 +	tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid];
 +	init_timer(&tid_tx->session_timer);
 +
  	/* assign a dialog token */
  	sta->ampdu_mlme.dialog_token_allocator++;
  	tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator;
@@@ -514,38 -494,6 +542,6 @@@
  }
  EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
  
- /*
-  * splice packets from the STA's pending to the local pending,
-  * requires a call to ieee80211_agg_splice_finish later
-  */
- static void __acquires(agg_queue)
- ieee80211_agg_splice_packets(struct ieee80211_local *local,
- 			     struct tid_ampdu_tx *tid_tx, u16 tid)
- {
- 	int queue = ieee80211_ac_from_tid(tid);
- 	unsigned long flags;
- 
- 	ieee80211_stop_queue_agg(local, tid);
- 
- 	if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
- 			  " from the pending queue\n", tid))
- 		return;
- 
- 	if (!skb_queue_empty(&tid_tx->pending)) {
- 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- 		/* copy over remaining packets */
- 		skb_queue_splice_tail_init(&tid_tx->pending,
- 					   &local->pending[queue]);
- 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
- 	}
- }
- 
- static void __releases(agg_queue)
- ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
- {
- 	ieee80211_wake_queue_agg(local, tid);
- }
- 
  static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
  					 struct sta_info *sta, u16 tid)
  {
@@@ -599,7 -547,7 +595,7 @@@ void ieee80211_start_tx_ba_cb(struct ie
  	}
  
  	mutex_lock(&local->sta_mtx);
 -	sta = sta_info_get(sdata, ra);
 +	sta = sta_info_get_bss(sdata, ra);
  	if (!sta) {
  		mutex_unlock(&local->sta_mtx);
  #ifdef CONFIG_MAC80211_HT_DEBUG
@@@ -728,7 -676,7 +724,7 @@@ void ieee80211_stop_tx_ba_cb(struct iee
  
  	mutex_lock(&local->sta_mtx);
  
 -	sta = sta_info_get(sdata, ra);
 +	sta = sta_info_get_bss(sdata, ra);
  	if (!sta) {
  #ifdef CONFIG_MAC80211_HT_DEBUG
  		printk(KERN_DEBUG "Could not find station: %pM\n", ra);
@@@ -866,11 -814,6 +862,11 @@@ void ieee80211_process_addba_resp(struc
  			ieee80211_agg_tx_operational(local, sta, tid);
  
  		sta->ampdu_mlme.addba_req_num[tid] = 0;
 +
 +		if (tid_tx->timeout)
 +			mod_timer(&tid_tx->session_timer,
 +				  TU_TO_EXP_TIME(tid_tx->timeout));
 +
  	} else {
  		___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
  						true);
diff --combined net/sched/sch_gred.c
index a1b7407,6cd8ddf..1b5e631
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@@ -34,7 -34,7 +34,7 @@@ struct gred_sched
  
  struct gred_sched_data {
  	u32		limit;		/* HARD maximal queue length	*/
 -	u32      	DP;		/* the drop pramaters */
 +	u32		DP;		/* the drop parameters */
  	u32		bytesin;	/* bytes seen on virtualQ so far*/
  	u32		packetsin;	/* packets seen on virtualQ so far*/
  	u32		backlog;	/* bytes on the virtualQ */
@@@ -379,14 -379,13 +379,14 @@@ static inline int gred_change_table_def
  }
  
  static inline int gred_change_vq(struct Qdisc *sch, int dp,
 -				 struct tc_gred_qopt *ctl, int prio, u8 *stab)
 +				 struct tc_gred_qopt *ctl, int prio,
 +				 u8 *stab, u32 max_P)
  {
  	struct gred_sched *table = qdisc_priv(sch);
  	struct gred_sched_data *q;
  
  	if (table->tab[dp] == NULL) {
- 		table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL);
+ 		table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC);
  		if (table->tab[dp] == NULL)
  			return -ENOMEM;
  	}
@@@ -401,7 -400,7 +401,7 @@@
  
  	red_set_parms(&q->parms,
  		      ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog,
 -		      ctl->Scell_log, stab);
 +		      ctl->Scell_log, stab, max_P);
  
  	return 0;
  }
@@@ -410,7 -409,6 +410,7 @@@ static const struct nla_policy gred_pol
  	[TCA_GRED_PARMS]	= { .len = sizeof(struct tc_gred_qopt) },
  	[TCA_GRED_STAB]		= { .len = 256 },
  	[TCA_GRED_DPS]		= { .len = sizeof(struct tc_gred_sopt) },
 +	[TCA_GRED_MAX_P]	= { .type = NLA_U32 },
  };
  
  static int gred_change(struct Qdisc *sch, struct nlattr *opt)
@@@ -420,7 -418,6 +420,7 @@@
  	struct nlattr *tb[TCA_GRED_MAX + 1];
  	int err, prio = GRED_DEF_PRIO;
  	u8 *stab;
 +	u32 max_P;
  
  	if (opt == NULL)
  		return -EINVAL;
@@@ -436,8 -433,6 +436,8 @@@
  	    tb[TCA_GRED_STAB] == NULL)
  		return -EINVAL;
  
 +	max_P = tb[TCA_GRED_MAX_P] ? nla_get_u32(tb[TCA_GRED_MAX_P]) : 0;
 +
  	err = -EINVAL;
  	ctl = nla_data(tb[TCA_GRED_PARMS]);
  	stab = nla_data(tb[TCA_GRED_STAB]);
@@@ -462,7 -457,7 +462,7 @@@
  
  	sch_tree_lock(sch);
  
 -	err = gred_change_vq(sch, ctl->DP, ctl, prio, stab);
 +	err = gred_change_vq(sch, ctl->DP, ctl, prio, stab, max_P);
  	if (err < 0)
  		goto errout_locked;
  
@@@ -503,7 -498,6 +503,7 @@@ static int gred_dump(struct Qdisc *sch
  	struct gred_sched *table = qdisc_priv(sch);
  	struct nlattr *parms, *opts = NULL;
  	int i;
 +	u32 max_p[MAX_DPs];
  	struct tc_gred_sopt sopt = {
  		.DPs	= table->DPs,
  		.def_DP	= table->def,
@@@ -515,14 -509,6 +515,14 @@@
  	if (opts == NULL)
  		goto nla_put_failure;
  	NLA_PUT(skb, TCA_GRED_DPS, sizeof(sopt), &sopt);
 +
 +	for (i = 0; i < MAX_DPs; i++) {
 +		struct gred_sched_data *q = table->tab[i];
 +
 +		max_p[i] = q ? q->parms.max_P : 0;
 +	}
 +	NLA_PUT(skb, TCA_GRED_MAX_P, sizeof(max_p), max_p);
 +
  	parms = nla_nest_start(skb, TCA_GRED_PARMS);
  	if (parms == NULL)
  		goto nla_put_failure;

-- 
LinuxNextTracking


More information about the linux-merge mailing list