From 00af5c69598212cf6cd4ecb4ca89785118aeecad Mon Sep 17 00:00:00 2001 From: roel kluin Date: Wed, 29 Oct 2008 15:55:53 -0400 Subject: [PATCH 01/33] cipso: unsigned buf_len cannot be negative unsigned buf_len cannot be negative Signed-off-by: Roel Kluin Signed-off-by: Paul Moore --- net/ipv4/cipso_ipv4.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 490e035c6d90..2e78f6bd9775 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -2063,9 +2063,10 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb, u32 opt_len; int len_delta; - buf_len = cipso_v4_genopt(buf, buf_len, doi_def, secattr); - if (buf_len < 0) - return buf_len; + ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr); + if (ret_val < 0) + return ret_val; + buf_len = ret_val; opt_len = (buf_len + 3) & ~3; /* we overwrite any existing options to ensure that we have enough From f8a024796b2bbec3d1a4ad5aae6173cfb18226b4 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 29 Oct 2008 16:09:12 -0400 Subject: [PATCH 02/33] netlabel: Fix compiler warnings in netlabel_mgmt.c Fix the compiler warnings below, thanks to Andrew Morton for finding them. net/netlabel/netlabel_mgmt.c: In function `netlbl_mgmt_listentry': net/netlabel/netlabel_mgmt.c:268: warning: 'ret_val' might be used uninitialized in this function Signed-off-by: Paul Moore --- net/netlabel/netlabel_mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index ee769ecaa13c..0a0ef17b2a40 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -265,7 +265,7 @@ add_failure: static int netlbl_mgmt_listentry(struct sk_buff *skb, struct netlbl_dom_map *entry) { - int ret_val; + int ret_val = 0; struct nlattr *nla_a; struct nlattr *nla_b; struct netlbl_af4list *iter4; From 10d0bd56966571d0324dfd9bbb8aa913a60bef5f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 29 Oct 2008 01:03:01 +0200 Subject: [PATCH 03/33] iwlwifi: fix suspend to RAM in iwlwifi This patch fixes suspend to RAM after by moving notify_mac out of iwlwifi mutex http://bugzilla.kernel.org/show_bug.cgi?id=11845 Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Tested-by: Carlos R. Mafra Tested-by: Christian Borntraeger Cc: Rafael J. Wysocki Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 24a1aeb6448f..321dbc8c034a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2090,7 +2090,6 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl4965_error_recovery(priv); iwl_power_update_mode(priv, 1); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) iwl4965_set_mode(priv, priv->iw_mode); @@ -2342,6 +2341,7 @@ static void iwl_bg_alive_start(struct work_struct *data) mutex_lock(&priv->mutex); iwl_alive_start(priv); mutex_unlock(&priv->mutex); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl4965_bg_rf_kill(struct work_struct *work) From 87bf24f3d2e076468deaa5181d44184887072904 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 29 Oct 2008 10:35:02 +0100 Subject: [PATCH 04/33] libertas: remove two libertas sparse warning Johannes Berg detected this two sparse warnings: drivers/net/wireless/libertas/cmd.c:609:16: warning: cast to restricted __le16 drivers/net/wireless/libertas/cmd.c:611:16: warning: cast to restricted __le16 ... but cmd.minlevel is "s8", so we can access it directly and hope for the sign-extension-code in the compiler to convert that to the "s16" type. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 297696de2da0..8265c7d25edc 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -605,9 +605,9 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, if (ret == 0) { *curlevel = le16_to_cpu(cmd.curlevel); if (minlevel) - *minlevel = le16_to_cpu(cmd.minlevel); + *minlevel = cmd.minlevel; if (maxlevel) - *maxlevel = le16_to_cpu(cmd.maxlevel); + *maxlevel = cmd.maxlevel; } lbs_deb_leave(LBS_DEB_CMD); From 48735d8d8bd701b1e0cd3d49c21e5e385ddcb077 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 29 Oct 2008 11:43:32 +0100 Subject: [PATCH 05/33] libertas: fix buffer overrun If somebody sends an invalid beacon/probe response, that can trash the whole BSS descriptor. The descriptor is, luckily, large enough so that it cannot scribble past the end of it; it's well above 400 bytes long. Signed-off-by: Johannes Berg Cc: stable@kernel.org [2.6.24-2.6.27, bug present in some form since driver was added (2.6.22)] Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 8f66903641b9..22c4c6110521 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -598,8 +598,8 @@ static int lbs_process_bss(struct bss_descriptor *bss, switch (elem->id) { case MFIE_TYPE_SSID: - bss->ssid_len = elem->len; - memcpy(bss->ssid, elem->data, elem->len); + bss->ssid_len = min_t(int, 32, elem->len); + memcpy(bss->ssid, elem->data, bss->ssid_len); lbs_deb_scan("got SSID IE: '%s', len %u\n", escape_essid(bss->ssid, bss->ssid_len), bss->ssid_len); From 85519a65fd1100ceede7318a89f77a219c69c6ac Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 29 Oct 2008 08:30:53 -0400 Subject: [PATCH 06/33] ath5k: correct misspelling in debug help Change "mamagement" to "management" Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 8f92d670f614..19980cbd5d5f 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -339,7 +339,7 @@ static struct { { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, - { ATH5K_DEBUG_LED, "led", "LED mamagement" }, + { ATH5K_DEBUG_LED, "led", "LED management" }, { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, From 5dc5340cfc00097e79d9d787567d311e898aaa84 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 29 Oct 2008 17:19:08 +0100 Subject: [PATCH 07/33] rt2x00: Fix build error when mac80211=M rt2x00=Y Make menuconfig RT2X00 a tristate instead of boolean, otherwise we do not correctly inherit the mac80211 value on which RT2X00 depends, and makes it possible to compile rt2x00 into the kernel while mac80211 is a module. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index f839ce044afd..95511ac22470 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -1,5 +1,5 @@ menuconfig RT2X00 - bool "Ralink driver support" + tristate "Ralink driver support" depends on MAC80211 && WLAN_80211 && EXPERIMENTAL ---help--- This will enable the experimental support for the Ralink drivers, From 7d19267b8d1e12c0baebf9be96e04cddffe63f67 Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Wed, 29 Oct 2008 14:25:42 +0100 Subject: [PATCH 08/33] ath5k: Fix reset sequence for AR5212 in general and RF5111 in particular Take care to handle register 0xa228 exactly as in the HAL released by Atheros. This change is required to make ath5k work again on my system since commit 2203d6be (ath5k: Misc hw_reset updates), thus fixing a regression in 2.6.27 and therefore hopefully eligible for inclusion into a stable release. v2: Only overwrite initial register values on later revisions of AR5212 chips. v3: Use standard macros to manipulate the register. Signed-off-by: Elias Oltmanns Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/initvals.c | 2 ++ drivers/net/wireless/ath5k/reset.c | 20 ++++++-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index ea2e1a20b499..ceaa6c475c06 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -806,6 +806,8 @@ static const struct ath5k_ini_mode ar5212_rf5111_ini_mode_end[] = { { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY(642), { 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xa228, + { 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5 } }, { 0xa23c, { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } }, }; diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 8f1886834e61..1b6d45b6772d 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -537,9 +537,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, mdelay(1); /* - * Write some more initial register settings + * Write some more initial register settings for revised chips */ - if (ah->ah_version == AR5K_AR5212) { + if (ah->ah_version == AR5K_AR5212 && + ah->ah_phy_revision > 0x41) { ath5k_hw_reg_write(ah, 0x0002a002, 0x982c); if (channel->hw_value == CHANNEL_G) @@ -558,19 +559,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, else ath5k_hw_reg_write(ah, 0x00000000, 0x994c); - /* Some bits are disabled here, we know nothing about - * register 0xa228 yet, most of the times this ends up - * with a value 0x9b5 -haven't seen any dump with - * a different value- */ - /* Got this from decompiling binary HAL */ - data = ath5k_hw_reg_read(ah, 0xa228); - data &= 0xfffffdff; - ath5k_hw_reg_write(ah, data, 0xa228); + /* Got this from legacy-hal */ + AR5K_REG_DISABLE_BITS(ah, 0xa228, 0x200); - data = ath5k_hw_reg_read(ah, 0xa228); - data &= 0xfffe03ff; - ath5k_hw_reg_write(ah, data, 0xa228); - data = 0; + AR5K_REG_MASKED_BITS(ah, 0xa228, 0x800, 0xfffe03ff); /* Just write 0x9b5 ? */ /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */ From 063279062a8c530cc90fb77797db16c49c905b26 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 29 Oct 2008 08:30:56 -0400 Subject: [PATCH 09/33] ath5k: honor FIF_BCN_PRBRESP_PROMISC in STA mode We were setting RX_FILTER_BEACON even after entering STA mode, which leads to a lot of unnecessary wakeups. This should fix the bug "Ath5k driver has too many interrupts per second at idle" at http://bugzilla.kernel.org/show_bug.cgi?id=11749. Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index cfd4d052d666..9e47d727e220 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2942,10 +2942,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, sc->opmode != NL80211_IFTYPE_MESH_POINT && test_bit(ATH_STAT_PROMISC, sc->status)) rfilt |= AR5K_RX_FILTER_PROM; - if (sc->opmode == NL80211_IFTYPE_STATION || - sc->opmode == NL80211_IFTYPE_ADHOC) { + if (sc->opmode == NL80211_IFTYPE_ADHOC) rfilt |= AR5K_RX_FILTER_BEACON; - } /* Set filters */ ath5k_hw_set_rx_filter(ah,rfilt); From adef199c61a224703dfa95c69d360c793ab2ea97 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 29 Oct 2008 08:30:57 -0400 Subject: [PATCH 10/33] ath5k: add self to MAINTAINERS I might as well be on the official list for ath5k. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 16202c8ac68f..185b84a51036 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -738,6 +738,8 @@ P: Nick Kossifidis M: mickflemm@gmail.com P: Luis R. Rodriguez M: mcgrof@gmail.com +P: Bob Copeland +M: me@bobcopeland.com L: linux-wireless@vger.kernel.org L: ath5k-devel@lists.ath5k.org S: Maintained From 47b676c0e03dcfd88de91f6f24a06653cfdf32af Mon Sep 17 00:00:00 2001 From: Manish Katiyar Date: Thu, 30 Oct 2008 10:44:48 -0400 Subject: [PATCH 11/33] netlabel: Fix compilation warnings in net/netlabel/netlabel_addrlist.c Enable netlabel auditing functions only when CONFIG_AUDIT is set Signed-off-by: Manish Katiyar Signed-off-by: Paul Moore --- net/netlabel/netlabel_addrlist.c | 2 ++ net/netlabel/netlabel_addrlist.h | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/net/netlabel/netlabel_addrlist.c b/net/netlabel/netlabel_addrlist.c index b0925a303353..249f6b92f153 100644 --- a/net/netlabel/netlabel_addrlist.c +++ b/net/netlabel/netlabel_addrlist.c @@ -315,6 +315,7 @@ struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, * Audit Helper Functions */ +#ifdef CONFIG_AUDIT /** * netlbl_af4list_audit_addr - Audit an IPv4 address * @audit_buf: audit buffer @@ -386,3 +387,4 @@ void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, } } #endif /* IPv6 */ +#endif /* CONFIG_AUDIT */ diff --git a/net/netlabel/netlabel_addrlist.h b/net/netlabel/netlabel_addrlist.h index 0242bead405f..07ae7fd82be1 100644 --- a/net/netlabel/netlabel_addrlist.h +++ b/net/netlabel/netlabel_addrlist.h @@ -120,9 +120,19 @@ struct netlbl_af4list *netlbl_af4list_search(__be32 addr, struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr, __be32 mask, struct list_head *head); + +#ifdef CONFIG_AUDIT void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, int src, const char *dev, __be32 addr, __be32 mask); +#else +static inline void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, + int src, const char *dev, + __be32 addr, __be32 mask) +{ + return; +} +#endif #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -179,11 +189,23 @@ struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr, const struct in6_addr *mask, struct list_head *head); + +#ifdef CONFIG_AUDIT void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, int src, const char *dev, const struct in6_addr *addr, const struct in6_addr *mask); +#else +static inline void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, + int src, + const char *dev, + const struct in6_addr *addr, + const struct in6_addr *mask) +{ + return; +} +#endif #endif /* IPV6 */ #endif From fba4acda35f3119328bcba28aacefae14245d2bb Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Thu, 30 Oct 2008 17:41:14 -0700 Subject: [PATCH 12/33] bonding: fix miimon failure counter During the rework of the mii monitor for: commit f0c76d61779b153dbfb955db3f144c62d02173c2 Author: Jay Vosburgh Date: Wed Jul 2 18:21:58 2008 -0700 bonding: refactor mii monitor I left out the increment of the link failure counter. This patch corrects that omission. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 832739f38db4..85de1d04d1ee 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2376,6 +2376,9 @@ static void bond_miimon_commit(struct bonding *bond) continue; case BOND_LINK_DOWN: + if (slave->link_failure_count < UINT_MAX) + slave->link_failure_count++; + slave->link = BOND_LINK_DOWN; if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || From a434e43f3d844192bc23bd7b408bac979c40efe7 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Thu, 30 Oct 2008 17:41:15 -0700 Subject: [PATCH 13/33] bonding: Clean up resource leaks This patch reworks the resource free logic performed at the time a bonding device is released. This (a) closes two resource leaks, one for workqueues and one for multicast lists, and (b) improves commonality of code between the "destroy one" and "destroy all" paths by performing final free activity via destructor instead of explicitly (and differently) in each path. "Sean E. Millichamp" reported the workqueue leak, and included a different patch. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 49 +++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 85de1d04d1ee..a3efba59eee9 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1979,6 +1979,20 @@ void bond_destroy(struct bonding *bond) unregister_netdevice(bond->dev); } +static void bond_destructor(struct net_device *bond_dev) +{ + struct bonding *bond = bond_dev->priv; + + if (bond->wq) + destroy_workqueue(bond->wq); + + netif_addr_lock_bh(bond_dev); + bond_mc_list_destroy(bond); + netif_addr_unlock_bh(bond_dev); + + free_netdev(bond_dev); +} + /* * First release a slave and than destroy the bond if no more slaves iare left. * Must be under rtnl_lock when this function is called. @@ -4553,7 +4567,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) bond_set_mode_ops(bond, bond->params.mode); - bond_dev->destructor = free_netdev; + bond_dev->destructor = bond_destructor; /* Initialize the device options */ bond_dev->tx_queue_len = 0; @@ -4592,20 +4606,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) return 0; } -/* De-initialize device specific data. - * Caller must hold rtnl_lock. - */ -static void bond_deinit(struct net_device *bond_dev) -{ - struct bonding *bond = bond_dev->priv; - - list_del(&bond->bond_list); - -#ifdef CONFIG_PROC_FS - bond_remove_proc_entry(bond); -#endif -} - static void bond_work_cancel_all(struct bonding *bond) { write_lock_bh(&bond->lock); @@ -4627,6 +4627,22 @@ static void bond_work_cancel_all(struct bonding *bond) cancel_delayed_work(&bond->ad_work); } +/* De-initialize device specific data. + * Caller must hold rtnl_lock. + */ +static void bond_deinit(struct net_device *bond_dev) +{ + struct bonding *bond = bond_dev->priv; + + list_del(&bond->bond_list); + + bond_work_cancel_all(bond); + +#ifdef CONFIG_PROC_FS + bond_remove_proc_entry(bond); +#endif +} + /* Unregister and free all bond devices. * Caller must hold rtnl_lock. */ @@ -4638,9 +4654,6 @@ static void bond_free_all(void) struct net_device *bond_dev = bond->dev; bond_work_cancel_all(bond); - netif_addr_lock_bh(bond_dev); - bond_mc_list_destroy(bond); - netif_addr_unlock_bh(bond_dev); /* Release the bonded slaves */ bond_release_all(bond_dev); bond_destroy(bond); From ce39a800ea87c655de49af021c8b20ee323cb40d Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Thu, 30 Oct 2008 17:41:16 -0700 Subject: [PATCH 14/33] bonding: fix panic when taking bond interface down before removing module A panic was discovered with bonding when using mode 5 or 6 and trying to remove the slaves from the bond after the interface was taken down. When calling 'ifconfig bond0 down' the following happens: bond_close() bond_alb_deinitialize() tlb_deinitialize() kfree(bond_info->tx_hashtbl) bond_info->tx_hashtbl = NULL Unfortunately if there are still slaves in the bond, when removing the module the following happens: bonding_exit() bond_free_all() bond_release_all() bond_alb_deinit_slave() tlb_clear_slave() tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl u32 next_index = tx_hash_table[index].next As you might guess we panic when trying to access a few entries into the table that no longer exists. I experimented with several options (like moving the calls to tlb_deinitialize somewhere else), but it really makes the most sense to be part of the bond_close routine. It also didn't seem logical move tlb_clear_slave around too much, so the simplest option seems to add a check in tlb_clear_slave to make sure we haven't already wiped the tx_hashtbl away before searching for all the non-existent hash-table entries that used to point to the slave as the output interface. Signed-off-by: Andy Gospodarek Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_alb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index ade5f3f6693b..87437c788476 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -169,11 +169,14 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_ /* clear slave from tx_hashtbl */ tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl; - index = SLAVE_TLB_INFO(slave).head; - while (index != TLB_NULL_INDEX) { - u32 next_index = tx_hash_table[index].next; - tlb_init_table_entry(&tx_hash_table[index], save_load); - index = next_index; + /* skip this if we've already freed the tx hash table */ + if (tx_hash_table) { + index = SLAVE_TLB_INFO(slave).head; + while (index != TLB_NULL_INDEX) { + u32 next_index = tx_hash_table[index].next; + tlb_init_table_entry(&tx_hash_table[index], save_load); + index = next_index; + } } tlb_init_slave(slave); From 6824a105d4b699e3c08cc3df371de4b0480017b9 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 30 Oct 2008 08:59:33 +0100 Subject: [PATCH 15/33] myri10ge: fix stop/go mmio ordering Use mmiowb() to ensure "stop" and "go" commands are sent in order on ia64. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index b1556b2e404c..a5f428bcc0eb 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.4.3-1.371" +#define MYRI10GE_VERSION_STR "1.4.3-1.375" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -1393,6 +1393,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) if (tx->req == tx->done) { tx->queue_active = 0; put_be32(htonl(1), tx->send_stop); + mmiowb(); } __netif_tx_unlock(dev_queue); } @@ -2864,6 +2865,7 @@ again: if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) { tx->queue_active = 1; put_be32(htonl(1), tx->send_go); + mmiowb(); } tx->pkt_start++; if ((avail - count) < MXGEFW_MAX_SEND_DESC) { From 51ac3beffd4afaea4350526cf01fe74aaff25eff Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 29 Oct 2008 09:56:06 -0400 Subject: [PATCH 16/33] SMC91x: delete unused local variable "lp" Signed-off-by: Mike Frysinger Signed-off-by: Jeff Garzik --- drivers/net/smc91x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index c70870e0fd61..6f9895d4e5bd 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -2060,7 +2060,6 @@ static int smc_request_attrib(struct platform_device *pdev, struct net_device *ndev) { struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib"); - struct smc_local *lp = netdev_priv(ndev); if (!res) return 0; @@ -2075,7 +2074,6 @@ static void smc_release_attrib(struct platform_device *pdev, struct net_device *ndev) { struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib"); - struct smc_local *lp = netdev_priv(ndev); if (res) release_mem_region(res->start, ATTRIB_SIZE); From dc5596d920b504d263c7ca38bd76326179b13dee Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Wed, 29 Oct 2008 11:01:36 -0500 Subject: [PATCH 17/33] atl1: fix vlan tag regression Commit 401c0aabec4b97320f962a0161a846d230a6f7aa introduced a regression in the atl1 driver by storing the VLAN tag in the wrong TX descriptor field. This patch causes the VLAN tag to be stored in its proper location. Tested-by: Ramon Casellas Signed-off-by: Jay Cliburn Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 7 ++++--- drivers/net/atlx/atl1.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 3cf59a7f5a1c..246d92b42636 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2310,7 +2310,8 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count, if (tpd != ptpd) memcpy(tpd, ptpd, sizeof(struct tx_packet_desc)); tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - tpd->word2 = (cpu_to_le16(buffer_info->length) & + tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT); + tpd->word2 |= (cpu_to_le16(buffer_info->length) & TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT; /* @@ -2409,8 +2410,8 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) | ((vlan_tag >> 9) & 0x8); ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT; - ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) << - TPD_VL_TAGGED_SHIFT; + ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) << + TPD_VLANTAG_SHIFT; } tso = atl1_tso(adapter, skb, ptpd); diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h index a5015b14a429..ffa73fc8d95e 100644 --- a/drivers/net/atlx/atl1.h +++ b/drivers/net/atlx/atl1.h @@ -504,7 +504,7 @@ struct rx_free_desc { #define TPD_PKTNT_MASK 0x0001 #define TPD_PKTINT_SHIFT 15 #define TPD_VLANTAG_MASK 0xFFFF -#define TPD_VLAN_SHIFT 16 +#define TPD_VLANTAG_SHIFT 16 /* tpd word 3 bits 0:13 */ #define TPD_EOP_MASK 0x0001 From e83603fd4ace0bc8e2585cf9d450bb1dc80db448 Mon Sep 17 00:00:00 2001 From: Chunbo Luo Date: Tue, 28 Oct 2008 09:51:46 +0800 Subject: [PATCH 18/33] amd8111e: fix dma_free_coherent context Acoording commit aa24886e379d2b641c5117e178b15ce1d5d366ba, dma_free_coherent() need irqs enabled. This patch fix following warning messages: WARNING: at linux/arch/x86/kernel/pci-dma.c:376 dma_free_coherent+0xaa/0xb0() Call Trace: [] warn_on_slowpath+0x5f/0x90 [] ? __kfree_skb+0x3a/0xa0 [] ? discard_slab+0x23/0x40 [] dma_free_coherent+0xaa/0xb0 [] amd8111e_close+0x10f/0x1b0 [] dev_close+0x5e/0xb0 [] dev_change_flags+0xa1/0x1e0 [] ic_close_devs+0x36/0x4e [] ip_auto_config+0x581/0x10f3 [] ? kobject_add+0x69/0x90 [] ? kobject_get+0x1a/0x30 [] ? kobject_uevent+0xb/0x10 [] ? kset_register+0x52/0x60 [] ? kset_create_and_add+0x6b/0xa0 [] ? tcp_ca_find+0x24/0x50 [] ? ip_auto_config+0x0/0x10f3 [] _stext+0x3c/0x150 [] ? register_irq_proc+0xd3/0xf0 [] ? mb_cache_create+0x80/0x1f0 [] kernel_init+0x141/0x1b8 [] ? kernel_init+0x0/0x1b8 [] child_rip+0xa/0x11 [] ? kernel_init+0x0/0x1b8 [] ? kernel_init+0x0/0x1b8 [] ? child_rip+0x0/0x11 Signed-off-by: Chunbo Luo Signed-off-by: Jeff Garzik --- drivers/net/amd8111e.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index ba1be0b3a8c8..07a6697e3635 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -644,10 +644,6 @@ This function frees the transmiter and receiver descriptor rings. */ static void amd8111e_free_ring(struct amd8111e_priv* lp) { - - /* Free transmit and receive skbs */ - amd8111e_free_skbs(lp->amd8111e_net_dev); - /* Free transmit and receive descriptor rings */ if(lp->rx_ring){ pci_free_consistent(lp->pci_dev, @@ -1233,7 +1229,9 @@ static int amd8111e_close(struct net_device * dev) amd8111e_disable_interrupt(lp); amd8111e_stop_chip(lp); - amd8111e_free_ring(lp); + + /* Free transmit and receive skbs */ + amd8111e_free_skbs(lp->amd8111e_net_dev); netif_carrier_off(lp->amd8111e_net_dev); @@ -1243,6 +1241,7 @@ static int amd8111e_close(struct net_device * dev) spin_unlock_irq(&lp->lock); free_irq(dev->irq, dev); + amd8111e_free_ring(lp); /* Update the statistics before closing */ amd8111e_get_stats(dev); From 71527ef484426f2a4fb868da379b46f4408e80d6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 27 Oct 2008 14:11:34 -0700 Subject: [PATCH 19/33] at91_ether: request/free GPIO for PHY interrupt When the at91_ether driver is using a GPIO for its PHY interrupt, be sure to request (and later, if needed, free) that GPIO. Signed-off-by: David Brownell Signed-off-by: Jeff Garzik --- drivers/net/arm/at91_ether.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 0fa53464efb2..6f431a887e7e 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -1080,7 +1080,8 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add init_timer(&lp->check_timer); lp->check_timer.data = (unsigned long)dev; lp->check_timer.function = at91ether_check_link; - } + } else if (lp->board_data.phy_irq_pin >= 32) + gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy"); /* Display ethernet banner */ printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%s)\n", @@ -1167,6 +1168,9 @@ static int __devexit at91ether_remove(struct platform_device *pdev) struct net_device *dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(dev); + if (lp->board_data.phy_irq_pin >= 32) + gpio_free(lp->board_data.phy_irq_pin); + unregister_netdev(dev); free_irq(dev->irq, dev); dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); From c132419e560a2ecd3c8cf77f9c37e103e74b3754 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 30 Oct 2008 18:17:06 -0700 Subject: [PATCH 20/33] gianfar: Fix race in TBI/SerDes configuration The init_phy() function attaches to the PHY, then configures the SerDes<->TBI link (in SGMII mode). The TBI is on the MDIO bus with the PHY (sort of) and is accessed via the gianfar's MDIO registers, using the functions gfar_local_mdio_read/write(), which don't do any locking. The previously attached PHY will start a work-queue on a timer, and probably an irq handler as well, which will talk to the PHY and thus use the MDIO bus. This uses phy_read/write(), which have locking, but not against the gfar_local_mdio versions. The result is that PHY code will try to use the MDIO bus at the same time as the SerDes setup code, corrupting the transfers. Setting up the SerDes before attaching to the PHY will insure that there is no race between the SerDes code and *our* PHY, but doesn't fix everything. Typically the PHYs for all gianfar devices are on the same MDIO bus, which is associated with the first gianfar device. This means that the first gianfar's SerDes code could corrupt the MDIO transfers for a different gianfar's PHY. The lock used by phy_read/write() is contained in the mii_bus structure, which is pointed to by the PHY. This is difficult to access from the gianfar drivers, as there is no link between a gianfar device and the mii_bus which shares the same MDIO registers. As far as the device layer and drivers are concerned they are two unrelated devices (which happen to share registers). Generally all gianfar devices' PHYs will be on the bus associated with the first gianfar. But this might not be the case, so simply locking the gianfar's PHY's mii bus might not lock the mii bus that the SerDes setup code is going to use. We solve this by having the code that creates the gianfar platform device look in the device tree for an mdio device that shares the gianfar's registers. If one is found the ID of its platform device is saved in the gianfar's platform data. A new function in the gianfar mii code, gfar_get_miibus(), can use the bus ID to search through the platform devices for a gianfar_mdio device with the right ID. The platform device's driver data is the mii_bus structure, which the SerDes setup code can use to lock the current bus. Signed-off-by: Trent Piepho CC: Andy Fleming Signed-off-by: Jeff Garzik --- arch/powerpc/sysdev/fsl_soc.c | 26 ++++++++++++++++++++++++++ drivers/net/gianfar.c | 7 +++++++ drivers/net/gianfar_mii.c | 21 +++++++++++++++++++++ drivers/net/gianfar_mii.h | 3 +++ include/linux/fsl_devices.h | 3 ++- 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 01b884b25696..26ecb96f9731 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -223,6 +223,8 @@ static int gfar_mdio_of_init_one(struct device_node *np) if (ret) return ret; + /* The gianfar device will try to use the same ID created below to find + * this bus, to coordinate register access (since they share). */ mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start&0xfffff, &res, 1); if (IS_ERR(mdio_dev)) @@ -394,6 +396,30 @@ static int __init gfar_of_init(void) of_node_put(mdio); } + /* Get MDIO bus controlled by this eTSEC, if any. Normally only + * eTSEC 1 will control an MDIO bus, not necessarily the same + * bus that its PHY is on ('mdio' above), so we can't just use + * that. What we do is look for a gianfar mdio device that has + * overlapping registers with this device. That's really the + * whole point, to find the device sharing our registers to + * coordinate access with it. + */ + for_each_compatible_node(mdio, NULL, "fsl,gianfar-mdio") { + if (of_address_to_resource(mdio, 0, &res)) + continue; + + if (res.start >= r[0].start && res.end <= r[0].end) { + /* Get the ID the mdio bus platform device was + * registered with. gfar_data.bus_id is + * different because it's for finding a PHY, + * while this is for finding a MII bus. + */ + gfar_data.mdio_bus = res.start&0xfffff; + of_node_put(mdio); + break; + } + } + ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 64b201134fdb..249541a1814b 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -586,6 +586,10 @@ static void gfar_configure_serdes(struct net_device *dev) struct gfar_mii __iomem *regs = (void __iomem *)&priv->regs->gfar_mii_regs; int tbipa = gfar_read(&priv->regs->tbipa); + struct mii_bus *bus = gfar_get_miibus(priv); + + if (bus) + mutex_lock(&bus->mdio_lock); /* Single clk mode, mii mode off(for serdes communication) */ gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT); @@ -596,6 +600,9 @@ static void gfar_configure_serdes(struct net_device *dev) gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); + + if (bus) + mutex_unlock(&bus->mdio_lock); } static void init_registers(struct net_device *dev) diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index bf73eea98010..0e2595d24933 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -269,6 +269,27 @@ static struct device_driver gianfar_mdio_driver = { .remove = gfar_mdio_remove, }; +static int match_mdio_bus(struct device *dev, void *data) +{ + const struct gfar_private *priv = data; + const struct platform_device *pdev = to_platform_device(dev); + + return !strcmp(pdev->name, gianfar_mdio_driver.name) && + pdev->id == priv->einfo->mdio_bus; +} + +/* Given a gfar_priv structure, find the mii_bus controlled by this device (not + * necessarily the same as the bus the gfar's PHY is on), if one exists. + * Normally only the first gianfar controls a mii_bus. */ +struct mii_bus *gfar_get_miibus(const struct gfar_private *priv) +{ + /*const*/ struct device *d; + + d = bus_find_device(gianfar_mdio_driver.bus, NULL, (void *)priv, + match_mdio_bus); + return d ? dev_get_drvdata(d) : NULL; +} + int __init gfar_mdio_init(void) { return driver_register(&gianfar_mdio_driver); diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 2af28b16a0e2..02dc970ca1ff 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h @@ -18,6 +18,8 @@ #ifndef __GIANFAR_MII_H #define __GIANFAR_MII_H +struct gfar_private; /* forward ref */ + #define MIIMIND_BUSY 0x00000001 #define MIIMIND_NOTVALID 0x00000004 @@ -44,6 +46,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value); int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); +struct mii_bus *gfar_get_miibus(const struct gfar_private *priv); int __init gfar_mdio_init(void); void gfar_mdio_exit(void); #endif /* GIANFAR_PHY_H */ diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 4e625e0094c8..708bab58d8d0 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -49,7 +49,8 @@ struct gianfar_platform_data { u32 device_flags; /* board specific information */ u32 board_flags; - char bus_id[MII_BUS_ID_SIZE]; + int mdio_bus; /* Bus controlled by us */ + char bus_id[MII_BUS_ID_SIZE]; /* Bus PHY is on */ u32 phy_id; u8 mac_addr[6]; phy_interface_t interface; From bdb59f949d663b7e943fb5f40b2557af4314abf9 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 30 Oct 2008 18:17:07 -0700 Subject: [PATCH 21/33] gianfar: Don't reset TBI<->SerDes link if it's already up The link may be up already via the chip's reset strapping, or though action of U-Boot, or from the last time the interface was brought up. Resetting the link causes it to go down for several seconds. This can significantly increase the time from power-on to DHCP completion and a device being accessible to the network. Signed-off-by: Trent Piepho Acked-by: Andy Fleming Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 249541a1814b..83a5cb6aa23b 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -591,6 +591,14 @@ static void gfar_configure_serdes(struct net_device *dev) if (bus) mutex_lock(&bus->mdio_lock); + /* If the link is already up, we must already be ok, and don't need to + * configure and reset the TBI<->SerDes link. Maybe U-Boot configured + * everything for us? Resetting it takes the link down and requires + * several seconds for it to come back. + */ + if (gfar_local_mdio_read(regs, tbipa, MII_BMSR) & BMSR_LSTATUS) + goto done; + /* Single clk mode, mii mode off(for serdes communication) */ gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT); @@ -601,6 +609,7 @@ static void gfar_configure_serdes(struct net_device *dev) gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); + done: if (bus) mutex_unlock(&bus->mdio_lock); } From 263e69cbc9e5a9e7bcf6a24f641ef0717d1ae4df Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 30 Oct 2008 23:11:44 -0700 Subject: [PATCH 22/33] pppoe: Fix socket leak. Move SKB trim before we lookup the socket so we don't have to put it on failure. Based upon an initial patch by Jarek Poplawski and suggestions from Herbert Xu. Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index fc6f4b8c64b3..b646e92134dc 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -399,11 +399,11 @@ static int pppoe_rcv(struct sk_buff *skb, if (skb->len < len) goto drop; - po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); - if (!po) + if (pskb_trim_rcsum(skb, len)) goto drop; - if (pskb_trim_rcsum(skb, len)) + po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); + if (!po) goto drop; return sk_receive_skb(sk_pppox(po), skb, 0); From ad1d967c88e349c7e822ad75dd3247a2a50d2ea3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Oct 2008 23:54:35 -0700 Subject: [PATCH 23/33] net: delete excess kernel-doc notation Remove excess kernel-doc function parameters from networking header & driver files: Warning(include/net/sock.h:946): Excess function parameter or struct member 'sk' description in 'sk_filter_release' Warning(include/linux/netdevice.h:1545): Excess function parameter or struct member 'cpu' description in 'netif_tx_lock' Warning(drivers/net/wan/z85230.c:712): Excess function parameter or struct member 'regs' description in 'z8530_interrupt' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/wan/z85230.c | 1 - include/linux/netdevice.h | 1 - include/net/sock.h | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index ccd9cd35ecbe..5bf7e01ef0e9 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -695,7 +695,6 @@ EXPORT_SYMBOL(z8530_nop); * z8530_interrupt - Handle an interrupt from a Z8530 * @irq: Interrupt number * @dev_id: The Z8530 device that is interrupting. - * @regs: unused * * A Z85[2]30 device has stuck its hand in the air for attention. * We scan both the channels on the chip for events and then call diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c8bcb59adfdf..9d77b1d7dca8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1537,7 +1537,6 @@ static inline void __netif_tx_unlock_bh(struct netdev_queue *txq) /** * netif_tx_lock - grab network device transmit lock * @dev: network device - * @cpu: cpu number of lock owner * * Get network device transmit lock */ diff --git a/include/net/sock.h b/include/net/sock.h index ada50c04d09f..c04f9e18ea22 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -936,7 +936,6 @@ extern void sock_init_data(struct socket *sock, struct sock *sk); /** * sk_filter_release: Release a socket filter - * @sk: socket * @fp: filter to remove * * Remove a filter from a socket and release its resources. From 485ac57bc1238719b1508f91b0f9eeda4a3c84bb Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 30 Oct 2008 23:55:16 -0700 Subject: [PATCH 24/33] netns: add register_pernet_gen_subsys/unregister_pernet_gen_subsys netns ops which are registered with register_pernet_gen_device() are shutdown strictly before those which are registered with register_pernet_subsys(). Sometimes this leads to opposite (read: buggy) shutdown ordering between two modules. Add register_pernet_gen_subsys()/unregister_pernet_gen_subsys() for modules which aren't elite enough for entry in struct net, and which can't use register_pernet_gen_device(). PPTP conntracking module is such one. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/net_namespace.h | 2 ++ net/core/net_namespace.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 708009be88b6..700c53a3c6fa 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -214,6 +214,8 @@ struct pernet_operations { extern int register_pernet_subsys(struct pernet_operations *); extern void unregister_pernet_subsys(struct pernet_operations *); +extern int register_pernet_gen_subsys(int *id, struct pernet_operations *); +extern void unregister_pernet_gen_subsys(int id, struct pernet_operations *); extern int register_pernet_device(struct pernet_operations *); extern void unregister_pernet_device(struct pernet_operations *); extern int register_pernet_gen_device(int *id, struct pernet_operations *); diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index f1d07b5c1e17..1895a4ca9c4f 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -325,6 +325,38 @@ void unregister_pernet_subsys(struct pernet_operations *module) } EXPORT_SYMBOL_GPL(unregister_pernet_subsys); +int register_pernet_gen_subsys(int *id, struct pernet_operations *ops) +{ + int rv; + + mutex_lock(&net_mutex); +again: + rv = ida_get_new_above(&net_generic_ids, 1, id); + if (rv < 0) { + if (rv == -EAGAIN) { + ida_pre_get(&net_generic_ids, GFP_KERNEL); + goto again; + } + goto out; + } + rv = register_pernet_operations(first_device, ops); + if (rv < 0) + ida_remove(&net_generic_ids, *id); + mutex_unlock(&net_mutex); +out: + return rv; +} +EXPORT_SYMBOL_GPL(register_pernet_gen_subsys); + +void unregister_pernet_gen_subsys(int id, struct pernet_operations *ops) +{ + mutex_lock(&net_mutex); + unregister_pernet_operations(ops); + ida_remove(&net_generic_ids, id); + mutex_unlock(&net_mutex); +} +EXPORT_SYMBOL_GPL(unregister_pernet_gen_subsys); + /** * register_pernet_device - register a network namespace device * @ops: pernet operations structure for the subsystem From 61e5744849cb936bf4361181b8f9ebccebf4d9db Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 30 Oct 2008 23:55:44 -0700 Subject: [PATCH 25/33] netfilter: nf_conntrack_proto_gre: switch to register_pernet_gen_subsys() register_pernet_gen_device() can't be used is nf_conntrack_pptp module is also used (compiled in or loaded). Right now, proto_gre_net_exit() is called before nf_conntrack_pptp_net_exit(). The former shutdowns and frees GRE piece of netns, however the latter absolutely needs it to flush keymap. Oops is inevitable. Switch to shiny new register_pernet_gen_subsys() to get correct ordering in netns ops list. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_proto_gre.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index a2cdbcbf64c4..4ab62ad85dd4 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -335,7 +335,7 @@ static int __init nf_ct_proto_gre_init(void) rv = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4); if (rv < 0) return rv; - rv = register_pernet_gen_device(&proto_gre_net_id, &proto_gre_net_ops); + rv = register_pernet_gen_subsys(&proto_gre_net_id, &proto_gre_net_ops); if (rv < 0) nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); return rv; @@ -344,7 +344,7 @@ static int __init nf_ct_proto_gre_init(void) static void nf_ct_proto_gre_fini(void) { nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); - unregister_pernet_gen_device(proto_gre_net_id, &proto_gre_net_ops); + unregister_pernet_gen_subsys(proto_gre_net_id, &proto_gre_net_ops); } module_init(nf_ct_proto_gre_init); From 3a8af722495469e9c550386b910c5b93c91cf107 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 31 Oct 2008 00:00:33 -0700 Subject: [PATCH 26/33] net: Really remove all of LOOPBACK_TSO code. As noticed by Saikiran Madugula, commit 7447ef63cf2dfdc444f4c72ae13f604350b2e25f ("loopback: Remove rest of LOOPBACK_TSO code.") got rid of emulate_large_send_offload() but didn't get rid of the call site as well. Signed-off-by: David S. Miller --- drivers/net/loopback.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 3b43bfd85a0f..b1ac63ab8c16 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -76,15 +76,6 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) skb->protocol = eth_type_trans(skb,dev); -#ifdef LOOPBACK_TSO - if (skb_is_gso(skb)) { - BUG_ON(skb->protocol != htons(ETH_P_IP)); - BUG_ON(ip_hdr(skb)->protocol != IPPROTO_TCP); - - emulate_large_send_offload(skb); - return 0; - } -#endif dev->last_rx = jiffies; /* it's OK to use per_cpu_ptr() because BHs are off */ From a432226614c5616e3cfd211e0acffa0acfb4770c Mon Sep 17 00:00:00 2001 From: "fernando@oss.ntt.co" Date: Thu, 23 Oct 2008 04:27:19 +0000 Subject: [PATCH 27/33] xfrm: do not leak ESRCH to user space I noticed that, under certain conditions, ESRCH can be leaked from the xfrm layer to user space through sys_connect. In particular, this seems to happen reliably when the kernel fails to resolve a template either because the AF_KEY receive buffer being used by racoon is full or because the SA entry we are trying to use is in XFRM_STATE_EXPIRED state. However, since this could be a transient issue it could be argued that EAGAIN would be more appropriate. Besides this error code is not even documented in the man page for sys_connect (as of man-pages 3.07). Signed-off-by: Fernando Luis Vazquez Cao Signed-off-by: David S. Miller --- net/xfrm/xfrm_policy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 832b47c1de80..25872747762c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1251,6 +1251,8 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, -EINVAL : -EAGAIN); xfrm_state_put(x); } + else if (error == -ESRCH) + error = -EAGAIN; if (!tmpl->optional) goto fail; From cbafe312ef4a263e9aa36786bc67e1e6d959872b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Fri, 31 Oct 2008 00:40:19 -0700 Subject: [PATCH 28/33] bpa10x: free sk_buff with kfree_skb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspired by Sergio Luis' similar patches, I finally found a case which is trivial enough that spatch won't choke on it. Signed-off-by: Ilpo Järvinen Acked-by: Marcel Holtmann Signed-off-by: David S. Miller --- drivers/bluetooth/bpa10x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 32f3a8ed8d3d..b936d8ce2728 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -443,8 +443,8 @@ static void bpa10x_destruct(struct hci_dev *hdev) BT_DBG("%s", hdev->name); - kfree(data->rx_skb[0]); - kfree(data->rx_skb[1]); + kfree_skb(data->rx_skb[0]); + kfree_skb(data->rx_skb[1]); kfree(data); } From 920da6923cf03c8a78fbaffa408f8ab37f6abfc1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 31 Oct 2008 16:41:26 -0700 Subject: [PATCH 29/33] key: fix setkey(8) policy set breakage Steps to reproduce: #/usr/sbin/setkey -f flush; spdflush; add 192.168.0.42 192.168.0.1 ah 24500 -A hmac-md5 "1234567890123456"; add 192.168.0.42 192.168.0.1 esp 24501 -E 3des-cbc "123456789012123456789012"; spdadd 192.168.0.42 192.168.0.1 any -P out ipsec esp/transport//require ah/transport//require; setkey: invalid keymsg length Policy dump will bail out with the same message after that. -recv(4, "\2\16\0\0\32\0\3\0\0\0\0\0\37\r\0\0\3\0\5\0\377 \0\0\2\0\0\0\300\250\0*\0"..., 32768, 0) = 208 +recv(4, "\2\16\0\0\36\0\3\0\0\0\0\0H\t\0\0\3\0\5\0\377 \0\0\2\0\0\0\300\250\0*\0"..., 32768, 0) = 208 Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/key/af_key.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index e55e0441e4d9..3440a4637f01 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2075,7 +2075,6 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in req_size += socklen * 2; } else { size -= 2*socklen; - socklen = 0; } rq = (void*)skb_put(skb, req_size); pol->sadb_x_policy_len += req_size/8; From d1a203eac0ec13cd1c0ba610fe7a55c9bc40473b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 1 Nov 2008 21:01:09 -0700 Subject: [PATCH 30/33] net: add documentation for skb recycling Commit 04a4bb55bcf35b63d40fd2725e58599ff8310dd7 ("net: add skb_recycle_check() to enable netdriver skb recycling") added a method for network drivers to recycle skbuffs, but while use of this mechanism was documented in the commit message, it should really have been added as a docbook comment as well -- this patch does that. Signed-off-by: Stephen Hemminger Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- net/core/skbuff.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 4e22e3a35359..ebb6b94f8af2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -449,6 +449,18 @@ void kfree_skb(struct sk_buff *skb) __kfree_skb(skb); } +/** + * skb_recycle_check - check if skb can be reused for receive + * @skb: buffer + * @skb_size: minimum receive buffer size + * + * Checks that the skb passed in is not shared or cloned, and + * that it is linear and its head portion at least as large as + * skb_size so that it can be recycled as a receive buffer. + * If these conditions are met, this function does any necessary + * reference count dropping and cleans up the skbuff as if it + * just came from __alloc_skb(). + */ int skb_recycle_check(struct sk_buff *skb, int skb_size) { struct skb_shared_info *shinfo; From 920a46115ca3fa88990276d98520abab85495b2d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 1 Nov 2008 21:22:23 -0700 Subject: [PATCH 31/33] udp: multicast packets need to check namespace Current UDP multicast delivery is not namespace aware. Signed-off-by: Eric Dumazet Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv4/udp.c | 12 +++++++----- net/ipv6/udp.c | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2095abc3caba..cf02701ced48 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -284,7 +284,7 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, } EXPORT_SYMBOL_GPL(udp4_lib_lookup); -static inline struct sock *udp_v4_mcast_next(struct sock *sk, +static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk, __be16 loc_port, __be32 loc_addr, __be16 rmt_port, __be32 rmt_addr, int dif) @@ -296,7 +296,8 @@ static inline struct sock *udp_v4_mcast_next(struct sock *sk, sk_for_each_from(s, node) { struct inet_sock *inet = inet_sk(s); - if (s->sk_hash != hnum || + if (!net_eq(sock_net(s), net) || + s->sk_hash != hnum || (inet->daddr && inet->daddr != rmt_addr) || (inet->dport != rmt_port && inet->dport) || (inet->rcv_saddr && inet->rcv_saddr != loc_addr) || @@ -1079,15 +1080,16 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, read_lock(&udp_hash_lock); sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); dif = skb->dev->ifindex; - sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); + sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); if (sk) { struct sock *sknext = NULL; do { struct sk_buff *skb1 = skb; - sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr, - uh->source, saddr, dif); + sknext = udp_v4_mcast_next(net, sk_next(sk), uh->dest, + daddr, uh->source, saddr, + dif); if (sknext) skb1 = skb_clone(skb, GFP_ATOMIC); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e51da8c092fa..71e259e866a1 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -328,7 +328,7 @@ drop: return -1; } -static struct sock *udp_v6_mcast_next(struct sock *sk, +static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, __be16 loc_port, struct in6_addr *loc_addr, __be16 rmt_port, struct in6_addr *rmt_addr, int dif) @@ -340,7 +340,7 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, sk_for_each_from(s, node) { struct inet_sock *inet = inet_sk(s); - if (sock_net(s) != sock_net(sk)) + if (!net_eq(sock_net(s), net)) continue; if (s->sk_hash == num && s->sk_family == PF_INET6) { @@ -383,14 +383,14 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, read_lock(&udp_hash_lock); sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); dif = inet6_iif(skb); - sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); + sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); if (!sk) { kfree_skb(skb); goto out; } sk2 = sk; - while ((sk2 = udp_v6_mcast_next(sk_next(sk2), uh->dest, daddr, + while ((sk2 = udp_v6_mcast_next(net, sk_next(sk2), uh->dest, daddr, uh->source, saddr, dif))) { struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); if (buff) { From abdd5a0301a6306d6465ceca9de8e732b2fedaa5 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Sat, 1 Nov 2008 21:30:50 -0700 Subject: [PATCH 32/33] IRDA: remove double inclusion of module.h Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/ks959-sir.c | 1 - drivers/net/irda/ksdazzle-sir.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index 2482d61662a2..2e67ae015d91 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -118,7 +118,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 1e0de93fd618..3843b5faba8b 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -82,7 +82,6 @@ #include #include #include -#include #include #include #include From 48dcc33e5e11de0f76b65b113988dbc930d17395 Mon Sep 17 00:00:00 2001 From: Jianjun Kong Date: Sat, 1 Nov 2008 21:37:27 -0700 Subject: [PATCH 33/33] af_unix: netns: fix problem of return value fix problem of return value net/unix/af_unix.c: unix_net_init() when error appears, it should return 'error', not always return 0. Signed-off-by: Jianjun Kong Signed-off-by: David S. Miller --- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index dc504d308ec0..4d3c6071b9a4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2213,7 +2213,7 @@ static int unix_net_init(struct net *net) #endif error = 0; out: - return 0; + return error; } static void unix_net_exit(struct net *net)