The following commit has been merged in the master branch:
commit b26e478f8fd5b575684f021b05a5c6236ebb911a
Merge: bcebcc468a6bcd3820fe9ad36b34220563efc93a bb3c36863e8001fc21a88bebfdead4da4c23e848
Author: David S. Miller <davem(a)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