From a46f025d053e47b9ce602f53f6d30e94d304a51c Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 16 Apr 2008 14:02:04 -0700 Subject: mac80211: Fix n-band association problem There are two structures named wmm_info and wmm_param, they are used while parsing the beacon frame. (Check the function ieee802_11_parse_elems). Certain APs like D-link does not set the fifth bit in WMM IE. While sending the association request to n-only ap it checks for wmm_ie. If it is set then only ieee80211_ht_cap is sent during association request. So n-only association fails. And this patch fixes this problem by copying the wmm_info to wmm_ie, which enables the "wmm" flag in iee80211_send_assoc. Signed-off-by: Abhijeet Kolekar Acked-by: Ron Rindjunsky Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6b75cb6..c0a5345 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2709,7 +2709,26 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->wmm_ie_len = elems.wmm_param_len + 2; } else bss->wmm_ie_len = 0; - } else if (!elems.wmm_param && bss->wmm_ie) { + } else if (elems.wmm_info && + (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_info_len || + memcmp(bss->wmm_ie, elems.wmm_info, elems.wmm_info_len))) { + /* As for certain AP's Fifth bit is not set in WMM IE in + * beacon frames.So while parsing the beacon frame the + * wmm_info structure is used instead of wmm_param. + * wmm_info structure was never used to set bss->wmm_ie. + * This code fixes this problem by copying the WME + * information from wmm_info to bss->wmm_ie and enabling + * n-band association. + */ + kfree(bss->wmm_ie); + bss->wmm_ie = kmalloc(elems.wmm_info_len + 2, GFP_ATOMIC); + if (bss->wmm_ie) { + memcpy(bss->wmm_ie, elems.wmm_info - 2, + elems.wmm_info_len + 2); + bss->wmm_ie_len = elems.wmm_info_len + 2; + } else + bss->wmm_ie_len = 0; + } else if (!elems.wmm_param && !elems.wmm_info && bss->wmm_ie) { kfree(bss->wmm_ie); bss->wmm_ie = NULL; bss->wmm_ie_len = 0; -- cgit v0.10.2 From 0f48d7e1cf2341148dcafc19a098ca22e184bee9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 17 Apr 2008 19:36:28 +0200 Subject: mac80211: MAINTAINERS update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates the mac80211 maintainers entry to  1) remove Jiri 2) put me first Signed-off-by: Johannes Berg Cc: Michael Wu Cc: Jiri Benc Signed-off-by: John W. Linville diff --git a/MAINTAINERS b/MAINTAINERS index 45b86ab..36aadf6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2547,12 +2547,10 @@ W: http://www.tazenda.demon.co.uk/phil/linux-hp S: Maintained MAC80211 -P: Michael Wu -M: flamingice@sourmilk.net P: Johannes Berg M: johannes@sipsolutions.net -P: Jiri Benc -M: jbenc@suse.cz +P: Michael Wu +M: flamingice@sourmilk.net L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git -- cgit v0.10.2 From 1855ba7812dbd294fcfc083dc7d3b14d3b1f38db Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 18 Apr 2008 20:51:41 +0200 Subject: b43: Workaround invalid bluetooth settings This adds a workaround for invalid bluetooth SPROM settings on ASUS PCI cards. This will stop the microcode from poking with the BT GPIO line. This fixes data transmission on this device, as the BT GPIO line is used for something TX related on this device (probably the power amplifier or the radio). This also adds a modparam knob to help debugging this in the future, as more devices with this bug may show up. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index cf5c046..4bc053f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -84,6 +84,10 @@ int b43_modparam_qos = 1; module_param_named(qos, b43_modparam_qos, int, 0444); MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); +static int modparam_btcoex = 1; +module_param_named(btcoex, modparam_btcoex, int, 0444); +MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)"); + static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), @@ -3708,6 +3712,8 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev) struct ssb_sprom *sprom = &dev->dev->bus->sprom; u32 hf; + if (!modparam_btcoex) + return; if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST)) return; if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode) @@ -3719,11 +3725,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev) else hf |= B43_HF_BTCOEX; b43_hf_write(dev, hf); - //TODO } static void b43_bluetooth_coext_disable(struct b43_wldev *dev) -{ //TODO +{ + if (!modparam_btcoex) + return; + //TODO } static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) @@ -4416,6 +4424,8 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) static void b43_sprom_fixup(struct ssb_bus *bus) { + struct pci_dev *pdev; + /* boardflags workarounds */ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL && bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74) @@ -4423,6 +4433,14 @@ static void b43_sprom_fixup(struct ssb_bus *bus) if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40) bus->sprom.boardflags_lo |= B43_BFL_PACTRL; + if (bus->bustype == SSB_BUSTYPE_PCI) { + pdev = bus->host_pci; + if (pdev->vendor == PCI_VENDOR_ID_BROADCOM && + pdev->device == 0x4318 && + pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK && + pdev->subsystem_device == 0x100F) + bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; + } } static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl) -- cgit v0.10.2 From a259d6a45b915e00e8c6085e35fea7b61e3008a8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 18 Apr 2008 21:06:37 +0200 Subject: b43: Fix HostFlags data types The HostFlags are a bitmask of 48bit. So we must use an u64 datatype to hold all bits. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 4bc053f..a90e902 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3710,7 +3710,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) static void b43_bluetooth_coext_enable(struct b43_wldev *dev) { struct ssb_sprom *sprom = &dev->dev->bus->sprom; - u32 hf; + u64 hf; if (!modparam_btcoex) return; @@ -3860,7 +3860,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev) struct ssb_sprom *sprom = &bus->sprom; struct b43_phy *phy = &dev->phy; int err; - u32 hf, tmp; + u64 hf; + u32 tmp; B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index 575c543..de024dc 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -2043,7 +2043,7 @@ int b43_phy_init(struct b43_wldev *dev) void b43_set_rx_antenna(struct b43_wldev *dev, int antenna) { struct b43_phy *phy = &dev->phy; - u32 hf; + u64 hf; u16 tmp; int autodiv = 0; -- cgit v0.10.2 From 9fc38458355525f801cd2ab403ac89850489a05e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 19 Apr 2008 16:53:00 +0200 Subject: b43: Add more btcoexist workarounds This adds more workarounds for devices with broken BT bits. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a90e902..94a0cde 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4423,6 +4423,12 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) return err; } +#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice) ( \ + (pdev->vendor == PCI_VENDOR_ID_##_vendor) && \ + (pdev->device == _device) && \ + (pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \ + (pdev->subsystem_device == _subdevice) ) + static void b43_sprom_fixup(struct ssb_bus *bus) { struct pci_dev *pdev; @@ -4436,10 +4442,9 @@ static void b43_sprom_fixup(struct ssb_bus *bus) bus->sprom.boardflags_lo |= B43_BFL_PACTRL; if (bus->bustype == SSB_BUSTYPE_PCI) { pdev = bus->host_pci; - if (pdev->vendor == PCI_VENDOR_ID_BROADCOM && - pdev->device == 0x4318 && - pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK && - pdev->subsystem_device == 0x100F) + if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || + IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || + IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013)) bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; } } -- cgit v0.10.2 From 4503183aa32e6886400d82282292934fa64a81b0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 19 Apr 2008 17:52:12 +0200 Subject: ssb: Fix all-ones boardflags In the SSB SPROM a field set to all ones means the value is not defined in the SPROM. In case of the boardflags, we need to set them to zero to avoid confusing drivers. Drivers will only check the flags by ANDing. Signed-off-by: Larry Finger Signed-off-by: Gabor Stefanik Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 904b1a8d..57c4ccf 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -484,6 +484,11 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, goto unsupported; } + if (out->boardflags_lo == 0xFFFF) + out->boardflags_lo = 0; /* per specs */ + if (out->boardflags_hi == 0xFFFF) + out->boardflags_hi = 0; /* per specs */ + return 0; unsupported: ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d " -- cgit v0.10.2 From d1d8f44a4e3c730984283c0bf4b3458e3a88c15a Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Mon, 21 Apr 2008 21:28:24 +0300 Subject: ath5k: Fix radio identification on AR5424/2424 *Fix radio chip identification on AR5424/2424 during ath5k_hw_attach *Try to assign an RF2413 radio on AR2424 for testing Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 87e7822..5fb1ae6 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -304,14 +304,20 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_radio = AR5K_RF2413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { - ah->ah_radio = AR5K_RF5413; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { - if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && - ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) + /* AR5424 */ + if (srev >= AR5K_SREV_VER_AR5424) { + ah->ah_radio = AR5K_RF5413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; - else + /* AR2424 */ + } else { + ah->ah_radio = AR5K_RF2413; /* For testing */ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + } + /* * Register returns 0x4 for radio revision * so ath5k_hw_radio_revision doesn't parse the value -- cgit v0.10.2 From 1ebebea8e844d01c80b93b8ee4d696ee7c0cbc27 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 23 Apr 2008 11:47:15 +0400 Subject: mac80211: Fix race between ieee80211_rx_bss_put and lookup routines. The put routine first decrements the users counter and then (if it is zero) locks the sta_bss_lock and removes one from the list and the hash. Thus, any of ieee80211_sta_config_auth, ieee80211_rx_bss_get or ieee80211_rx_mesh_bss_get can race with it by finding a bss that is about to get kfree-ed. Using atomic_dec_and_lock in ieee80211_rx_bss_put takes care of this race. Signed-off-by: Pavel Emelyanov Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c0a5345..a5e5c31 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2248,10 +2248,13 @@ static void ieee80211_rx_bss_put(struct net_device *dev, struct ieee80211_sta_bss *bss) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - if (!atomic_dec_and_test(&bss->users)) + + local_bh_disable(); + if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { + local_bh_enable(); return; + } - spin_lock_bh(&local->sta_bss_lock); __ieee80211_rx_bss_hash_del(dev, bss); list_del(&bss->list); spin_unlock_bh(&local->sta_bss_lock); -- cgit v0.10.2 From 13d8fd2d15fdd492078bedb9fde87c901a4e4df0 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 23 Apr 2008 12:51:28 +0300 Subject: net/mac80211/rx.c: fix off-by-one This patch fixes an off-by-one in net/mac80211/rx.c introduced by commit 8318d78a44d49ac1edf2bdec7299de3617c4232e (cfg80211 API for channels/bitrates, mac80211 and driver conversion) and spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 52e4554..02f436a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2170,7 +2170,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_supported_band *sband; if (status->band < 0 || - status->band > IEEE80211_NUM_BANDS) { + status->band >= IEEE80211_NUM_BANDS) { WARN_ON(1); return; } -- cgit v0.10.2 From 0da926f05748d273e7b2b673b0de21629ae9acdd Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Wed, 23 Apr 2008 13:45:12 +0300 Subject: mac80211: fix use before check of Qdisc length This patch fixes use of Qdisc length in requeue function, before we checked the reference is valid. (Adrian Bunk's catch) Signed-off-by: Ron Rindjunsky Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 4e94e40..64faa3d 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -709,7 +709,7 @@ void ieee80211_requeue(struct ieee80211_local *local, int queue) struct ieee80211_sched_data *q = qdisc_priv(root_qd); struct Qdisc *qdisc = q->queues[queue]; struct sk_buff *skb = NULL; - u32 len = qdisc->q.qlen; + u32 len; if (!qdisc || !qdisc->dequeue) return; -- cgit v0.10.2 From 1033b3ea11820ea1fb1b877207bd6724e9aaedc3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 23 Apr 2008 19:13:01 +0200 Subject: b43: Workaround DMA quirks Some mainboards/CPUs don't allow DMA masks bigger than a certain limit. Some VIA crap^h^h^h^hdevices have an upper limit of 0xFFFFFFFF. So in this case a 64-bit b43 device would always fail to acquire the mask. Implement a workaround to fallback to lower DMA mask, as we can always also support a lower mask. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 21c886a..6dcbb3c 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -980,6 +980,42 @@ void b43_dma_free(struct b43_wldev *dev) destroy_ring(dma, tx_ring_mcast); } +static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) +{ + u64 orig_mask = mask; + bool fallback = 0; + int err; + + /* Try to set the DMA mask. If it fails, try falling back to a + * lower mask, as we can always also support a lower one. */ + while (1) { + err = ssb_dma_set_mask(dev->dev, mask); + if (!err) + break; + if (mask == DMA_64BIT_MASK) { + mask = DMA_32BIT_MASK; + fallback = 1; + continue; + } + if (mask == DMA_32BIT_MASK) { + mask = DMA_30BIT_MASK; + fallback = 1; + continue; + } + b43err(dev->wl, "The machine/kernel does not support " + "the required %u-bit DMA mask\n", + (unsigned int)dma_mask_to_engine_type(orig_mask)); + return -EOPNOTSUPP; + } + if (fallback) { + b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n", + (unsigned int)dma_mask_to_engine_type(orig_mask), + (unsigned int)dma_mask_to_engine_type(mask)); + } + + return 0; +} + int b43_dma_init(struct b43_wldev *dev) { struct b43_dma *dma = &dev->dma; @@ -989,14 +1025,9 @@ int b43_dma_init(struct b43_wldev *dev) dmamask = supported_dma_mask(dev); type = dma_mask_to_engine_type(dmamask); - err = ssb_dma_set_mask(dev->dev, dmamask); - if (err) { - b43err(dev->wl, "The machine/kernel does not support " - "the required DMA mask (0x%08X%08X)\n", - (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(dmamask & 0x00000000FFFFFFFFULL)); - return -EOPNOTSUPP; - } + err = b43_dma_set_mask(dev, dmamask); + if (err) + return err; err = -ENOMEM; /* setup TX DMA channels. */ -- cgit v0.10.2 From d619ee08490ca78c9571dca133cd0d0527a60839 Mon Sep 17 00:00:00 2001 From: Luis Carlos Cobo Date: Wed, 23 Apr 2008 12:34:59 -0700 Subject: mac80211: update mesh EID values This patch updates mesh EID values, some of which where conflicting with already-approved 11h EIDs (pointed out by Tomas Winkler). I wanted to use the values suggested in the last available 802.11 draft (2.0) but it assigns 50 to MESH_CONFIG, the same value than EXT_SUPP_RATES. Using the values proposed in the draft incremented by one. Signed-off-by: Luis Carlos Cobo Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index f27d11a..529f301 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -465,13 +465,19 @@ enum ieee80211_eid { WLAN_EID_TS_DELAY = 43, WLAN_EID_TCLAS_PROCESSING = 44, WLAN_EID_QOS_CAPA = 46, - /* 802.11s */ - WLAN_EID_MESH_CONFIG = 36, /* Pending IEEE 802.11 ANA approval */ - WLAN_EID_MESH_ID = 37, /* Pending IEEE 802.11 ANA approval */ - WLAN_EID_PEER_LINK = 40, /* Pending IEEE 802.11 ANA approval */ - WLAN_EID_PREQ = 53, /* Pending IEEE 802.11 ANA approval */ - WLAN_EID_PREP = 54, /* Pending IEEE 802.11 ANA approval */ - WLAN_EID_PERR = 55, /* Pending IEEE 802.11 ANA approval */ + /* 802.11s + * + * All mesh EID numbers are pending IEEE 802.11 ANA approval. + * The numbers have been incremented from those suggested in + * 802.11s/D2.0 so that MESH_CONFIG does not conflict with + * EXT_SUPP_RATES. + */ + WLAN_EID_MESH_CONFIG = 51, + WLAN_EID_MESH_ID = 52, + WLAN_EID_PEER_LINK = 55, + WLAN_EID_PREQ = 68, + WLAN_EID_PREP = 69, + WLAN_EID_PERR = 70, /* 802.11h */ WLAN_EID_PWR_CONSTRAINT = 32, WLAN_EID_PWR_CAPABILITY = 33, -- cgit v0.10.2 From 8ba82e969f71d088f718f93d64985d5fcdd9c171 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Wed, 23 Apr 2008 21:56:49 +0200 Subject: prism54: prism54_get_encode() test below 0 on unsigned index previously in this function: u32 index = (dwrq->flags & IW_ENCODE_INDEX) - 1; index is unsigned, so if -1, the original test (below) didn't work. Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index e5b3c28..5b375b2 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -1186,7 +1186,7 @@ prism54_get_encode(struct net_device *ndev, struct iw_request_info *info, rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); devindex = r.u; /* Now get the key, return it */ - if ((index < 0) || (index > 3)) + if (index == -1 || index > 3) /* no index provided, use the current one */ index = devindex; rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); -- cgit v0.10.2 From 4d381ffb02701c3fc976091473aead7c03523133 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Wed, 23 Apr 2008 22:10:29 +0200 Subject: wireless: rndis_wlan: modparam_workaround_interval is never below 0. priv->param_workaround_interval is unsigned, modparam_workaround_interval not. the former is never < 0. Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 977751f..d0b1fb1 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2402,7 +2402,6 @@ static int bcm4320_early_init(struct usbnet *dev) priv->param_power_output = modparam_power_output; priv->param_roamtrigger = modparam_roamtrigger; priv->param_roamdelta = modparam_roamdelta; - priv->param_workaround_interval = modparam_workaround_interval; priv->param_country[0] = toupper(priv->param_country[0]); priv->param_country[1] = toupper(priv->param_country[1]); @@ -2425,8 +2424,10 @@ static int bcm4320_early_init(struct usbnet *dev) else if (priv->param_roamdelta > 2) priv->param_roamdelta = 2; - if (priv->param_workaround_interval < 0) + if (modparam_workaround_interval < 0) priv->param_workaround_interval = 500; + else + priv->param_workaround_interval = modparam_workaround_interval; rndis_set_config_parameter_str(dev, "Country", priv->param_country); rndis_set_config_parameter_str(dev, "FrameBursting", -- cgit v0.10.2 From 099714934d80100624829f1e2961b9dccaef3280 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 23 Apr 2008 16:22:13 -0700 Subject: iwlwifi: Don't unlock priv->mutex if it isn't locked Commit b716bb91 ("iwlwifi: Cancel scanning upon association") moved the test of priv->vif in iwl{3945,4964}_mac_config_interface() outside of where priv->mutex is held, but still tries to do mutex_unlock() on return. This is clearly wrong and triggers a nasty lockdep warning when this codepath is triggered. Fix this by removing the mutex_unlock(). Signed-off-by: Roland Dreier Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1a5678f..a1a0b3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6907,7 +6907,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (priv->vif != vif) { IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); - mutex_unlock(&priv->mutex); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d7e2358..d0bbcaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6473,7 +6473,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, if (priv->vif != vif) { IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); - mutex_unlock(&priv->mutex); return 0; } -- cgit v0.10.2 From 8c0469cdd08df4dacabc8ca33256ce20de43d73f Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Wed, 23 Apr 2008 18:54:01 -0700 Subject: ppp_generic: use stats from net_device structure Use stats which now is in the net_device instead of one declared in ppp structure. Kill ppp_net_stats function, because by default it is used identical internal_stats function from net/core/dev.c Signed-of-by: Paulius Zaleckas Signed-off-by: David S. Miller diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 4dc5b4b..d3207c0 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -123,7 +123,6 @@ struct ppp { u32 minseq; /* MP: min of most recent seqnos */ struct sk_buff_head mrq; /* MP: receive reconstruction queue */ #endif /* CONFIG_PPP_MULTILINK */ - struct net_device_stats stats; /* statistics */ #ifdef CONFIG_PPP_FILTER struct sock_filter *pass_filter; /* filter for packets to pass */ struct sock_filter *active_filter;/* filter for pkts to reset idle */ @@ -914,18 +913,10 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) outf: kfree_skb(skb); - ++ppp->stats.tx_dropped; + ++ppp->dev->stats.tx_dropped; return 0; } -static struct net_device_stats * -ppp_net_stats(struct net_device *dev) -{ - struct ppp *ppp = (struct ppp *) dev->priv; - - return &ppp->stats; -} - static int ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { @@ -1095,8 +1086,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) #endif /* CONFIG_PPP_FILTER */ } - ++ppp->stats.tx_packets; - ppp->stats.tx_bytes += skb->len - 2; + ++ppp->dev->stats.tx_packets; + ppp->dev->stats.tx_bytes += skb->len - 2; switch (proto) { case PPP_IP: @@ -1171,7 +1162,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) drop: if (skb) kfree_skb(skb); - ++ppp->stats.tx_errors; + ++ppp->dev->stats.tx_errors; } /* @@ -1409,7 +1400,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) spin_unlock_bh(&pch->downl); if (ppp->debug & 1) printk(KERN_ERR "PPP: no memory (fragment)\n"); - ++ppp->stats.tx_errors; + ++ppp->dev->stats.tx_errors; ++ppp->nxseq; return 1; /* abandon the frame */ } @@ -1538,7 +1529,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) if (skb->len > 0) /* note: a 0-length skb is used as an error indication */ - ++ppp->stats.rx_length_errors; + ++ppp->dev->stats.rx_length_errors; kfree_skb(skb); ppp_receive_error(ppp); @@ -1547,7 +1538,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) static void ppp_receive_error(struct ppp *ppp) { - ++ppp->stats.rx_errors; + ++ppp->dev->stats.rx_errors; if (ppp->vj) slhc_toss(ppp->vj); } @@ -1627,8 +1618,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) break; } - ++ppp->stats.rx_packets; - ppp->stats.rx_bytes += skb->len - 2; + ++ppp->dev->stats.rx_packets; + ppp->dev->stats.rx_bytes += skb->len - 2; npi = proto_to_npindex(proto); if (npi < 0) { @@ -1806,7 +1797,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) */ if (seq_before(seq, ppp->nextseq)) { kfree_skb(skb); - ++ppp->stats.rx_dropped; + ++ppp->dev->stats.rx_dropped; ppp_receive_error(ppp); return; } @@ -1928,7 +1919,7 @@ ppp_mp_reconstruct(struct ppp *ppp) /* Got a complete packet yet? */ if (lost == 0 && (p->BEbits & E) && (head->BEbits & B)) { if (len > ppp->mrru + 2) { - ++ppp->stats.rx_length_errors; + ++ppp->dev->stats.rx_length_errors; printk(KERN_DEBUG "PPP: reconstructed packet" " is too long (%d)\n", len); } else if (p == head) { @@ -1937,7 +1928,7 @@ ppp_mp_reconstruct(struct ppp *ppp) skb = skb_get(p); break; } else if ((skb = dev_alloc_skb(len)) == NULL) { - ++ppp->stats.rx_missed_errors; + ++ppp->dev->stats.rx_missed_errors; printk(KERN_DEBUG "PPP: no memory for " "reconstructed packet"); } else { @@ -1966,7 +1957,7 @@ ppp_mp_reconstruct(struct ppp *ppp) if (ppp->debug & 1) printk(KERN_DEBUG " missed pkts %u..%u\n", ppp->nextseq, head->sequence-1); - ++ppp->stats.rx_dropped; + ++ppp->dev->stats.rx_dropped; ppp_receive_error(ppp); } @@ -2377,12 +2368,12 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) struct slcompress *vj = ppp->vj; memset(st, 0, sizeof(*st)); - st->p.ppp_ipackets = ppp->stats.rx_packets; - st->p.ppp_ierrors = ppp->stats.rx_errors; - st->p.ppp_ibytes = ppp->stats.rx_bytes; - st->p.ppp_opackets = ppp->stats.tx_packets; - st->p.ppp_oerrors = ppp->stats.tx_errors; - st->p.ppp_obytes = ppp->stats.tx_bytes; + st->p.ppp_ipackets = ppp->dev->stats.rx_packets; + st->p.ppp_ierrors = ppp->dev->stats.rx_errors; + st->p.ppp_ibytes = ppp->dev->stats.rx_bytes; + st->p.ppp_opackets = ppp->dev->stats.tx_packets; + st->p.ppp_oerrors = ppp->dev->stats.tx_errors; + st->p.ppp_obytes = ppp->dev->stats.tx_bytes; if (!vj) return; st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; @@ -2436,7 +2427,6 @@ ppp_create_interface(int unit, int *retp) dev->priv = ppp; dev->hard_start_xmit = ppp_start_xmit; - dev->get_stats = ppp_net_stats; dev->do_ioctl = ppp_net_ioctl; ret = -EEXIST; -- cgit v0.10.2 From 48abfe05cd01279afe27159e98d7c7f932598f42 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 23 Apr 2008 19:37:58 -0700 Subject: tun: Fix minor race in TUNSETLINK ioctl handling. Noticed by Alan Cox. The IFF_UP test is a bit racey, because other entities outside of this driver's ioctl handler can modify that state, even though this ioctl handler runs under lock_kernel(). Signed-off-by: David S. Miller diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d91856b..d8b1ba1 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -668,16 +668,23 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, break; case TUNSETLINK: + { + int ret; + /* Only allow setting the type when the interface is down */ + rtnl_lock(); if (tun->dev->flags & IFF_UP) { DBG(KERN_INFO "%s: Linktype set failed because interface is up\n", tun->dev->name); - return -EBUSY; + ret = -EBUSY; } else { tun->dev->type = (int) arg; DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type); + ret = 0; } - break; + rtnl_unlock(); + return ret; + } #ifdef TUN_DEBUG case TUNSETDEBUG: -- cgit v0.10.2 From 49186b4a083655a4ebf54e94baf0736256b01b47 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Wed, 23 Apr 2008 19:44:13 -0700 Subject: iwlwifi: Fix built-in compilation of iwlcore (part 2) On Wed, 2008-04-23 at 13:38 +0300, Tomas Winkler wrote: > This patch fixes problem in Makefile that prevented > built-in compilation of iwlcore Here is the second part. Without this, drivers/net/wireless/iwlwifi/build-in.o will not be linked into vmlinux. Signed-off-by: Zhu Yi Signed-off-by: David S. Miller diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 7009219..c2642bc 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -56,8 +56,7 @@ obj-$(CONFIG_RTL8187) += rtl8187.o obj-$(CONFIG_ADM8211) += adm8211.o -obj-$(CONFIG_IWL3945) += iwlwifi/ -obj-$(CONFIG_IWL4965) += iwlwifi/ +obj-$(CONFIG_IWLCORE) += iwlwifi/ obj-$(CONFIG_RT2X00) += rt2x00/ obj-$(CONFIG_P54_COMMON) += p54/ -- cgit v0.10.2 From c9c1014b2bd014c7ec037bbb6f58818162fdb265 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 23 Apr 2008 22:10:48 -0700 Subject: [RTNETLINK]: Fix bogus ASSERT_RTNL warning ASSERT_RTNL uses mutex_trylock to test whether the rtnl_mutex is held. This bogus warnings when running in atomic context, which f.e. happens when adding secondary unicast addresses through macvlan or vlan or when synchronizing multicast addresses from wireless devices. Mid-term we might want to consider moving all address updates to process context since the locking seems overly complicated, for now just fix the bogus warning by changing ASSERT_RTNL to use mutex_is_locked(). Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index b9e1740..44c81c7 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -740,13 +740,13 @@ extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change); extern void rtnl_lock(void); extern void rtnl_unlock(void); extern int rtnl_trylock(void); +extern int rtnl_is_locked(void); extern void rtnetlink_init(void); extern void __rtnl_unlock(void); #define ASSERT_RTNL() do { \ - if (unlikely(rtnl_trylock())) { \ - rtnl_unlock(); \ + if (unlikely(!rtnl_is_locked())) { \ printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \ __FILE__, __LINE__); \ dump_stack(); \ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index bc39e41..cf857c4 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -82,6 +82,11 @@ int rtnl_trylock(void) return mutex_trylock(&rtnl_mutex); } +int rtnl_is_locked(void) +{ + return mutex_is_locked(&rtnl_mutex); +} + static struct rtnl_link *rtnl_msg_handlers[NPROTO]; static inline int rtm_msgindex(int msgtype) @@ -1402,6 +1407,7 @@ EXPORT_SYMBOL(rtnetlink_put_metrics); EXPORT_SYMBOL(rtnl_lock); EXPORT_SYMBOL(rtnl_trylock); EXPORT_SYMBOL(rtnl_unlock); +EXPORT_SYMBOL(rtnl_is_locked); EXPORT_SYMBOL(rtnl_unicast); EXPORT_SYMBOL(rtnl_notify); EXPORT_SYMBOL(rtnl_set_sk_err); -- cgit v0.10.2 From 3d36696024499aef19dbf24a781e91a24fbbe4af Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 24 Apr 2008 00:59:25 -0700 Subject: [AF_UNIX] Initialise UNIX sockets before general device initcalls When drivers call request_module(), it tries to do something with UNIX sockets and triggers a 'runaway loop modprobe net-pf-1' warning. Avoid this by initialising AF_UNIX support earlier. Signed-off-by: David Woodhouse Signed-off-by: David S. Miller diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 2851d0d..63ed69f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2193,7 +2193,11 @@ static void __exit af_unix_exit(void) unregister_pernet_subsys(&unix_net_ops); } -module_init(af_unix_init); +/* Earlier than device_initcall() so that other drivers invoking + request_module() don't end up in a loop when modprobe tries + to use a UNIX socket. But later than subsys_initcall() because + we depend on stuff initialised there */ +fs_initcall(af_unix_init); module_exit(af_unix_exit); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 5e659e4cb0eedacdc1f621a61e400a4611ddef8a Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Thu, 24 Apr 2008 01:02:16 -0700 Subject: [NET]: Fix heavy stack usage in seq_file output routines. Plan C: we can follow the Al Viro's proposal about %n like in this patch. The same applies to udp, fib (the /proc/net/route file), rt_cache and sctp debug. This is minus ~150-200 bytes for each. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 02088de..2e2fc33 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -1003,7 +1003,7 @@ static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi) static int fib_seq_show(struct seq_file *seq, void *v) { struct fib_iter_state *iter; - char bf[128]; + int len; __be32 prefix, mask; unsigned flags; struct fib_node *f; @@ -1025,18 +1025,19 @@ static int fib_seq_show(struct seq_file *seq, void *v) mask = FZ_MASK(iter->zone); flags = fib_flag_trans(fa->fa_type, mask, fi); if (fi) - snprintf(bf, sizeof(bf), - "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u", + seq_printf(seq, + "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n", fi->fib_dev ? fi->fib_dev->name : "*", prefix, fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority, mask, (fi->fib_advmss ? fi->fib_advmss + 40 : 0), fi->fib_window, - fi->fib_rtt >> 3); + fi->fib_rtt >> 3, &len); else - snprintf(bf, sizeof(bf), - "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u", - prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0); - seq_printf(seq, "%-127s\n", bf); + seq_printf(seq, + "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n", + prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0, &len); + + seq_printf(seq, "%*s\n", 127 - len, ""); out: return 0; } diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index ea294ff..4b02d14 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -2602,15 +2602,16 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) list_for_each_entry_rcu(fa, &li->falh, fa_list) { const struct fib_info *fi = fa->fa_info; unsigned flags = fib_flag_trans(fa->fa_type, mask, fi); - char bf[128]; + int len; if (fa->fa_type == RTN_BROADCAST || fa->fa_type == RTN_MULTICAST) continue; if (fi) - snprintf(bf, sizeof(bf), - "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u", + seq_printf(seq, + "%s\t%08X\t%08X\t%04X\t%d\t%u\t" + "%d\t%08X\t%d\t%u\t%u%n", fi->fib_dev ? fi->fib_dev->name : "*", prefix, fi->fib_nh->nh_gw, flags, 0, 0, @@ -2619,14 +2620,15 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) (fi->fib_advmss ? fi->fib_advmss + 40 : 0), fi->fib_window, - fi->fib_rtt >> 3); + fi->fib_rtt >> 3, &len); else - snprintf(bf, sizeof(bf), - "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u", + seq_printf(seq, + "*\t%08X\t%08X\t%04X\t%d\t%u\t" + "%d\t%08X\t%d\t%u\t%u%n", prefix, 0, flags, 0, 0, 0, - mask, 0, 0, 0); + mask, 0, 0, 0, &len); - seq_printf(seq, "%-127s\n", bf); + seq_printf(seq, "%*s\n", 127 - len, ""); } } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 780e948..ce25a13 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -367,10 +367,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) "HHUptod\tSpecDst"); else { struct rtable *r = v; - char temp[256]; + int len; - sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t" - "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X", + seq_printf(seq, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t" + "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", r->u.dst.dev ? r->u.dst.dev->name : "*", (unsigned long)r->rt_dst, (unsigned long)r->rt_gateway, r->rt_flags, atomic_read(&r->u.dst.__refcnt), @@ -384,8 +384,9 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1, r->u.dst.hh ? (r->u.dst.hh->hh_output == dev_queue_xmit) : 0, - r->rt_spec_dst); - seq_printf(seq, "%-127s\n", temp); + r->rt_spec_dst, &len); + + seq_printf(seq, "%*s\n", 127 - len, ""); } return 0; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7766151..0e9bc12 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2255,13 +2255,13 @@ void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo) } static void get_openreq4(struct sock *sk, struct request_sock *req, - char *tmpbuf, int i, int uid) + struct seq_file *f, int i, int uid, int *len) { const struct inet_request_sock *ireq = inet_rsk(req); int ttd = req->expires - jiffies; - sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p", + seq_printf(f, "%4d: %08X:%04X %08X:%04X" + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p%n", i, ireq->loc_addr, ntohs(inet_sk(sk)->sport), @@ -2276,10 +2276,11 @@ static void get_openreq4(struct sock *sk, struct request_sock *req, 0, /* non standard timer */ 0, /* open_requests have no inode */ atomic_read(&sk->sk_refcnt), - req); + req, + len); } -static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i) +static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) { int timer_active; unsigned long timer_expires; @@ -2305,8 +2306,8 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i) timer_expires = jiffies; } - sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " - "%08X %5d %8d %lu %d %p %u %u %u %u %d", + seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " + "%08X %5d %8d %lu %d %p %u %u %u %u %d%n", i, src, srcp, dest, destp, sk->sk_state, tp->write_seq - tp->snd_una, sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog : @@ -2322,11 +2323,12 @@ static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i) icsk->icsk_ack.ato, (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong, tp->snd_cwnd, - tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh); + tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh, + len); } static void get_timewait4_sock(struct inet_timewait_sock *tw, - char *tmpbuf, int i) + struct seq_file *f, int i, int *len) { __be32 dest, src; __u16 destp, srcp; @@ -2340,11 +2342,11 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw, destp = ntohs(tw->tw_dport); srcp = ntohs(tw->tw_sport); - sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p", + seq_printf(f, "%4d: %08X:%04X %08X:%04X" + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p%n", i, src, srcp, dest, destp, tw->tw_substate, 0, 0, 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0, - atomic_read(&tw->tw_refcnt), tw); + atomic_read(&tw->tw_refcnt), tw, len); } #define TMPSZ 150 @@ -2352,7 +2354,7 @@ static void get_timewait4_sock(struct inet_timewait_sock *tw, static int tcp4_seq_show(struct seq_file *seq, void *v) { struct tcp_iter_state* st; - char tmpbuf[TMPSZ + 1]; + int len; if (v == SEQ_START_TOKEN) { seq_printf(seq, "%-*s\n", TMPSZ - 1, @@ -2366,16 +2368,16 @@ static int tcp4_seq_show(struct seq_file *seq, void *v) switch (st->state) { case TCP_SEQ_STATE_LISTENING: case TCP_SEQ_STATE_ESTABLISHED: - get_tcp4_sock(v, tmpbuf, st->num); + get_tcp4_sock(v, seq, st->num, &len); break; case TCP_SEQ_STATE_OPENREQ: - get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid); + get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid, &len); break; case TCP_SEQ_STATE_TIME_WAIT: - get_timewait4_sock(v, tmpbuf, st->num); + get_timewait4_sock(v, seq, st->num, &len); break; } - seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf); + seq_printf(seq, "%*s\n", TMPSZ - 1 - len, ""); out: return 0; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b053ac7..1f535e31 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1619,7 +1619,8 @@ void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo) } /* ------------------------------------------------------------------------ */ -static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket) +static void udp4_format_sock(struct sock *sp, struct seq_file *f, + int bucket, int *len) { struct inet_sock *inet = inet_sk(sp); __be32 dest = inet->daddr; @@ -1627,13 +1628,13 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket) __u16 destp = ntohs(inet->dport); __u16 srcp = ntohs(inet->sport); - sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" - " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p", + seq_printf(f, "%4d: %08X:%04X %08X:%04X" + " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p%n", bucket, src, srcp, dest, destp, sp->sk_state, atomic_read(&sp->sk_wmem_alloc), atomic_read(&sp->sk_rmem_alloc), 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), - atomic_read(&sp->sk_refcnt), sp); + atomic_read(&sp->sk_refcnt), sp, len); } int udp4_seq_show(struct seq_file *seq, void *v) @@ -1644,11 +1645,11 @@ int udp4_seq_show(struct seq_file *seq, void *v) "rx_queue tr tm->when retrnsmt uid timeout " "inode"); else { - char tmpbuf[129]; struct udp_iter_state *state = seq->private; + int len; - udp4_format_sock(v, tmpbuf, state->bucket); - seq_printf(seq, "%-127s\n", tmpbuf); + udp4_format_sock(v, seq, state->bucket, &len); + seq_printf(seq, "%*s\n", 127 - len ,""); } return 0; } diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c index cfeb07e..f73ec0e 100644 --- a/net/sctp/objcnt.c +++ b/net/sctp/objcnt.c @@ -83,13 +83,12 @@ static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = { */ static int sctp_objcnt_seq_show(struct seq_file *seq, void *v) { - int i; - char temp[128]; + int i, len; i = (int)*(loff_t *)v; - sprintf(temp, "%s: %d", sctp_dbg_objcnt[i].label, - atomic_read(sctp_dbg_objcnt[i].counter)); - seq_printf(seq, "%-127s\n", temp); + seq_printf(seq, "%s: %d%n", sctp_dbg_objcnt[i].label, + atomic_read(sctp_dbg_objcnt[i].counter), &len); + seq_printf(seq, "%*s\n", 127 - len, ""); return 0; } -- cgit v0.10.2 From 9edb74cc6ccb3a893c3d40727b7003c3c16f85a0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 24 Apr 2008 03:44:43 -0700 Subject: tun: Multicast handling in tun_chr_ioctl() needs proper locking. Since these operations don't go through the normal device calls, we have to ensure we synchronize with those paths. Noticed by Alan Cox. Signed-off-by: David S. Miller diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d8b1ba1..0ce07a3 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -741,7 +741,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, case SIOCADDMULTI: /** Add the specified group to the character device's multicast filter * list. */ + rtnl_lock(); + netif_tx_lock_bh(tun->dev); add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data); + netif_tx_unlock_bh(tun->dev); + rtnl_unlock(); + DBG(KERN_DEBUG "%s: add multi: %s\n", tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data)); return 0; @@ -749,7 +754,12 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, case SIOCDELMULTI: /** Remove the specified group from the character device's multicast * filter list. */ + rtnl_lock(); + netif_tx_lock_bh(tun->dev); del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data); + netif_tx_unlock_bh(tun->dev); + rtnl_unlock(); + DBG(KERN_DEBUG "%s: del multi: %s\n", tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data)); return 0; -- cgit v0.10.2