3.0.23-stable review
Subsystems (45)
Greg KH
maintainercover 3.0.23-stable review
This is the start of the stable review cycle for the 3.0.23 release. There are 73 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu Mar 1 00:00:00 UTC 2012. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v3.0/stable-review/patch-3.0.23-rc1.gz
and the diffstat can be found below.
thanks,
greg k-h
-------------
Makefile | 4 +- arch/arm/include/asm/assembler.h | 5 + arch/arm/mm/cache-v7.S | 6 + arch/powerpc/kernel/perf_event.c | 8 +- arch/x86/include/asm/i387.h | 284 +++++++++++++++++++----- arch/x86/include/asm/processor.h | 1 + arch/x86/include/asm/thread_info.h | 2 - arch/x86/kernel/cpu/intel_cacheinfo.c | 44 +++- arch/x86/kernel/process_32.c | 25 +-- arch/x86/kernel/process_64.c | 29 +-- arch/x86/kernel/traps.c | 41 ++-- arch/x86/kernel/xsave.c | 12 +- arch/x86/kvm/vmx.c | 2 +- drivers/cdrom/cdrom.c | 8 +- drivers/gpu/drm/radeon/r100.c | 4 +- drivers/gpu/drm/radeon/rs600.c | 4 +- drivers/hwmon/ads1015.c | 3 +- drivers/hwmon/f75375s.c | 5 +- drivers/hwmon/max6639.c | 22 +- drivers/infiniband/ulp/ipoib/ipoib.h | 6 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 55 ++--- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 9 +- drivers/media/video/hdpvr/hdpvr-video.c | 3 +- drivers/mmc/card/block.c | 82 ++++--- drivers/net/3c59x.c | 2 +- drivers/net/davinci_emac.c | 6 +- drivers/net/jme.c | 10 +- drivers/net/jme.h | 2 +- drivers/net/usb/ipheth.c | 5 + drivers/net/veth.c | 4 +- drivers/net/via-velocity.c | 3 - drivers/net/wireless/ath/ath9k/rc.c | 2 +- drivers/pci/probe.c | 5 + drivers/scsi/scsi_pm.c | 16 ++ drivers/scsi/scsi_priv.h | 1 + drivers/scsi/scsi_scan.c | 4 +- drivers/usb/core/hcd-pci.c | 5 +- drivers/usb/core/hcd.c | 6 +- drivers/usb/core/hub.c | 30 ++- drivers/usb/host/pci-quirks.c | 11 + drivers/usb/host/xhci-hub.c | 2 +- drivers/usb/host/xhci-mem.c | 32 ++- drivers/usb/host/xhci.c | 5 + drivers/usb/serial/cp210x.c | 2 + drivers/usb/serial/option.c | 143 +----------- drivers/usb/serial/ti_usb_3410_5052.c | 6 +- drivers/usb/serial/ti_usb_3410_5052.h | 4 + drivers/usb/storage/usb.c | 89 +++----- drivers/usb/storage/usb.h | 7 +- fs/ecryptfs/inode.c | 2 + fs/eventpoll.c | 264 ++++++++++++++++++++--- fs/nfs/nfs4state.c | 2 + fs/signalfd.c | 15 ++ include/asm-generic/poll.h | 2 + include/linux/eventpoll.h | 1 + include/linux/fs.h | 1 + include/linux/signalfd.h | 5 +- include/linux/usb/ch11.h | 10 +- include/net/flow.h | 10 + include/net/inet_sock.h | 2 + include/net/route.h | 4 + include/net/sch_generic.h | 9 +- kernel/fork.c | 5 +- kernel/irq/autoprobe.c | 4 +- kernel/irq/chip.c | 42 +++- kernel/irq/internals.h | 2 +- kernel/irq/manage.c | 2 +- mm/nommu.c | 7 + net/core/dev.c | 10 +- net/core/netpoll.c | 2 +- net/ipv4/arp.c | 3 +- net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_options.c | 4 +- net/ipv4/route.c | 97 ++++++--- net/ipv4/tcp_input.c | 45 +++-- net/ipv4/tcp_ipv4.c | 5 + net/ipv6/ip6mr.c | 8 +- net/mac80211/main.c | 4 +- net/netfilter/ipvs/ip_vs_core.c | 2 +- net/sched/sch_choke.c | 3 +- net/sched/sch_netem.c | 7 +- net/sched/sch_sfb.c | 3 +- scripts/package/builddeb | 12 +- sound/pci/hda/patch_conexant.c | 11 +- sound/soc/codecs/wm8962.c | 2 +- 85 files changed, 1062 insertions(+), 613 deletions(-)
Greg KH
maintainerPATCH 1/73 ASoC: wm8962: Fix sidetone enumeration texts
3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Brown <[email protected]>
commit 31794bc37bf2db84f085da52b72bfba65739b2d2 upstream.
The sidetone enumeration texts have left and right swapped.
--- sound/soc/codecs/wm8962.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/codecs/wm8962.c +1 -1
@@ -2373,7 +2373,7 @@ static int out_pga_event(struct snd_soc_ } } -static const char *st_text[] = {"None" ,"Right" ,"Left" }; +static const char *st_text[] = {"None" ,"Left" ,"Right" };static const struct soc_enum str_enum =SOC_ENUM_SINGLE (WM8962_DAC_DSP_MIXING_1 ,2 ,3 , st_text);
Greg KH
maintainerPATCH 2/73 NOMMU: Lock i_mmap_mutex for access to the VMA prio list
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
commit 918e556ec214ed2f584e4cac56d7b29e4bb6bf27 upstream.
Lock i_mmap_mutex for access to the VMA prio list to prevent concurrent access. Currently, certain parts of the mmap handling are protected by the region mutex, but not all.
--- mm/nommu.c | 7 +++++++ 1 file changed, 7 insertions(+)
mm/nommu.c +7 -0
@@ -697,9 +697,11 @@ static void add_vma_to_mm(struct mm_struif (vma->vm_file) { mapping = vma->vm_file->f_mapping; +mutex_lock (&mapping->i_mmap_mutex);flush_dcache_mmap_lock (mapping);vma_prio_tree_insert (vma, &mapping->i_mmap);flush_dcache_mmap_unlock (mapping); +mutex_unlock (&mapping->i_mmap_mutex); }/* add the VMA to the tree */
@@ -761,9 +763,11 @@ static void delete_vma_from_mm(struct vmif (vma->vm_file) { mapping = vma->vm_file->f_mapping; +mutex_lock (&mapping->i_mmap_mutex);flush_dcache_mmap_lock (mapping);vma_prio_tree_remove (vma, &mapping->i_mmap);flush_dcache_mmap_unlock (mapping); +mutex_unlock (&mapping->i_mmap_mutex); }/* remove from the MM's tree and list */
@@ -2061,6 +2065,7 @@ int nommu_shrink_inode_mappings(struct i high = (size +PAGE_SIZE -1 ) >>PAGE_SHIFT ;down_write (&nommu_region_sem); +mutex_lock (&inode->i_mapping->i_mmap_mutex);/* search for VMAs that fall within the dead zone */ vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap,
@@ -2068,6 +2073,7 @@ int nommu_shrink_inode_mappings(struct i/* found one - only interested if it's shared out of the page * cache */ if (vma->vm_flags &VM_SHARED ) { +mutex_unlock (&inode->i_mapping->i_mmap_mutex);up_write (&nommu_region_sem);return -ETXTBSY ;/* not quite true, but near enough */ }
@@ -2095,6 +2101,7 @@ int nommu_shrink_inode_mappings(struct i } } +mutex_unlock (&inode->i_mapping->i_mmap_mutex);up_write (&nommu_region_sem);return 0 ; }
Greg KH
maintainerPATCH 3/73 hwmon: (max6639) Fix FAN_FROM_REG calculation
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris D Schimp <[email protected]>
commit b63d97a36edb1aecf8c13e5f5783feff4d64c24b upstream.
RPM calculation from tachometer value does not depend on PPR. Also, do not report negative RPM values.
--- drivers/hwmon/max6639.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/hwmon/max6639.c +3 -3
@@ -72,8 +72,8 @@ static unsigned short normal_i2c[] = { 0static const int rpm_ranges[] = {2000 ,4000 ,8000 ,16000 }; -#define FAN_FROM_REG (val, div, rpm_range) ((val) == 0 ? -1 : \ - (val) == 255 ? 0 : (rpm_ranges[rpm_range] * 30) / ((div + 1) * (val))) +#define FAN_FROM_REG (val, rpm_range) ((val) == 0 || (val) == 255 ? \ + 0 : (rpm_ranges[rpm_range] * 30) / (val))#define TEMP_LIMIT_TO_REG (val) SENSORS_LIMIT((val) / 1000, 0, 255)/*
@@ -333,7 +333,7 @@ static ssize_t show_fan_input(struct devreturn PTR_ERR (data);return sprintf (buf,"%d\n" ,FAN_FROM_REG (data->fan[attr->index], - data->ppr, data->rpm_range)); + data->rpm_range)); } static ssize_t show_alarm(struct device *dev,
Greg KH
maintainerPATCH 4/73 hwmon: (max6639) Fix PPR register initialization to set both channels
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris D Schimp <[email protected]>
commit 2f2da1ac0ba5b6cc6e1957c4da5ff20e67d8442b upstream.
Initialize PPR register for both channels, and set correct PPR register bits. Also remove unnecessary variable initializations.
--- drivers/hwmon/max6639.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/hwmon/max6639.c +9 -7
@@ -429,9 +429,9 @@ static int max6639_init_client(struct i2struct max6639_data *data =i2c_get_clientdata (client);struct max6639_platform_data *max6639_info = client->dev.platform_data; -int i =0 ; +int i;int rpm_range =1 ;/* default: 4000 RPM */ -int err =0 ; +int err;/* Reset chip to default values, see below for GCONFIG setup */ err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG,
@@ -446,11 +446,6 @@ static int max6639_init_client(struct i2else data->ppr =2 ; data->ppr -=1 ; - err =i2c_smbus_write_byte_data (client, -MAX6639_REG_FAN_PPR (i), - data->ppr <<5 ); -if (err) - goto exit;if (max6639_info) rpm_range =rpm_range_to_reg (max6639_info->rpm_range);
@@ -458,6 +453,13 @@ static int max6639_init_client(struct i2for (i =0 ; i <2 ; i++) { +/* Set Fan pulse per revolution */ + err =i2c_smbus_write_byte_data (client, +MAX6639_REG_FAN_PPR (i), + data->ppr <<6 ); +if (err) + goto exit; +/* Fans config PWM, RPM */ err = i2c_smbus_write_byte_data(client, MAX6639_REG_FAN_CONFIG1(i),
Greg KH
maintainerPATCH 5/73 hwmon: (ads1015) Fix file leak in probe function
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
commit 363434b5dc352464ac7601547891e5fc9105f124 upstream.
An error while creating sysfs attribute files in the driver's probe function results in an error abort, but already created files are not removed. This patch fixes the problem.
--- drivers/hwmon/ads1015.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/hwmon/ads1015.c +1 -2
@@ -284,7 +284,7 @@ static int ads1015_probe(struct i2c_cliecontinue ; err =device_create_file (&client->dev, &ads1015_in[k].dev_attr);if (err) - goto exit_free; + goto exit_remove; } data->hwmon_dev =hwmon_device_register (&client->dev);
@@ -298,7 +298,6 @@ static int ads1015_probe(struct i2c_clie exit_remove:for (k =0 ; k <ADS1015_CHANNELS ; ++k)device_remove_file (&client->dev, &ads1015_in[k].dev_attr); -exit_free:kfree (data); exit:return err;
Greg KH
maintainerPATCH 6/73 powerpc/perf: power_pmu_start restores incorrect values, breaking frequency events
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anton Blanchard <[email protected]>
commit 9a45a9407c69d068500923480884661e2b9cc421 upstream.
perf on POWER stopped working after commit e050e3f0a71b (perf: Fix broken interrupt rate throttling). That patch exposed a bug in the POWER perf_events code.
Since the PMCs count upwards and take an exception when the top bit is set, we want to write 0x80000000 - left in power_pmu_start. We were instead programming in left which effectively disables the counter until we eventually hit 0x80000000. This could take seconds or longer.
With the patch applied I get the expected number of samples:
SAMPLE events: 9948
--- arch/powerpc/kernel/perf_event.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
arch/powerpc/kernel/perf_event.c +7 -1
@@ -865,6 +865,7 @@ static void power_pmu_start(struct perf_ {unsigned long flags;s64 left; +unsigned long val;if (!event->hw.idx || !event->hw.sample_period)return ;
@@ -880,7 +881,12 @@ static void power_pmu_start(struct perf_ event->hw.state =0 ; left =local64_read (&event->hw.period_left); -write_pmc (event->hw.idx, left); + + val =0 ; +if (left <0x80000000L ) + val =0x80000000L - left; + +write_pmc (event->hw.idx, val);perf_event_update_userpage (event);perf_pmu_enable (event->pmu);
Greg KH
maintainerPATCH 7/73 drm/radeon/kms: fix MSI re-arm on rv370+
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit b7f5b7dec3d539a84734f2bcb7e53fbb1532a40b upstream.
MSI_REARM_EN register is a write only trigger register. There is no need RMW when re-arming.
May fix:
https://bugs.freedesktop.org/show_bug.cgi?id=41668
--- drivers/gpu/drm/radeon/r100.c | 4 +--- drivers/gpu/drm/radeon/rs600.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-)
drivers/gpu/drm/radeon/r100.c +1 -3
@@ -681,9 +681,7 @@ int r100_irq_process(struct radeon_devicWREG32 (RADEON_AIC_CNTL , msi_rearm |RS400_MSI_REARM );break ;default : - msi_rearm =RREG32 (RADEON_MSI_REARM_EN ) & ~RV370_MSI_REARM_EN ; -WREG32 (RADEON_MSI_REARM_EN , msi_rearm); -WREG32 (RADEON_MSI_REARM_EN , msi_rearm |RV370_MSI_REARM_EN ); +WREG32 (RADEON_MSI_REARM_EN ,RV370_MSI_REARM_EN );break ; } }
drivers/gpu/drm/radeon/rs600.c +1 -3
@@ -698,9 +698,7 @@ int rs600_irq_process(struct radeon_deviWREG32 (RADEON_BUS_CNTL , msi_rearm |RS600_MSI_REARM );break ;default : - msi_rearm =RREG32 (RADEON_MSI_REARM_EN ) & ~RV370_MSI_REARM_EN ; -WREG32 (RADEON_MSI_REARM_EN , msi_rearm); -WREG32 (RADEON_MSI_REARM_EN , msi_rearm |RV370_MSI_REARM_EN ); +WREG32 (RADEON_MSI_REARM_EN ,RV370_MSI_REARM_EN );break ; } }
Greg KH
maintainerPATCH 8/73 PCI: workaround hard-wired bus number V2
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yinghai Lu <[email protected]>
commit 71f6bd4a23130cd2f4b036010c5790b1295290b9 upstream.
Fixes PCI device detection on IBM xSeries IBM 3850 M2 / x3950 M2 when using ACPI resources (_CRS).
This is default, a manual workaround (without this patch) would be pci=nocrs boot param.
V2: Add dev_warn if the workaround is hit. This should reveal how common such setups are (via google) and point to possible problems if things are still not working as expected. -> Suggested by Jan Beulich.
--- drivers/pci/probe.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/pci/probe.c +5 -0
@@ -657,6 +657,11 @@ int __devinit pci_scan_bridge(struct pcidev_dbg (&dev->dev,"scanning [bus %02x-%02x] behind bridge, pass %d\n" , secondary, subordinate, pass); +if (!primary && (primary != bus->number) && secondary && subordinate) { +dev_warn (&dev->dev,"Primary bus is hard wired to 0\n" ); + primary = bus->number; + } +/* Check if setup is sensible at all */ if (!pass && (primary != bus->number || secondary <= bus->number)) {
Greg KH
maintainerPATCH 9/73 mac80211: Fix a rwlock bad magic bug
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mohammed Shafi Shajakhan <[email protected]>
commit b57e6b560fc2a2742910ac5ca0eb2c46e45aeac2 upstream.
read_lock(&tpt_trig->trig.leddev_list_lock) is accessed via the path ieee80211_open (->) ieee80211_do_open (->) ieee80211_mod_tpt_led_trig (->) ieee80211_start_tpt_led_trig (->) tpt_trig_timer before initializing it.
the intilization of this read/write lock happens via the path ieee80211_led_init (->) led_trigger_register, but we are doing 'ieee80211_led_init' after 'ieeee80211_if_add' where we register netdev_ops.
so we access leddev_list_lock before initializing it and causes the following bug in chrome laptops with AR928X cards with the following script
while true
do
sudo modprobe -v ath9k
sleep 3
sudo modprobe -r ath9k
sleep 3
done
BUG: rwlock bad magic on CPU#1, wpa_supplicant/358, f5b9eccc Pid: 358, comm: wpa_supplicant Not tainted 3.0.13 #1 Call Trace: [<8137b9df>] rwlock_bug+0x3d/0x47 [<81179830>] do_raw_read_lock+0x19/0x29 [<8137f063>] _raw_read_lock+0xd/0xf [<f9081957>] tpt_trig_timer+0xc3/0x145 [mac80211] [<f9081f3a>] ieee80211_mod_tpt_led_trig+0x152/0x174 [mac80211] [<f9076a3f>] ieee80211_do_open+0x11e/0x42e [mac80211] [<f9075390>] ? ieee80211_check_concurrent_iface+0x26/0x13c [mac80211] [<f9076d97>] ieee80211_open+0x48/0x4c [mac80211] [<812dbed8>] __dev_open+0x82/0xab [<812dc0c9>] __dev_change_flags+0x9c/0x113 [<812dc1ae>] dev_change_flags+0x18/0x44 [<8132144f>] devinet_ioctl+0x243/0x51a [<81321ba9>] inet_ioctl+0x93/0xac [<812cc951>] sock_ioctl+0x1c6/0x1ea [<812cc78b>] ? might_fault+0x20/0x20 [<810b1ebb>] do_vfs_ioctl+0x46e/0x4a2 [<810a6ebb>] ? fget_light+0x2f/0x70 [<812ce549>] ? sys_recvmsg+0x3e/0x48 [<810b1f35>] sys_ioctl+0x46/0x69 [<8137fa77>] sysenter_do_call+0x12/0x2
--- net/mac80211/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/mac80211/main.c +2 -2
@@ -910,6 +910,8 @@ int ieee80211_register_hw(struct ieee802wiphy_debug (local->hw.wiphy,"Failed to initialize wep: %d\n" , result); +ieee80211_led_init (local); +rtnl_lock (); result = ieee80211_init_rate_ctrl_alg(local,
@@ -931,8 +933,6 @@ int ieee80211_register_hw(struct ieee802rtnl_unlock (); -ieee80211_led_init (local); - local->network_latency_notifier.notifier_call = ieee80211_max_network_latency; result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
Greg KH
maintainerPATCH 10/73 ipheth: Add iPhone 4S
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Gardner <[email protected]>
commit 72ba009b8a159e995e40d3b4e5d7d265acead983 upstream.
--- drivers/net/usb/ipheth.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/usb/ipheth.c +5 -0
@@ -60,6 +60,7 @@#define USB_PRODUCT_IPHONE_3GS 0x1294#define USB_PRODUCT_IPHONE_4 0x1297#define USB_PRODUCT_IPHONE_4_VZW 0x129c +#define USB_PRODUCT_IPHONE_4S 0x12a0#define IPHETH_USBINTF_CLASS 255#define IPHETH_USBINTF_SUBCLASS 253
@@ -103,6 +104,10 @@ static struct usb_device_id ipheth_table USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW,IPHETH_USBINTF_CLASS ,IPHETH_USBINTF_SUBCLASS , IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( +USB_VENDOR_APPLE ,USB_PRODUCT_IPHONE_4S , +IPHETH_USBINTF_CLASS ,IPHETH_USBINTF_SUBCLASS , + IPHETH_USBINTF_PROTO) }, { } };MODULE_DEVICE_TABLE (usb, ipheth_table);
Greg KH
maintainerPATCH 11/73 eCryptfs: Copy up lower inode attrs after setting lower xattr
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tyler Hicks <[email protected]>
commit 545d680938be1e86a6c5250701ce9abaf360c495 upstream.
After passing through a ->setxattr() call, eCryptfs needs to copy the inode attributes from the lower inode to the eCryptfs inode, as they may have changed in the lower filesystem's ->setxattr() path.
One example is if an extended attribute containing a POSIX Access Control List is being set. The new ACL may cause the lower filesystem to modify the mode of the lower inode and the eCryptfs inode would need to be updated to reflect the new mode.
https://launchpad.net/bugs/926292
--- fs/ecryptfs/inode.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ecryptfs/inode.c +2 -0
@@ -1119,6 +1119,8 @@ ecryptfs_setxattr(struct dentry *dentry, } rc =vfs_setxattr (lower_dentry, name, value, size, flags); +if (!rc) +fsstack_copy_attr_all (dentry->d_inode, lower_dentry->d_inode); out:return rc; }
Greg KH
maintainerPATCH 12/73 ALSA: hda - Fix redundant jack creations for cx5051
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[Note that since the patch isn't applicable (and unnecessary) to 3.3-rc, there is no corresponding upstream fix.]
The cx5051 parser calls snd_hda_input_jack_add() in the init callback to create and initialize the jack detection instances. Since the init callback is called at each time when the device gets woken up after suspend or power-saving mode, the duplicated instances are accumulated at each call. This ends up with the kernel warnings with the too large array size.
The fix is simply to move the calls of snd_hda_input_jack_add() into the parser section instead of the init callback.
The fix is needed only up to 3.2 kernel, since the HD-audio jack layer was redesigned in the 3.3 kernel.
--- sound/pci/hda/patch_conexant.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
sound/pci/hda/patch_conexant.c +10 -1
@@ -1917,6 +1917,10 @@ static void cxt5051_init_mic_port(structsnd_hda_codec_write (codec, nid,0 ,AC_VERB_SET_UNSOLICITED_ENABLE ,AC_USRSP_EN | event); +} + +static void cxt5051_init_mic_jack (struct hda_codec *codec,hda_nid_t nid) +{snd_hda_input_jack_add (codec, nid,SND_JACK_MICROPHONE ,NULL );snd_hda_input_jack_report (codec, nid); }
@@ -1934,7 +1938,6 @@ static int cxt5051_init(struct hda_codecstruct conexant_spec *spec = codec->spec;conexant_init (codec); -conexant_init_jacks (codec);if (spec->auto_mic &AUTO_MIC_PORTB )cxt5051_init_mic_port (codec,0x17 ,CXT5051_PORTB_EVENT );
@@ -2067,6 +2070,12 @@ static int patch_cxt5051(struct hda_codeif (spec->beep_amp)snd_hda_attach_beep_device (codec, spec->beep_amp); +conexant_init_jacks (codec); +if (spec->auto_mic &AUTO_MIC_PORTB ) +cxt5051_init_mic_jack (codec,0x17 ); +if (spec->auto_mic &AUTO_MIC_PORTC ) +cxt5051_init_mic_jack (codec,0x18 ); +return 0 ; }
Greg KH
maintainerPATCH 13/73 mmc: core: check for zero length ioctl data
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Rudholm <[email protected]>
commit 4d6144de8ba263eb3691a737c547e5b2fdc45287 upstream.
If the read or write buffer size associated with the command sent through the mmc_blk_ioctl is zero, do not prepare data buffer.
This enables a ioctl(2) call to for instance send a MMC_SWITCH to set a byte in the ext_csd.
--- drivers/mmc/card/block.c | 82 +++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 37 deletions(-)
drivers/mmc/card/block.c +45 -37
@@ -251,6 +251,9 @@ static struct mmc_blk_ioc_data *mmc_blk_ goto idata_err; } +if (!idata->buf_bytes) +return idata; + idata->buf =kzalloc (idata->buf_bytes,GFP_KERNEL );if (!idata->buf) { err = -ENOMEM ;
@@ -297,25 +300,6 @@ static int mmc_blk_ioctl_cmd(struct blocif (IS_ERR (idata))return PTR_ERR (idata); - cmd.opcode = idata->ic.opcode; - cmd.arg = idata->ic.arg; - cmd.flags = idata->ic.flags; - - data.sg = &sg; - data.sg_len =1 ; - data.blksz = idata->ic.blksz; - data.blocks = idata->ic.blocks; - -sg_init_one (data.sg, idata->buf, idata->buf_bytes); - -if (idata->ic.write_flag) - data.flags =MMC_DATA_WRITE ; -else - data.flags =MMC_DATA_READ ; - - mrq.cmd = &cmd; - mrq.data = &data; - md =mmc_blk_get (bdev->bd_disk);if (!md) { err = -EINVAL ;
@@ -328,6 +312,48 @@ static int mmc_blk_ioctl_cmd(struct bloc goto cmd_done; } + cmd.opcode = idata->ic.opcode; + cmd.arg = idata->ic.arg; + cmd.flags = idata->ic.flags; + +if (idata->buf_bytes) { + data.sg = &sg; + data.sg_len =1 ; + data.blksz = idata->ic.blksz; + data.blocks = idata->ic.blocks; + +sg_init_one (data.sg, idata->buf, idata->buf_bytes); + +if (idata->ic.write_flag) + data.flags =MMC_DATA_WRITE ; +else + data.flags =MMC_DATA_READ ; + +/* data.flags must already be set before doing this. */ +mmc_set_data_timeout (&data, card); + +/* Allow overriding the timeout_ns for empirical tuning. */ +if (idata->ic.data_timeout_ns) + data.timeout_ns = idata->ic.data_timeout_ns; + +if ((cmd.flags &MMC_RSP_R1B ) ==MMC_RSP_R1B ) { +/* +* Pretend this is a data transfer and rely on the +* host driver to compute timeout. When all host +* drivers support cmd.cmd_timeout for R1B, this +* can be changed to: +* +* mrq.data = NULL; +* cmd.cmd_timeout = idata->ic.cmd_timeout_ms; +*/ + data.timeout_ns = idata->ic.cmd_timeout_ms *1000000 ; + } + + mrq.data = &data; + } + + mrq.cmd = &cmd; +mmc_claim_host (card->host);if (idata->ic.is_acmd) {
@@ -336,24 +362,6 @@ static int mmc_blk_ioctl_cmd(struct bloc goto cmd_rel_host; } -/* data.flags must already be set before doing this. */ -mmc_set_data_timeout (&data, card); -/* Allow overriding the timeout_ns for empirical tuning. */ -if (idata->ic.data_timeout_ns) - data.timeout_ns = idata->ic.data_timeout_ns; - -if ((cmd.flags &MMC_RSP_R1B ) ==MMC_RSP_R1B ) { -/* -* Pretend this is a data transfer and rely on the host driver -* to compute timeout. When all host drivers support -* cmd.cmd_timeout for R1B, this can be changed to: -* -* mrq.data = NULL; -* cmd.cmd_timeout = idata->ic.cmd_timeout_ms; -*/ - data.timeout_ns = idata->ic.cmd_timeout_ms *1000000 ; - } -mmc_wait_for_req (card->host, &mrq);if (cmd.error) {
Greg KH
maintainerPATCH 14/73 NFSv4: Ensure we throw out bad delegation stateids on NFS4ERR_BAD_STATEID
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
commit b9f9a03150969e4bd9967c20bce67c4de769058f upstream.
To ensure that we don't just reuse the bad delegation when we attempt to recover the nfs4_state that received the bad stateid error.
--- fs/nfs/nfs4state.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfs/nfs4state.c +2 -0
@@ -1065,6 +1065,8 @@ void nfs4_schedule_stateid_recovery(cons {struct nfs_client *clp = server->nfs_client; +if (test_and_clear_bit (NFS_DELEGATED_STATE , &state->flags)) +nfs_async_inode_return_delegation (state->inode, &state->stateid);nfs4_state_mark_reclaim_nograce (clp, state);nfs4_schedule_state_manager (clp); }
Greg KH
maintainerPATCH 15/73 ARM: 7321/1: cache-v7: Disable preemption when reading CCSIDR
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Boyd <[email protected]>
commit b46c0f74657d1fe1c1b0c1452631cc38a9e6987f upstream.
armv7's flush_cache_all() flushes caches via set/way. To determine the cache attributes (line size, number of sets, etc.) the assembly first writes the CSSELR register to select a cache level and then reads the CCSIDR register. The CSSELR register is banked per-cpu and is used to determine which cache level CCSIDR reads. If the task is migrated between when the CSSELR is written and the CCSIDR is read the CCSIDR value may be for an unexpected cache level (for example L1 instead of L2) and incorrect cache flushing could occur.
Disable interrupts across the write and read so that the correct cache attributes are read and used for the cache flushing routine. We disable interrupts instead of disabling preemption because the critical section is only 3 instructions and we want to call v7_dcache_flush_all from __v7_setup which doesn't have a full kernel stack with a struct thread_info.
This fixes a problem we see in scm_call() when flush_cache_all() is called from preemptible context and sometimes the L2 cache is not properly flushed out.
--- arch/arm/mm/cache-v7.S | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm/mm/cache-v7.S +6 -0
@@ -54,9 +54,15 @@ loop1: and r1, r1, #7 @ mask of the bits for current cache only cmp r1, #2 @ see what cache we have at this level blt skip @ skip if no cache, or just i-cache +#ifdef CONFIG_PREEMPT + save_and_disable_irqs r9 @ make cssr&csidr read atomic +#endif mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr isb @ isb to sych the new cssr&csidr mrc p15, 1, r1, c0, c0, 0 @ read the new csidr +#ifdef CONFIG_PREEMPT + restore_irqs_notrace r9 +#endif and r2, r1, #7 @ extract the length of the cache lines add r2, r2, #4 @ add 4 (line length offset) ldr r4, =0x3ff
Greg KH
maintainerPATCH 16/73 ARM: 7325/1: fix v7 boot with lockdep enabled
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rabin Vincent <[email protected]>
commit 8e43a905dd574f54c5715d978318290ceafbe275 upstream.
Bootup with lockdep enabled has been broken on v7 since b46c0f74657d ("ARM: 7321/1: cache-v7: Disable preemption when reading CCSIDR").
This is because v7_setup (which is called very early during boot) calls v7_flush_dcache_all, and the save_and_disable_irqs added by that patch ends up attempting to call into lockdep C code (trace_hardirqs_off()) when we are in no position to execute it (no stack, MMU off).
Fix this by using a notrace variant of save_and_disable_irqs. The code already uses the notrace variant of restore_irqs.
--- arch/arm/include/asm/assembler.h | 5 +++++ arch/arm/mm/cache-v7.S | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
arch/arm/include/asm/assembler.h +5 -0
@@ -137,6 +137,11 @@ disable_irq .endm + .macro save_and_disable_irqs_notrace, oldcpsr + mrs \oldcpsr, cpsr + disable_irq_notrace + .endm +/* * Restore interrupt state previously stored in a register. We don't * guarantee that this will preserve the flags.
arch/arm/mm/cache-v7.S +1 -1
@@ -55,7 +55,7 @@ loop1: cmp r1, #2 @ see what cache we have at this level blt skip @ skip if no cache, or just i-cache #ifdef CONFIG_PREEMPT - save_and_disable_irqs r9 @ make cssr&csidr read atomic + save_and_disable_irqs_notrace r9 @ make cssr&csidr read atomic #endif mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr isb @ isb to sych the new cssr&csidr
Greg KH
maintainerPATCH 17/73 net: Make qdisc_skb_cb upper size bound explicit.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: "David S. Miller" <[email protected]>
[ Upstream commit 16bda13d90c8d5da243e2cfa1677e62ecce26860 ]
Just like skb->cb[], so that qdisc_skb_cb can be encapsulated inside of other data structures.
This is intended to be used by IPoIB so that it can remember addressing information stored at hard_header_ops->create() time that it can fetch when the packet gets to the transmit routine.
--- include/net/sch_generic.h | 9 ++++++++- net/sched/sch_choke.c | 3 +-- net/sched/sch_netem.c | 3 +-- net/sched/sch_sfb.c | 3 +-- 4 files changed, 11 insertions(+), 7 deletions(-)
include/net/sch_generic.h +8 -1
@@ -219,9 +219,16 @@ struct tcf_proto {struct qdisc_skb_cb {unsigned int pkt_len; -long data[]; +unsigned char data[24 ]; }; +static inline void qdisc_cb_private_validate (const struct sk_buff *skb,int sz) +{ +struct qdisc_skb_cb *qcb; +BUILD_BUG_ON (sizeof (skb->cb) <sizeof (unsigned int ) + sz); +BUILD_BUG_ON (sizeof (qcb->data) < sz); +} +static inline int qdisc_qlen (struct Qdisc *q) {return q->q.qlen;
net/sched/sch_choke.c +1 -2
@@ -225,8 +225,7 @@ struct choke_skb_cb {static inline struct choke_skb_cb *choke_skb_cb (const struct sk_buff *skb) { -BUILD_BUG_ON (sizeof (skb->cb) < -sizeof (struct qdisc_skb_cb ) +sizeof (struct choke_skb_cb )); +qdisc_cb_private_validate (skb,sizeof (struct choke_skb_cb ));return (struct choke_skb_cb *)qdisc_skb_cb (skb)->data; }
net/sched/sch_netem.c +1 -2
@@ -117,8 +117,7 @@ struct netem_skb_cb {static inline struct netem_skb_cb *netem_skb_cb (struct sk_buff *skb) { -BUILD_BUG_ON (sizeof (skb->cb) < -sizeof (struct qdisc_skb_cb ) +sizeof (struct netem_skb_cb )); +qdisc_cb_private_validate (skb,sizeof (struct netem_skb_cb ));return (struct netem_skb_cb *)qdisc_skb_cb (skb)->data; }
net/sched/sch_sfb.c +1 -2
@@ -93,8 +93,7 @@ struct sfb_skb_cb {static inline struct sfb_skb_cb *sfb_skb_cb (const struct sk_buff *skb) { -BUILD_BUG_ON (sizeof (skb->cb) < -sizeof (struct qdisc_skb_cb ) +sizeof (struct sfb_skb_cb )); +qdisc_cb_private_validate (skb,sizeof (struct sfb_skb_cb ));return (struct sfb_skb_cb *)qdisc_skb_cb (skb)->data; }
Greg KH
maintainerPATCH 18/73 IPoIB: Stop lying about hard_header_len and use skb->cb to stash LL addresses
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roland Dreier <[email protected]>
[ Upstream commit 936d7de3d736e0737542641269436f4b5968e9ef ]
Commit a0417fa3a18a ("net: Make qdisc_skb_cb upper size bound explicit.") made it possible for a netdev driver to use skb->cb between its header_ops.create method and its .ndo_start_xmit method. Use this in ipoib_hard_header() to stash away the LL address (GID + QPN), instead of the "ipoib_pseudoheader" hack. This allows IPoIB to stop lying about its hard_header_len, which will let us fix the L2 check for GRO.
--- drivers/infiniband/ulp/ipoib/ipoib.h | 6 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 55 ++++++++----------------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 9 ---- 3 files changed, 24 insertions(+), 46 deletions(-)
drivers/infiniband/ulp/ipoib/ipoib.h +4 -2
@@ -44,6 +44,7 @@#include <linux/mutex.h> #include <net/neighbour.h> +#include <net/sch_generic.h> #include <asm/atomic.h>
@@ -117,8 +118,9 @@ struct ipoib_header {u16 reserved; }; -struct ipoib_pseudoheader { -u8 hwaddr[INFINIBAND_ALEN ]; +struct ipoib_cb { +struct qdisc_skb_cb qdisc_cb; +u8 hwaddr[INFINIBAND_ALEN ]; };/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
drivers/infiniband/ulp/ipoib/ipoib_main.c +19 -36
122 lines not on this page · raw message
drivers/infiniband/ulp/ipoib/ipoib_multicast.c +1 -8
@@ -258,21 +258,14 @@ static int ipoib_mcast_join_finish(strucnetif_tx_lock_bh (dev);while (!skb_queue_empty (&mcast->pkt_queue)) {struct sk_buff *skb =skb_dequeue (&mcast->pkt_queue); -struct dst_entry *dst =skb_dst (skb); -struct neighbour *n =NULL ;netif_tx_unlock_bh (dev); skb->dev = dev; -if (dst) - n =dst_get_neighbour_raw (dst); -if (!dst || !n) { -/* put pseudoheader back on for next time */ -skb_push (skb,sizeof (struct ipoib_pseudoheader )); - }if (dev_queue_xmit (skb))ipoib_warn (priv,"dev_queue_xmit failed to requeue packet\n" ); +netif_tx_lock_bh (dev); }netif_tx_unlock_bh (dev);
Greg KH
maintainerPATCH 19/73 gro: more generic L2 header check
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 5ca3b72c5da47d95b83857b768def6172fbc080a ]
Shlomo Pongratz reported GRO L2 header check was suited for Ethernet only, and failed on IB/ipoib traffic.
He provided a patch faking a zeroed header to let GRO aggregates frames.
Roland Dreier, Herbert Xu, and others suggested we change GRO L2 header check to be more generic, ie not assuming L2 header is 14 bytes, but taking into account hard_header_len.
__napi_gro_receive() has special handling for the common case (Ethernet) to avoid a memcmp() call and use an inline optimized function instead.
--- net/core/dev.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/core/dev.c +8 -2
@@ -3434,14 +3434,20 @@ static inline gro_result_t __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { struct sk_buff *p; +unsigned int maclen = skb->dev->hard_header_len;for (p = napi->gro_list; p; p = p->next) {unsigned long diffs; diffs = (unsigned long )p->dev ^ (unsigned long )skb->dev; diffs |= p->vlan_tci ^ skb->vlan_tci; - diffs |=compare_ether_header (skb_mac_header (p), -skb_gro_mac_header (skb)); +if (maclen ==ETH_HLEN ) + diffs |=compare_ether_header (skb_mac_header (p), +skb_gro_mac_header (skb)); +else if (!diffs) + diffs =memcmp (skb_mac_header (p), +skb_gro_mac_header (skb), + maclen);NAPI_GRO_CB (p)->same_flow = !diffs;NAPI_GRO_CB (p)->flush =0 ; }
Greg KH
maintainerPATCH 20/73 veth: Enforce minimum size of VETH_INFO_PEER
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Graf <[email protected]>
[ Upstream commit 237114384ab22c174ec4641e809f8e6cbcfce774 ]
VETH_INFO_PEER carries struct ifinfomsg plus optional IFLA attributes. A minimal size of sizeof(struct ifinfomsg) must be enforced or we may risk accessing that struct beyond the limits of the netlink message.
--- drivers/net/veth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/veth.c +3 -1
@@ -421,7 +421,9 @@ static void veth_dellink(struct net_deviunregister_netdevice_queue (peer, head); } -static const struct nla_policy veth_policy[VETH_INFO_MAX +1 ]; +static const struct nla_policy veth_policy[VETH_INFO_MAX +1 ] = { + [VETH_INFO_PEER ] = { .len =sizeof (struct ifinfomsg ) }, +};static struct rtnl_link_ops veth_link_ops = { .kind =DRV_NAME ,
Greg KH
maintainerPATCH 21/73 3c59x: shorten timer period for slave devices
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 3013dc0cceb9baaf25d5624034eeaa259bf99004 ]
Jean Delvare reported bonding on top of 3c59x adapters was not detecting network cable removal fast enough.
3c59x indeed uses a 60 seconds timer to check link status if carrier is on, and 5 seconds if carrier is off.
This patch reduces timer period to 5 seconds if device is a bonding slave.
--- drivers/net/3c59x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/3c59x.c +1 -1
@@ -1842,7 +1842,7 @@ vortex_timer(unsigned long data) ok =1 ; } -if (!netif_carrier_ok (dev)) +if (dev->flags &IFF_SLAVE || !netif_carrier_ok (dev)) next_tick =5 *HZ ;if (vp->medialock)
Greg KH
maintainerPATCH 22/73 ipv6-multicast: Fix memory leak in input path.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Greear <[email protected]>
[ Upstream commit 2015de5fe2a47086a3260802275932bfd810884e ]
Have to free the skb before returning if we fail
the fib lookup.
--- net/ipv6/ip6mr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv6/ip6mr.c +3 -1
@@ -2051,8 +2051,10 @@ int ip6_mr_input(struct sk_buff *skb)int err; err =ip6mr_fib_lookup (net, &fl6, &mrt); -if (err <0 ) +if (err <0 ) { +kfree_skb (skb);return err; + }read_lock (&mrt_lock); cache = ip6mr_cache_find(mrt,
Greg KH
maintainerPATCH 23/73 ipv6-multicast: Fix memory leak in IPv6 multicast.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Greear <[email protected]>
[ Upstream commit 67928c4041606f02725f3c95c4c0404e4532df1b ]
If reg_vif_xmit cannot find a routing entry, be sure to free the skb before returning the error.
--- net/ipv6/ip6mr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv6/ip6mr.c +3 -1
@@ -696,8 +696,10 @@ static netdev_tx_t reg_vif_xmit(struct sint err; err =ip6mr_fib_lookup (net, &fl6, &mrt); -if (err <0 ) +if (err <0 ) { +kfree_skb (skb);return err; + }read_lock (&mrt_lock); dev->stats.tx_bytes += skb->len;
Greg KH
maintainerPATCH 24/73 ipv4: fix for ip_options_rcv_srr() daddr update.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Wei <[email protected]>
[ Upstream commit b12f62efb8ec0b9523bdb6c2d412c07193086de9 ]
When opt->srr_is_hit is set skb_rtable(skb) has been updated for 'nexthop' and iph->daddr should always equals to skb_rtable->rt_dst holds, We need update iph->daddr either.
--- net/ipv4/ip_options.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/ip_options.c +1 -0
@@ -640,6 +640,7 @@ int ip_options_rcv_srr(struct sk_buff *s }if (srrptr <= srrspace) { opt->srr_is_hit =1 ; + iph->daddr = nexthop; opt->is_changed =1 ; }return 0 ;
Greg KH
maintainerPATCH 25/73 ipv4: Save nexthop address of LSRR/SSRR option to IPCB.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Wei <[email protected]>
[ Upstream commit ac8a48106be49c422575ddc7531b776f8eb49610 ]
We can not update iph->daddr in ip_options_rcv_srr(), It is too early. When some exception ocurred later (eg. in ip_forward() when goto sr_failed) we need the ip header be identical to the original one as ICMP need it.
Add a field 'nexthop' in struct ip_options to save nexthop of LSRR or SSRR option.
--- include/net/inet_sock.h | 2 ++ net/ipv4/ip_forward.c | 2 +- net/ipv4/ip_options.c | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-)
include/net/inet_sock.h +2 -0
@@ -31,6 +31,7 @@/** struct ip_options - IP Options * * @faddr - Saved first hop address +* @nexthop - Saved nexthop address in LSRR and SSRR * @is_data - Options in __data, rather than skb * @is_strictroute - Strict source route * @srr_is_hit - Packet destination addr was our one
@@ -41,6 +42,7 @@*/ struct ip_options {__be32 faddr; +__be32 nexthop;unsigned char optlen;unsigned char srr;unsigned char rr;
net/ipv4/ip_forward.c +1 -1
@@ -84,7 +84,7 @@ int ip_forward(struct sk_buff *skb) rt =skb_rtable (skb); -if (opt->is_strictroute &&ip_hdr (skb)->daddr != rt->rt_gateway) +if (opt->is_strictroute && opt->nexthop != rt->rt_gateway) goto sr_failed; if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
net/ipv4/ip_options.c +3 -2
@@ -568,12 +568,13 @@ void ip_forward_options(struct sk_buff * ) {if (srrptr +3 > srrspace)break ; -if (memcmp (&ip_hdr (skb)->daddr, &optptr[srrptr-1 ],4 ) ==0 ) +if (memcmp (&opt->nexthop, &optptr[srrptr-1 ],4 ) ==0 )break ; }if (srrptr +3 <= srrspace) { opt->is_changed =1 ;ip_rt_get_source (&optptr[srrptr-1 ], skb, rt); +ip_hdr (skb)->daddr = opt->nexthop; optptr[2 ] = srrptr+4 ; }else if (net_ratelimit ())printk (KERN_CRIT "ip_forward(): Argh! Destination lost!\n" );
@@ -640,7 +641,7 @@ int ip_options_rcv_srr(struct sk_buff *s }if (srrptr <= srrspace) { opt->srr_is_hit =1 ; - iph->daddr = nexthop; + opt->nexthop = nexthop; opt->is_changed =1 ; }return 0 ;
Greg KH
maintainerPATCH 26/73 ipv4: Fix wrong order of ip_rt_get_source() and update iph->daddr.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Wei <[email protected]>
[ Upstream commit 5dc7883f2a7c25f8df40d7479687153558cd531b ]
This patch fix a bug which introduced by commit ac8a4810 (ipv4: Save nexthop address of LSRR/SSRR option to IPCB.).In that patch, we saved the nexthop of SRR in ip_option->nexthop and update iph->daddr until we get to ip_forward_options(), but we need to update it before ip_rt_get_source(), otherwise we may get a wrong src.
--- net/ipv4/ip_options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/ip_options.c +1 -1
@@ -573,8 +573,8 @@ void ip_forward_options(struct sk_buff * }if (srrptr +3 <= srrspace) { opt->is_changed =1 ; -ip_rt_get_source (&optptr[srrptr-1 ], skb, rt);ip_hdr (skb)->daddr = opt->nexthop; +ip_rt_get_source (&optptr[srrptr-1 ], skb, rt); optptr[2 ] = srrptr+4 ; }else if (net_ratelimit ())printk (KERN_CRIT "ip_forward(): Argh! Destination lost!\n" );
Greg KH
maintainerPATCH 27/73 ipv4: reset flowi parameters on route connect
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit e6b45241c57a83197e5de9166b3b0d32ac562609 ]
Eric Dumazet found that commit 813b3b5db83
(ipv4: Use caller's on-stack flowi as-is in output route lookups.) that comes in 3.0 added a regression. The problem appears to be that resulting flowi4_oif is used incorrectly as input parameter to some routing lookups. The result is that when connecting to local port without listener if the IP address that is used is not on a loopback interface we incorrectly assign RTN_UNICAST to the output route because no route is matched by oif=lo. The RST packet can not be sent immediately by tcp_v4_send_reset because it expects RTN_LOCAL.
So, change ip_route_connect and ip_route_newports to
update the flowi4 fields that are input parameters because we do not want unnecessary binding to oif.
To make it clear what are the input parameters that
can be modified during lookup and to show which fields of floiw4 are reused add a new function to update the flowi4
structure: flowi4_update_output.
Thanks to Yurij M. Plotnikov for providing a bug report including a program to reproduce the problem.
Thanks to Eric Dumazet for tracking the problem down to tcp_v4_send_reset and providing initial fix.
--- include/net/flow.h | 10 ++++++++++ include/net/route.h | 4 ++++ 2 files changed, 14 insertions(+)
include/net/flow.h +10 -0
@@ -90,6 +90,16 @@ static inline void flowi4_init_output(st fl4->fl4_dport = dport; fl4->fl4_sport = sport; } + +/* Reset some input parameters after previous lookup */ +static inline void flowi4_update_output (struct flowi4 *fl4,int oif,__u8 tos, +__be32 daddr,__be32 saddr) +{ + fl4->flowi4_oif = oif; + fl4->flowi4_tos = tos; + fl4->daddr = daddr; + fl4->saddr = saddr; +}struct flowi6 {
include/net/route.h +4 -0
@@ -270,6 +270,7 @@ static inline struct rtable *ip_route_coif (IS_ERR (rt))return rt;ip_rt_put (rt); +flowi4_update_output (fl4, oif, tos, fl4->daddr, fl4->saddr); }security_sk_classify_flow (sk,flowi4_to_flowi (fl4));return ip_route_output_flow (net, fl4, sk);
@@ -284,6 +285,9 @@ static inline struct rtable *ip_route_ne fl4->fl4_dport = dport; fl4->fl4_sport = sport;ip_rt_put (rt); +flowi4_update_output (fl4, sk->sk_bound_dev_if, +RT_CONN_FLAGS (sk), fl4->daddr, + fl4->saddr);security_sk_classify_flow (sk,flowi4_to_flowi (fl4));return ip_route_output_flow (sock_net (sk), fl4, sk); }
Greg KH
maintainerPATCH 28/73 net: Dont proxy arp respond if iif == rt->dst.dev if private VLAN is disabled
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Graf <[email protected]>
[ Upstream commit 70620c46ac2b45c24b0f22002fdf5ddd1f7daf81 ]
Commit 653241 (net: RFC3069, private VLAN proxy arp support) changed the behavior of arp proxy to send arp replies back out on the interface the request came in even if the private VLAN feature is disabled.
Previously we checked rt->dst.dev != skb->dev for in scenarios, when proxy arp is enabled on for the netdevice and also when individual proxy neighbour entries have been added.
This patch adds the check back for the pneigh_lookup() scenario.
--- net/ipv4/arp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv4/arp.c +2 -1
@@ -906,7 +906,8 @@ static int arp_process(struct sk_buff *sif (addr_type ==RTN_UNICAST && (arp_fwd_proxy (in_dev, dev, rt) ||arp_fwd_pvlan (in_dev, dev, rt, sip, tip) || -pneigh_lookup (&arp_tbl, net, &tip, dev,0 ))) { + (rt->dst.dev != dev && +pneigh_lookup (&arp_tbl, net, &tip, dev,0 )))) { n =neigh_event_ns (&arp_tbl, sha, &sip, dev);if (n)neigh_release (n);
Greg KH
maintainerPATCH 29/73 netpoll: netpoll_poll_dev() should access dev->flags
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 58e05f357a039a94aa36475f8c110256f693a239 ]
commit 5a698af53f (bond: service netpoll arp queue on master device) tested IFF_SLAVE flag against dev->priv_flags instead of dev->flags
--- net/core/netpoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/netpoll.c +1 -1
@@ -193,7 +193,7 @@ void netpoll_poll_dev(struct net_devicepoll_napi (dev); -if (dev->priv_flags &IFF_SLAVE ) { +if (dev->flags &IFF_SLAVE ) {if (dev->npinfo) {struct net_device *bond_dev = dev->master;struct sk_buff *skb;
Greg KH
maintainerPATCH 30/73 net_sched: Bug in netem reordering
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hagen Paul Pfeifer <[email protected]>
[ Upstream commit eb10192447370f19a215a8c2749332afa1199d46 ]
Not now, but it looks you are correct. q->qdisc is NULL until another additional qdisc is attached (beside tfifo). See 50612537e9ab2969312. The following patch should work.
From: Hagen Paul Pfeifer <[email protected]>
netem: catch NULL pointer by updating the real qdisc statistic
--- net/sched/sch_netem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/sched/sch_netem.c +2 -2
@@ -381,8 +381,8 @@ static int netem_enqueue(struct sk_buff q->counter =0 ;__skb_queue_head (&q->qdisc->q, skb); - q->qdisc->qstats.backlog +=qdisc_pkt_len (skb); - q->qdisc->qstats.requeues++; + sch->qstats.backlog +=qdisc_pkt_len (skb); + sch->qstats.requeues++; ret =NET_XMIT_SUCCESS ; }
Greg KH
maintainerPATCH 31/73 via-velocity: S3 resume fix.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hagen Paul Pfeifer <[email protected]>
[ Upstream commit b530b1930bbd9d005345133f0ff0c556d2a52b19 ]
Initially diagnosed on Ubuntu 11.04 with kernel 2.6.38.
velocity_close is not called during a suspend / resume cycle in this driver and it has no business playing directly with power states.
--- drivers/net/via-velocity.c | 3 --- 1 file changed, 3 deletions(-)
drivers/net/via-velocity.c +0 -3
@@ -2513,9 +2513,6 @@ static int velocity_close(struct net_devif (dev->irq !=0 )free_irq (dev->irq, dev); -/* Power down the chip */ -pci_set_power_state (vptr->pdev, PCI_D3hot); -velocity_free_rings (vptr); vptr->flags &= (~VELOCITY_FLAGS_OPENED );
Greg KH
maintainerPATCH 32/73 tcp_v4_send_reset: binding oif to iif in no sock case
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shawn Lu <[email protected]>
[ Upstream commit e2446eaab5585555a38ea0df4e01ff313dbb4ac9 ]
Binding RST packet outgoing interface to incoming interface for tcp v4 when there is no socket associate with it. when sk is not NULL, using sk->sk_bound_dev_if instead. (suggested by Eric Dumazet).
This has few benefits:
1. tcp_v6_send_reset already did that.
2. This helps tcp connect with SO_BINDTODEVICE set. When connection is lost, we still able to sending out RST using same interface.
3. we are sending reply, it is most likely to be succeed if iif is used
--- net/ipv4/tcp_ipv4.c | 5 +++++ 1 file changed, 5 insertions(+)
net/ipv4/tcp_ipv4.c +5 -0
@@ -650,6 +650,11 @@ static void tcp_v4_send_reset(struct soc arg.iov[0].iov_len, IPPROTO_TCP, 0); arg.csumoffset = offsetof(struct tcphdr , check) /2 ; arg.flags = (sk &&inet_sk (sk)->transparent) ?IP_REPLY_ARG_NOSRCCHECK :0 ; +/* When socket is gone, all binding information is lost. +* routing might fail in this case. using iif for oif to +* make sure we can deliver it +*/ + arg.bound_dev_if = sk ? sk->sk_bound_dev_if :inet_iif (skb); net =dev_net (skb_dst (skb)->dev); ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr,
Greg KH
maintainerPATCH 33/73 tcp: allow tcp_sacktag_one() to tag ranges not aligned with skbs
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Neal Cardwell <[email protected]>
[ Upstream commit cc9a672ee522d4805495b98680f4a3db5d0a0af9 ]
This commit allows callers of tcp_sacktag_one() to pass in sequence ranges that do not align with skb boundaries, as tcp_shifted_skb() needs to do in an upcoming fix in this patch series.
In fact, now tcp_sacktag_one() does not need to depend on an input skb at all, which makes its semantics and dependencies more clear.
--- net/ipv4/tcp_input.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-)
net/ipv4/tcp_input.c +22 -14
@@ -1289,25 +1289,26 @@ static int tcp_match_skb_to_sack(structreturn in_sack; } -static u8 tcp_sacktag_one (struct sk_buff *skb,struct sock *sk, -struct tcp_sacktag_state *state, +/* Mark the given newly-SACKed range as such, adjusting counters and hints. */ +static u8 tcp_sacktag_one (struct sock *sk, +struct tcp_sacktag_state *state,u8 sacked, +u32 start_seq,u32 end_seq,int dup_sack,int pcount) {struct tcp_sock *tp =tcp_sk (sk); -u8 sacked =TCP_SKB_CB (skb)->sacked;int fack_count = state->fack_count;/* Account D-SACK for retransmitted packet. */ if (dup_sack && (sacked &TCPCB_RETRANS )) {if (tp->undo_marker && tp->undo_retrans && -after (TCP_SKB_CB (skb)->end_seq, tp->undo_marker)) +after (end_seq, tp->undo_marker)) tp->undo_retrans--;if (sacked &TCPCB_SACKED_ACKED ) state->reord =min (fack_count, state->reord); }/* Nothing to do; acked frame is about to be dropped (was ACKed). */ -if (!after (TCP_SKB_CB (skb)->end_seq, tp->snd_una)) +if (!after (end_seq, tp->snd_una))return sacked;if (!(sacked &TCPCB_SACKED_ACKED )) {
@@ -1326,13 +1327,13 @@ static u8 tcp_sacktag_one(struct sk_buff/* New sack for not retransmitted frame, * which was in hole. It is reordering. */ -if (before (TCP_SKB_CB (skb)->seq, +if (before (start_seq,tcp_highest_sack_seq (tp))) state->reord =min (fack_count, state->reord);/* SACK enhanced F-RTO (RFC4138; Appendix B) */ -if (!after (TCP_SKB_CB (skb)->end_seq, tp->frto_highmark)) +if (!after (end_seq, tp->frto_highmark)) state->flag |=FLAG_ONLY_ORIG_SACKED ; }
@@ -1350,8 +1351,7 @@ static u8 tcp_sacktag_one(struct sk_buff/* Lost marker hint past SACKed? Tweak RFC3517 cnt */ if (!tcp_is_fack (tp) && (tp->lost_skb_hint !=NULL ) && -before (TCP_SKB_CB (skb)->seq, -TCP_SKB_CB (tp->lost_skb_hint)->seq)) +before (start_seq,TCP_SKB_CB (tp->lost_skb_hint)->seq)) tp->lost_cnt_hint += pcount;if (fack_count > tp->fackets_out)
@@ -1407,7 +1407,11 @@ static int tcp_shifted_skb(struct sock * }/* We discard results */ -tcp_sacktag_one (skb, sk, state, dup_sack, pcount); +tcp_sacktag_one (sk, state, +TCP_SKB_CB (skb)->sacked, +TCP_SKB_CB (skb)->seq, +TCP_SKB_CB (skb)->end_seq, + dup_sack, pcount);/* Difference in this won't matter, both ACKed by the same cumul. ACK */ TCP_SKB_CB (prev)->sacked |= (TCP_SKB_CB (skb)->sacked &TCPCB_EVER_RETRANS );
@@ -1646,10 +1650,14 @@ static struct sk_buff *tcp_sacktag_walk(break ;if (in_sack) { -TCP_SKB_CB (skb)->sacked =tcp_sacktag_one (skb, sk, - state, - dup_sack, -tcp_skb_pcount (skb)); +TCP_SKB_CB (skb)->sacked = +tcp_sacktag_one (sk, + state, +TCP_SKB_CB (skb)->sacked, +TCP_SKB_CB (skb)->seq, +TCP_SKB_CB (skb)->end_seq, + dup_sack, +tcp_skb_pcount (skb));if (!before (TCP_SKB_CB (skb)->seq,tcp_highest_sack_seq (tp)))
Greg KH
maintainerPATCH 34/73 tcp: fix range tcp_shifted_skb() passes to tcp_sacktag_one()
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Neal Cardwell <[email protected]>
[ Upstream commit daef52bab1fd26e24e8e9578f8fb33ba1d0cb412 ]
Fix the newly-SACKed range to be the range of newly-shifted bytes.
Previously - since 832d11c5cd076abc0aa1eaf7be96c81d1a59ce41 - tcp_shifted_skb() incorrectly called tcp_sacktag_one() with the start and end sequence numbers of the skb it passes in set to the range just beyond the range that is newly-SACKed.
This commit also removes a special-case adjustment to lost_cnt_hint in tcp_shifted_skb() since the pre-existing adjustment of lost_cnt_hint in tcp_sacktag_one() now properly handles this things now that the correct start sequence number is passed in.
--- net/ipv4/tcp_input.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
net/ipv4/tcp_input.c +10 -9
@@ -1370,6 +1370,9 @@ static u8 tcp_sacktag_one(struct sock *sreturn sacked; } +/* Shift newly-SACKed bytes from this skb to the immediately previous +* already-SACKed sk_buff. Mark the newly-SACKed bytes as such. +*/ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, struct tcp_sacktag_state *state, unsigned int pcount, int shifted, int mss,
@@ -1377,12 +1380,11 @@ static int tcp_shifted_skb(struct sock * {struct tcp_sock *tp =tcp_sk (sk);struct sk_buff *prev =tcp_write_queue_prev (sk, skb); +u32 start_seq =TCP_SKB_CB (skb)->seq;/* start of newly-SACKed */ +u32 end_seq = start_seq + shifted;/* end of newly-SACKed */ BUG_ON (!pcount); -if (skb == tp->lost_skb_hint) - tp->lost_cnt_hint += pcount; -TCP_SKB_CB (prev)->end_seq += shifted;TCP_SKB_CB (skb)->seq += shifted;
@@ -1406,12 +1408,11 @@ static int tcp_shifted_skb(struct sock *skb_shinfo (skb)->gso_type =0 ; } -/* We discard results */ -tcp_sacktag_one (sk, state, -TCP_SKB_CB (skb)->sacked, -TCP_SKB_CB (skb)->seq, -TCP_SKB_CB (skb)->end_seq, - dup_sack, pcount); +/* Adjust counters and hints for the newly sacked sequence range but +* discard the return value since prev is already marked. +*/ +tcp_sacktag_one (sk, state,TCP_SKB_CB (skb)->sacked, + start_seq, end_seq, dup_sack, pcount);/* Difference in this won't matter, both ACKed by the same cumul. ACK */ TCP_SKB_CB (prev)->sacked |= (TCP_SKB_CB (skb)->sacked &TCPCB_EVER_RETRANS );
Greg KH
maintainerPATCH 35/73 tcp: fix tcp_shifted_skb() adjustment of lost_cnt_hint for FACK
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Neal Cardwell <[email protected]>
[ Upstream commit 0af2a0d0576205dda778d25c6c344fc6508fc81d ]
This commit ensures that lost_cnt_hint is correctly updated in tcp_shifted_skb() for FACK TCP senders. The lost_cnt_hint adjustment in tcp_sacktag_one() only applies to non-FACK senders, so FACK senders need their own adjustment.
This applies the spirit of 1e5289e121372a3494402b1b131b41bfe1cf9b7f - except now that the sequence range passed into tcp_sacktag_one() is correct we need only have a special case adjustment for FACK.
--- net/ipv4/tcp_input.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv4/tcp_input.c +4 -0
@@ -1385,6 +1385,10 @@ static int tcp_shifted_skb(struct sock *BUG_ON (!pcount); +/* Adjust hint for FACK. Non-FACK is handled in tcp_sacktag_one(). */ +if (tcp_is_fack (tp) && (skb == tp->lost_skb_hint)) + tp->lost_cnt_hint += pcount; +TCP_SKB_CB (prev)->end_seq += shifted;TCP_SKB_CB (skb)->seq += shifted;
Greg KH
maintainerPATCH 36/73 route: fix ICMP redirect validation
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Flavio Leitner <[email protected]>
[ Upstream commit 7cc9150ebe8ec06cafea9f1c10d92ddacf88d8ae ]
The commit f39925dbde7788cfb96419c0f092b086aa325c0f (ipv4: Cache learned redirect information in inetpeer.) removed some ICMP packet validations which are required by RFC 1122, section 3.2.2.2:
...
A Redirect message SHOULD be silently discarded if the new gateway address it specifies is not on the same connected (sub-) net through which the Redirect arrived [INTRO:2, Appendix A], or if the source of the Redirect is not the current first-hop gateway for the specified destination (see Section 3.3.1).
--- net/ipv4/route.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-)
net/ipv4/route.c +33 -7
@@ -1373,7 +1373,12 @@ static void rt_del(unsigned hash, structvoid ip_rt_redirect (__be32 old_gw,__be32 daddr,__be32 new_gw,__be32 saddr,struct net_device *dev) { +int s, i;struct in_device *in_dev =__in_dev_get_rcu (dev); +struct rtable *rt; +__be32 skeys[2 ] = { saddr,0 }; +int ikeys[2 ] = { dev->ifindex,0 }; +struct flowi4 fl4;struct inet_peer *peer;struct net *net;
@@ -1396,13 +1401,34 @@ void ip_rt_redirect(__be32 old_gw, __be3 goto reject_redirect; } - peer =inet_getpeer_v4 (daddr,1 ); -if (peer) { - peer->redirect_learned.a4 = new_gw; - -inet_putpeer (peer); - -atomic_inc (&__rt_peer_genid); +memset (&fl4,0 ,sizeof (fl4)); + fl4.daddr = daddr; +for (s =0 ; s <2 ; s++) { +for (i =0 ; i <2 ; i++) { + fl4.flowi4_oif = ikeys[i]; + fl4.saddr = skeys[s]; + rt =__ip_route_output_key (net, &fl4); +if (IS_ERR (rt)) +continue ; + +if (rt->dst.error || rt->dst.dev != dev || + rt->rt_gateway != old_gw) { +ip_rt_put (rt); +continue ; + } + +if (!rt->peer) +rt_bind_peer (rt, rt->rt_dst,1 ); + + peer = rt->peer; +if (peer) { + peer->redirect_learned.a4 = new_gw; +atomic_inc (&__rt_peer_genid); + } + +ip_rt_put (rt); +return ; + } }return ;
Greg KH
maintainerPATCH 37/73 ipv4: fix redirect handling
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 9cc20b268a5a14f5e57b8ad405a83513ab0d78dc ]
commit f39925dbde77 (ipv4: Cache learned redirect information in inetpeer.) introduced a regression in ICMP redirect handling.
It assumed ipv4_dst_check() would be called because all possible routes were attached to the inetpeer we modify in ip_rt_redirect(), but thats not true.
commit 7cc9150ebe (route: fix ICMP redirect validation) tried to fix this but solution was not complete. (It fixed only one route)
So we must lookup existing routes (including different TOS values) and call check_peer_redir() on them.
--- net/ipv4/route.c | 113 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 60 insertions(+), 53 deletions(-)
net/ipv4/route.c +60 -53
@@ -1369,16 +1369,41 @@ static void rt_del(unsigned hash, structspin_unlock_bh (rt_hash_lock_addr (hash)); } +static int check_peer_redir (struct dst_entry *dst,struct inet_peer *peer) +{ +struct rtable *rt = (struct rtable *) dst; +__be32 orig_gw = rt->rt_gateway; +struct neighbour *n, *old_n; + +dst_confirm (&rt->dst); + + rt->rt_gateway = peer->redirect_learned.a4; + n =__arp_bind_neighbour (&rt->dst, rt->rt_gateway); +if (IS_ERR (n)) +return PTR_ERR (n); + old_n =xchg (&rt->dst._neighbour, n); +if (old_n) +neigh_release (old_n); +if (!n || !(n->nud_state &NUD_VALID )) { +if (n) +neigh_event_send (n,NULL ); + rt->rt_gateway = orig_gw; +return -EAGAIN ; + }else { + rt->rt_flags |=RTCF_REDIRECTED ; +call_netevent_notifiers (NETEVENT_NEIGH_UPDATE , n); + } +return 0 ; +} +/* called in rcu_read_lock() section */ void ip_rt_redirect (__be32 old_gw,__be32 daddr,__be32 new_gw,__be32 saddr,struct net_device *dev) {int s, i;struct in_device *in_dev =__in_dev_get_rcu (dev); -struct rtable *rt;__be32 skeys[2 ] = { saddr,0 };int ikeys[2 ] = { dev->ifindex,0 }; -struct flowi4 fl4;struct inet_peer *peer;struct net *net;
@@ -1401,33 +1426,42 @@ void ip_rt_redirect(__be32 old_gw, __be3 goto reject_redirect; } -memset (&fl4,0 ,sizeof (fl4)); - fl4.daddr = daddr;for (s =0 ; s <2 ; s++) {for (i =0 ; i <2 ; i++) { - fl4.flowi4_oif = ikeys[i]; - fl4.saddr = skeys[s]; - rt =__ip_route_output_key (net, &fl4); -if (IS_ERR (rt)) -continue ; - -if (rt->dst.error || rt->dst.dev != dev || - rt->rt_gateway != old_gw) { -ip_rt_put (rt); -continue ; - } - -if (!rt->peer) -rt_bind_peer (rt, rt->rt_dst,1 ); - - peer = rt->peer; -if (peer) { - peer->redirect_learned.a4 = new_gw; -atomic_inc (&__rt_peer_genid); +unsigned int hash; +struct rtable __rcu **rthp; +struct rtable *rt; + + hash =rt_hash (daddr, skeys[s], ikeys[i],rt_genid (net)); + + rthp = &rt_hash_table[hash].chain; + +while ((rt =rcu_dereference (*rthp)) !=NULL ) { + rthp = &rt->dst.rt_next; + +if (rt->rt_key_dst != daddr || + rt->rt_key_src != skeys[s] || + rt->rt_oif != ikeys[i] || +rt_is_input_route (rt) || +rt_is_expired (rt) || + !net_eq (dev_net (rt->dst.dev), net) || + rt->dst.error || + rt->dst.dev != dev || + rt->rt_gateway != old_gw) +continue ; + +if (!rt->peer) +rt_bind_peer (rt, rt->rt_dst,1 ); + + peer = rt->peer; +if (peer) { +if (peer->redirect_learned.a4 != new_gw) { + peer->redirect_learned.a4 = new_gw; +atomic_inc (&__rt_peer_genid); + } +check_peer_redir (&rt->dst, peer); + } } - -ip_rt_put (rt); -return ; } }return ;
@@ -1715,33 +1749,6 @@ static void ip_rt_update_pmtu(struct dst } } -static int check_peer_redir (struct dst_entry *dst,struct inet_peer *peer) -{ -struct rtable *rt = (struct rtable *) dst; -__be32 orig_gw = rt->rt_gateway; -struct neighbour *n, *old_n; - -dst_confirm (&rt->dst); - - rt->rt_gateway = peer->redirect_learned.a4; - n =__arp_bind_neighbour (&rt->dst, rt->rt_gateway); -if (IS_ERR (n)) -return PTR_ERR (n); - old_n =xchg (&rt->dst._neighbour, n); -if (old_n) -neigh_release (old_n); -if (!n || !(n->nud_state &NUD_VALID )) { -if (n) -neigh_event_send (n,NULL ); - rt->rt_gateway = orig_gw; -return -EAGAIN ; - }else { - rt->rt_flags |=RTCF_REDIRECTED ; -call_netevent_notifiers (NETEVENT_NEIGH_UPDATE , n); - } -return 0 ; -} -static struct dst_entry *ipv4_dst_check (struct dst_entry *dst,u32 cookie) {struct rtable *rt = (struct rtable *) dst;
Greg KH
maintainerPATCH 38/73 USB: Added Kamstrup VID/PIDs to cp210x serial driver.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bruno Thomsen <[email protected]>
commit c6c1e4491dc8d1ed2509fa6aacffa7f34614fc38 upstream.
--- drivers/usb/serial/cp210x.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/serial/cp210x.c +2 -0
@@ -136,6 +136,8 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */ + { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */ { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
Greg KH
maintainerPATCH 39/73 USB: option: cleanup zte 3g-dongles pid in option.c
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rui li <[email protected]>
commit b9e44fe5ecda4158c22bc1ea4bffa378a4f83f65 upstream.
1. Remove all old mass-storage ids's pid:
0x0026,0x0053,0x0098,0x0099,0x0149,0x0150,0x0160;
2. As the pid from 0x1401 to 0x1510 which have not surely assigned to use for serial-port or mass-storage port,so i think it should be removed now, and will re-add after it have assigned in future;
3. sort the pid to WCDMA and CDMA.
--- drivers/usb/serial/option.c | 143 ++++---------------------------------------- 1 file changed, 13 insertions(+), 130 deletions(-)
drivers/usb/serial/option.c +13 -130
@@ -788,7 +788,6 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff),
@@ -803,7 +802,6 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, -/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
@@ -828,7 +826,6 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, -/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -836,7 +833,6 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff),
@@ -846,7 +842,6 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
@@ -865,8 +860,6 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0098, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0099, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
@@ -887,28 +880,18 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1083,127 +1066,27 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1403, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1404, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1405, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1406, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1407, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1408, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1409, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1410, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1411, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1412, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1413, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1414, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1415, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1416, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1417, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1418, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1419, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1420, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1421, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1422, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1423, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1427, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1429, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1430, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1431, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1432, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1433, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1434, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1435, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1436, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1437, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1438, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1439, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1440, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1441, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1442, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1443, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1444, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1445, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1446, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1447, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1448, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1449, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1450, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1451, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1452, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1453, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1454, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1455, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1456, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1457, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1458, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1459, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1460, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1461, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1462, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1463, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1464, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1465, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1466, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1467, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1468, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1469, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1470, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1471, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1472, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1473, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1474, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1475, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1476, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1477, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1478, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1479, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1480, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1482, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1483, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1484, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1485, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1486, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1487, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1488, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1489, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1490, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1491, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1492, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1493, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1494, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1495, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1496, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1497, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1498, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1499, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1500, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1501, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1502, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1503, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1504, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1505, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1506, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1507, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1508, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1509, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1510, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, + 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, - 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
Greg KH
maintainerPATCH 40/73 USB: Serial: ti_usb_3410_5052: Add Abbot Diabetes Care cable id
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Lunn <[email protected]>
commit 7fd25702ba616d9ba56e2a625472f29e5aff25ee upstream.
This USB-serial cable with mini stereo jack enumerates as:
Bus 001 Device 004: ID 1a61:3410 Abbott Diabetes Care
It is a TI3410 inside.
--- drivers/usb/serial/ti_usb_3410_5052.c | 6 ++++-- drivers/usb/serial/ti_usb_3410_5052.h | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-)
drivers/usb/serial/ti_usb_3410_5052.c +4 -2
@@ -165,7 +165,7 @@ static unsigned int product_5052_count;/* the array dimension is the number of default entries plus */ /* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */ /* null entry */ -static struct usb_device_id ti_id_table_3410[13 +TI_EXTRA_VID_PID_COUNT +1 ] = { +static struct usb_device_id ti_id_table_3410[14 +TI_EXTRA_VID_PID_COUNT +1 ] = { {USB_DEVICE (TI_VENDOR_ID ,TI_3410_PRODUCT_ID ) }, {USB_DEVICE (TI_VENDOR_ID ,TI_3410_EZ430_ID ) }, {USB_DEVICE (MTS_VENDOR_ID ,MTS_GSM_NO_FW_PRODUCT_ID ) },
@@ -179,6 +179,7 @@ static struct usb_device_id ti_id_table_ { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, }; static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -188,7 +189,7 @@ static struct usb_device_id ti_id_table_ { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, }; -static struct usb_device_id ti_id_table_combined[17 +2 *TI_EXTRA_VID_PID_COUNT +1 ] = { +static struct usb_device_id ti_id_table_combined[18 +2 *TI_EXTRA_VID_PID_COUNT +1 ] = { {USB_DEVICE (TI_VENDOR_ID ,TI_3410_PRODUCT_ID ) }, {USB_DEVICE (TI_VENDOR_ID ,TI_3410_EZ430_ID ) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -206,6 +207,7 @@ static struct usb_device_id ti_id_table_ { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, { } };
drivers/usb/serial/ti_usb_3410_5052.h +4 -0
@@ -49,6 +49,10 @@#define MTS_MT9234ZBA_PRODUCT_ID 0xF115#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319 +/* Abbott Diabetics vendor and product ids */ +#define ABBOTT_VENDOR_ID 0x1a61 +#define ABBOTT_PRODUCT_ID 0x3410 +/* Commands */ #define TI_GET_VERSION 0x01#define TI_GET_PORT_STATUS 0x02
Greg KH
maintainerPATCH 41/73 USB: Remove duplicate USB 3.0 hub feature #defines.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sarah Sharp <[email protected]>
commit d9f5343e35d9138432657202afa8e3ddb2ade360 upstream.
Somehow we ended up with duplicate hub feature #defines in ch11.h. Tatyana Brokhman first created the USB 3.0 hub feature macros in 2.6.38 with commit 0eadcc09203349b11ca477ec367079b23d32ab91 "usb: USB3.0 ch11 definitions". In 2.6.39, I modified a patch from John Youn that added similar macros in a different place in the same file, and committed dbe79bbe9dcb22cb3651c46f18943477141ca452 "USB 3.0 Hub Changes".
Some of the #defines used different names for the same values. Others used exactly the same names with the same values, like these gems:
#define USB_PORT_FEAT_BH_PORT_RESET 28
...
#define USB_PORT_FEAT_BH_PORT_RESET 28
According to my very geeky husband (who looked it up in the C99 spec), it is allowed to have object-like macros with duplicate names as long as the replacement list is exactly the same. However, he recalled that some compilers will give warnings when they find duplicate macros. It's probably best to remove the duplicates in the stable tree, so that the code compiles for everyone.
The macros are now fixed to move the feature requests that are specific to USB 3.0 hubs into a new section (out of the USB 2.0 hub feature section), and use the most common macro name.
This patch should be backported to 2.6.39.
--- include/linux/usb/ch11.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
include/linux/usb/ch11.h +2 -8
@@ -62,12 +62,6 @@#define USB_PORT_FEAT_TEST 21#define USB_PORT_FEAT_INDICATOR 22#define USB_PORT_FEAT_C_PORT_L1 23 -#define USB_PORT_FEAT_C_PORT_LINK_STATE 25 -#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26 -#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK 27 -#define USB_PORT_FEAT_BH_PORT_RESET 28 -#define USB_PORT_FEAT_C_BH_PORT_RESET 29 -#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30/* * Port feature selectors added by USB 3.0 spec.
@@ -76,8 +70,8 @@#define USB_PORT_FEAT_LINK_STATE 5#define USB_PORT_FEAT_U1_TIMEOUT 23#define USB_PORT_FEAT_U2_TIMEOUT 24 -#define USB_PORT_FEAT_C_LINK_STATE 25 -#define USB_PORT_FEAT_C_CONFIG_ERR 26 +#define USB_PORT_FEAT_C_PORT_LINK_STATE 25 +#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26#define USB_PORT_FEAT_REMOTE_WAKE_MASK 27#define USB_PORT_FEAT_BH_PORT_RESET 28#define USB_PORT_FEAT_C_BH_PORT_RESET 29
Greg KH
maintainerPATCH 42/73 USB: Fix handoff when BIOS disables host PCI device.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sarah Sharp <[email protected]>
commit cab928ee1f221c9cc48d6615070fefe2e444384a upstream.
On some systems with an Intel Panther Point xHCI host controller, the BIOS disables the xHCI PCI device during boot, and switches the xHCI ports over to EHCI. This allows the BIOS to access USB devices without having xHCI support.
The downside is that the xHCI BIOS handoff mechanism will fail because memory mapped I/O is not enabled for the disabled PCI device. Jesse Barnes says this is expected behavior. The PCI core will enable BARs before quirks run, but it will leave it in an undefined state, and it may not have memory mapped I/O enabled.
Make the generic USB quirk handler call pci_enable_device() to re-enable MMIO, and call pci_disable_device() once the host-specific BIOS handoff is finished. This will balance the ref counts in the PCI core. When the PCI probe function is called, usb_hcd_pci_probe() will call pci_enable_device() again.
This should be back ported to kernels as old as 2.6.31. That was the first kernel with xHCI support, and no one has complained about BIOS handoffs failing due to memory mapped I/O being disabled on other hosts (EHCI, UHCI, or OHCI).
--- drivers/usb/host/pci-quirks.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/usb/host/pci-quirks.c +11 -0
@@ -871,7 +871,17 @@ static void __devinit quirk_usb_early_ha*/ if (pdev->vendor ==0x184e )/* vendor Netlogic */ return ; +if (pdev->class !=PCI_CLASS_SERIAL_USB_UHCI && + pdev->class !=PCI_CLASS_SERIAL_USB_OHCI && + pdev->class !=PCI_CLASS_SERIAL_USB_EHCI && + pdev->class !=PCI_CLASS_SERIAL_USB_XHCI ) +return ; +if (pci_enable_device (pdev) <0 ) { +dev_warn (&pdev->dev,"Can't enable PCI device, " +"BIOS handoff failed.\n" ); +return ; + }if (pdev->class ==PCI_CLASS_SERIAL_USB_UHCI )quirk_usb_handoff_uhci (pdev);else if (pdev->class ==PCI_CLASS_SERIAL_USB_OHCI )
@@ -880,5 +890,6 @@ static void __devinit quirk_usb_early_haquirk_usb_disable_ehci (pdev); else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) quirk_usb_handoff_xhci(pdev); +pci_disable_device (pdev ); }DECLARE_PCI_FIXUP_FINAL (PCI_ANY_ID ,PCI_ANY_ID , quirk_usb_early_handoff);
Greg KH
maintainerPATCH 43/73 xhci: Fix oops caused by more USB2 ports than USB3 ports.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sarah Sharp <[email protected]>
commit 3278a55a1aebe2bbd47fbb5196209e5326a88b56 upstream.
The code to set the device removable bits in the USB 2.0 roothub descriptor was accidentally looking at the USB 3.0 port registers instead of the USB 2.0 registers. This can cause an oops if there are more USB 2.0 registers than USB 3.0 registers.
This should be backported to kernels as old as 2.6.39, that contain the commit 4bbb0ace9a3de8392527e3c87926309d541d3b00 "xhci: Return a USB 3.0 hub descriptor for USB3 roothub."
--- drivers/usb/host/xhci-hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-hub.c +1 -1
@@ -75,7 +75,7 @@ static void xhci_usb2_hub_descriptor(str*/ memset (port_removable,0 ,sizeof (port_removable));for (i =0 ; i < ports; i++) { - portsc =xhci_readl (xhci, xhci->usb3_ports[i]); + portsc =xhci_readl (xhci, xhci->usb2_ports[i]);/* If a device is removable, PORTSC reports a 0, same as in the * hub descriptor DeviceRemovable bits. */
Greg KH
maintainerPATCH 44/73 xhci: Fix encoding for HS bulk/control NAK rate.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sarah Sharp <[email protected]>
commit 340a3504fd39dad753ba908fb6f894ee81fc3ae2 upstream.
The xHCI 0.96 spec says that HS bulk and control endpoint NAK rate must be encoded as an exponent of two number of microframes. The endpoint descriptor has the NAK rate encoded in number of microframes. We were just copying the value from the endpoint descriptor into the endpoint context interval field, which was not correct. This lead to the VIA host rejecting the add of a bulk OUT endpoint from any USB 2.0 mass storage device.
The fix is to use the correct encoding. Refactor the code to convert number of frames to an exponential number of microframes, and make sure we convert the number of microframes in HS bulk and control endpoints to an exponent.
This should be back ported to kernels as old as 2.6.31, that contain the commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in xhci_get_endpoint_interval"
--- drivers/usb/host/xhci-mem.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-)
drivers/usb/host/xhci-mem.c +24 -8
@@ -1002,26 +1002,42 @@ static unsigned int xhci_parse_exponent_ }/* -* Convert bInterval expressed in frames (in 1-255 range) to exponent of +* Convert bInterval expressed in microframes (in 1-255 range) to exponent of * microframes, rounded down to nearest power of 2. */ -static unsigned int xhci_parse_frame_interval (struct usb_device *udev, -struct usb_host_endpoint *ep) +static unsigned int xhci_microframes_to_exponent (struct usb_device *udev, +struct usb_host_endpoint *ep,unsigned int desc_interval, +unsigned int min_exponent,unsigned int max_exponent) {unsigned int interval; - interval =fls (8 * ep->desc.bInterval) -1 ; - interval =clamp_val (interval,3 ,10 ); -if ((1 << interval) !=8 * ep->desc.bInterval) + interval =fls (desc_interval) -1 ; + interval =clamp_val (interval, min_exponent, max_exponent); +if ((1 << interval) != desc_interval)dev_warn (&udev->dev,"ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n" , ep->desc.bEndpointAddress,1 << interval, -8 * ep->desc.bInterval); + desc_interval);return interval; } +static unsigned int xhci_parse_microframe_interval (struct usb_device *udev, +struct usb_host_endpoint *ep) +{ +return xhci_microframes_to_exponent (udev, ep, + ep->desc.bInterval,0 ,15 ); +} + + +static unsigned int xhci_parse_frame_interval (struct usb_device *udev, +struct usb_host_endpoint *ep) +{ +return xhci_microframes_to_exponent (udev, ep, + ep->desc.bInterval *8 ,3 ,10 ); +} +/* Return the polling or NAK interval. * * The polling interval is expressed in "microframes". If xHCI's Interval field
@@ -1040,7 +1056,7 @@ static unsigned int xhci_get_endpoint_in/* Max NAK rate */ if (usb_endpoint_xfer_control (&ep->desc) ||usb_endpoint_xfer_bulk (&ep->desc)) { - interval = ep->desc.bInterval; + interval =xhci_parse_microframe_interval (udev, ep);break ; }/* Fall through - SS and HS isoc/int have same decoding */
Greg KH
maintainerPATCH 45/73 USB: Set hub depth after USB3 hub reset
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Elric Fu <[email protected]>
commit a45aa3b30583e7d54e7cf4fbcd0aa699348a6e5c upstream.
The superspeed device attached to a USB 3.0 hub(such as VIA's) doesn't respond the address device command after resume. The root cause is the superspeed hub will miss the Hub Depth value that is used as an offset into the route string to locate the bits it uses to determine the downstream port number after reset, and all packets can't be routed to the device attached to the superspeed hub.
Hub driver sends a Set Hub Depth request to the superspeed hub except for USB 3.0 root hub when the hub is initialized and doesn't send the request again after reset due to the resume process. So moving the code that sends the Set Hub Depth request to the superspeed hub from hub_configure() to hub_activate() is to cover those situations include initialization and reset.
The patch should be backported to kernels as old as 2.6.39.
--- drivers/usb/core/hub.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-)
drivers/usb/core/hub.c +17 -13
@@ -705,10 +705,26 @@ static void hub_activate(struct usb_hubif (type ==HUB_INIT3 ) goto init3; -/* After a resume, port power should still be on. +/* The superspeed hub except for root hub has to use Hub Depth +* value as an offset into the route string to locate the bits +* it uses to determine the downstream port number. So hub driver +* should send a set hub depth request to superspeed hub after +* the superspeed hub is set configuration in initialization or +* reset procedure. +* +* After a resume, port power should still be on. * For any other type of activation, turn it on. */ if (type !=HUB_RESUME ) { +if (hdev->parent &&hub_is_superspeed (hdev)) { + ret =usb_control_msg (hdev,usb_sndctrlpipe (hdev,0 ), +HUB_SET_DEPTH ,USB_RT_HUB , + hdev->level -1 ,0 ,NULL ,0 , +USB_CTRL_SET_TIMEOUT ); +if (ret <0 ) +dev_err (hub->intfdev, +"set hub depth failed\n" ); + }/* Speed up system boot by using a delayed_work for the * hub's initial power-up delays. This is pretty awkward
@@ -987,18 +1003,6 @@ static int hub_configure(struct usb_hub goto fail; } -if (hub_is_superspeed (hdev) && (hdev->parent !=NULL )) { - ret =usb_control_msg (hdev,usb_sndctrlpipe (hdev,0 ), -HUB_SET_DEPTH ,USB_RT_HUB , - hdev->level -1 ,0 ,NULL ,0 , -USB_CTRL_SET_TIMEOUT ); - -if (ret <0 ) { - message ="can't set hub depth" ; - goto fail; - } - } -/* Request the entire hub descriptor. * hub->descriptor can handle USB_MAXCHILDREN ports, * but the hub can/will return fewer bytes here.
Greg KH
maintainerPATCH 46/73 i387: math_state_restore() isnt called from asm
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit be98c2cdb15ba26148cd2bd58a857d4f7759ed38 upstream.
It was marked asmlinkage for some really old and stale legacy reasons. Fix that and the equally stale comment.
Noticed when debugging the irq_fpu_usable() bugs.
--- arch/x86/include/asm/i387.h | 2 +- arch/x86/kernel/traps.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/include/asm/i387.h +1 -1
@@ -29,7 +29,7 @@ extern unsigned int sig_xstate_size;extern void fpu_init (void );extern void mxcsr_feature_mask_init (void );extern int init_fpu (struct task_struct *child); -extern asmlinkage void math_state_restore(void); +extern void math_state_restore (void );extern void __math_state_restore (void );extern int dump_fpu (struct pt_regs *,struct user_i387_struct *);
arch/x86/kernel/traps.c +3 -3
@@ -745,10 +745,10 @@ void __math_state_restore(void)* Careful.. There are problems with IBM-designed IRQ13 behaviour. * Don't touch unless you *really* know how it works. * -* Must be called with kernel preemption disabled (in this case, -* local interrupts are disabled at the call-site in entry.S). +* Must be called with kernel preemption disabled (eg with local +* local interrupts as in the case of do_device_not_available). */ -asmlinkage void math_state_restore(void) +void math_state_restore (void ) {struct thread_info *thread =current_thread_info ();struct task_struct *tsk = thread->task;
Greg KH
maintainerPATCH 47/73 i387: make irq_fpu_usable() tests more robust
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 5b1cbac37798805c1fee18c8cebe5c0a13975b17 upstream.
Some code - especially the crypto layer - wants to use the x86 FP/MMX/AVX register set in what may be interrupt (typically softirq) context.
That *can* be ok, but the tests for when it was ok were somewhat suspect. We cannot touch the thread-specific status bits either, so we'd better check that we're not going to try to save FP state or anything like that.
Now, it may be that the TS bit is always cleared *before* we set the USEDFPU bit (and only set when we had already cleared the USEDFP before), so the TS bit test may actually have been sufficient, but it certainly was not obviously so.
So this explicitly verifies that we will not touch the TS_USEDFPU bit, and adds a few related sanity-checks. Because it seems that somehow AES-NI is corrupting user FP state. The cause is not clear, and this patch doesn't fix it, but while debugging it I really wanted the code to be more obviously correct and robust.
--- arch/x86/include/asm/i387.h | 54 +++++++++++++++++++++++++++++++++++++------- arch/x86/kernel/traps.c | 1 2 files changed, 47 insertions(+), 8 deletions(-)
arch/x86/include/asm/i387.h +46 -8
@@ -307,9 +307,54 @@ static inline void __clear_fpu(struct ta } } +/* +* Were we in an interrupt that interrupted kernel mode? +* +* We can do a kernel_fpu_begin/end() pair *ONLY* if that +* pair does nothing at all: TS_USEDFPU must be clear (so +* that we don't try to save the FPU state), and TS must +* be set (so that the clts/stts pair does nothing that is +* visible in the interrupted kernel thread). +*/ +static inline bool interrupted_kernel_fpu_idle (void ) +{ +return !(current_thread_info ()->status &TS_USEDFPU ) && + (read_cr0 () &X86_CR0_TS ); +} + +/* +* Were we in user mode (or vm86 mode) when we were +* interrupted? +* +* Doing kernel_fpu_begin/end() is ok if we are running +* in an interrupt context from user mode - we'll just +* save the FPU state as required. +*/ +static inline bool interrupted_user_mode (void ) +{ +struct pt_regs *regs =get_irq_regs (); +return regs &&user_mode_vm (regs); +} + +/* +* Can we use the FPU in kernel mode with the +* whole "kernel_fpu_begin/end()" sequence? +* +* It's always ok in process context (ie "not interrupt") +* but it is sometimes ok even from an irq. +*/ +static inline bool irq_fpu_usable (void ) +{ +return !in_interrupt () || +interrupted_user_mode () || +interrupted_kernel_fpu_idle (); +} +static inline void kernel_fpu_begin (void ) {struct thread_info *me =current_thread_info (); + +WARN_ON_ONCE (!irq_fpu_usable ());preempt_disable ();if (me->status &TS_USEDFPU )__save_init_fpu (me->task);
@@ -323,14 +368,6 @@ static inline void kernel_fpu_end(void)preempt_enable (); } -static inline bool irq_fpu_usable (void ) -{ -struct pt_regs *regs; - -return !in_interrupt () || !(regs =get_irq_regs ()) || \ -user_mode (regs) || (read_cr0 () &X86_CR0_TS ); -} -/* * Some instructions like VIA's padlock instructions generate a spurious * DNA fault but don't modify SSE registers. And these instructions
@@ -367,6 +404,7 @@ static inline void irq_ts_restore(int TS*/ static inline void save_init_fpu (struct task_struct *tsk) { +WARN_ON_ONCE (task_thread_info (tsk)->status &TS_USEDFPU );preempt_disable ();__save_init_fpu (tsk);stts ();
arch/x86/kernel/traps.c +1 -0
@@ -777,6 +777,7 @@ EXPORT_SYMBOL_GPL(math_state_restore); dotraplinkage void __kprobesdo_device_not_available (struct pt_regs *regs,long error_code) { +WARN_ON_ONCE (!user_mode_vm (regs));#ifdef CONFIG_MATH_EMULATION if (read_cr0 () &X86_CR0_EM ) {struct math_emu_info info = { };
Greg KH
maintainerPATCH 48/73 i387: fix sense of sanity check
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit c38e23456278e967f094b08247ffc3711b1029b2 upstream.
The check for save_init_fpu() (introduced in commit 5b1cbac37798: "i387:
make irq_fpu_usable() tests more robust") was the wrong way around, but I hadn't noticed, because my "tests" were bogus: the FPU exceptions are disabled by default, so even doing a divide by zero never actually triggers this code at all unless you do extra work to enable them.
So if anybody did enable them, they'd get one spurious warning.
--- arch/x86/include/asm/i387.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/i387.h +1 -1
@@ -404,7 +404,7 @@ static inline void irq_ts_restore(int TS*/ static inline void save_init_fpu (struct task_struct *tsk) { -WARN_ON_ONCE (task_thread_info (tsk)->status &TS_USEDFPU ); +WARN_ON_ONCE (!(task_thread_info (tsk)->status &TS_USEDFPU ));preempt_disable ();__save_init_fpu (tsk);stts ();
Greg KH
maintainerPATCH 49/73 i387: fix x86-64 preemption-unsafe user stack save/restore
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 15d8791cae75dca27bfda8ecfe87dca9379d6bb0 upstream.
Commit 5b1cbac37798 ("i387: make irq_fpu_usable() tests more robust") added a sanity check to the #NM handler to verify that we never cause the "Device Not Available" exception in kernel mode.
However, that check actually pinpointed a (fundamental) race where we do cause that exception as part of the signal stack FPU state save/restore code.
Because we use the floating point instructions themselves to save and restore state directly from user mode, we cannot do that atomically with testing the TS_USEDFPU bit: the user mode access itself may cause a page fault, which causes a task switch, which saves and restores the FP/MMX state from the kernel buffers.
This kind of "recursive" FP state save is fine per se, but it means that when the signal stack save/restore gets restarted, it will now take the '#NM' exception we originally tried to avoid. With preemption this can happen even without the page fault - but because of the user access, we cannot just disable preemption around the save/restore instruction.
There are various ways to solve this, including using the "enable/disable_page_fault()" helpers to not allow page faults at all during the sequence, and fall back to copying things by hand without the use of the native FP state save/restore instructions.
However, the simplest thing to do is to just allow the #NM from kernel space, but fix the race in setting and clearing CR0.TS that this all
exposed: the TS bit changes and the TS_USEDFPU bit absolutely have to be atomic wrt scheduling, so while the actual state save/restore can be interrupted and restarted, the act of actually clearing/setting CR0.TS and the TS_USEDFPU bit together must not.
Instead of just adding random "preempt_disable/enable()" calls to what is already excessively ugly code, this introduces some helper functions that mostly mirror the "kernel_fpu_begin/end()" functionality, just for the user state instead.
Those helper functions should probably eventually replace the other ad-hoc CR0.TS and TS_USEDFPU tests too, but I'll need to think about it some more: the task switching functionality in particular needs to expose the difference between the 'prev' and 'next' threads, while the new helper functions intentionally were written to only work with 'current'.
--- arch/x86/include/asm/i387.h | 42 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/traps.c | 1 - arch/x86/kernel/xsave.c | 10 +++------- 3 files changed, 45 insertions(+), 8 deletions(-)
arch/x86/include/asm/i387.h +42 -0
@@ -400,6 +400,48 @@ static inline void irq_ts_restore(int TS }/* +* The question "does this thread have fpu access?" +* is slightly racy, since preemption could come in +* and revoke it immediately after the test. +* +* However, even in that very unlikely scenario, +* we can just assume we have FPU access - typically +* to save the FP state - we'll just take a #NM +* fault and get the FPU access back. +* +* The actual user_fpu_begin/end() functions +* need to be preemption-safe, though. +* +* NOTE! user_fpu_end() must be used only after you +* have saved the FP state, and user_fpu_begin() must +* be used only immediately before restoring it. +* These functions do not do any save/restore on +* their own. +*/ +static inline int user_has_fpu (void ) +{ +return current_thread_info ()->status &TS_USEDFPU ; +} + +static inline void user_fpu_end (void ) +{ +preempt_disable (); +current_thread_info ()->status &= ~TS_USEDFPU ; +stts (); +preempt_enable (); +} + +static inline void user_fpu_begin (void ) +{ +preempt_disable (); +if (!user_has_fpu ()) { +clts (); +current_thread_info ()->status |=TS_USEDFPU ; + } +preempt_enable (); +} + +/* * These disable preemption on their own and are safe */ static inline void save_init_fpu (struct task_struct *tsk)
arch/x86/kernel/traps.c +0 -1
@@ -777,7 +777,6 @@ EXPORT_SYMBOL_GPL(math_state_restore); dotraplinkage void __kprobesdo_device_not_available (struct pt_regs *regs,long error_code) { -WARN_ON_ONCE (!user_mode_vm (regs));#ifdef CONFIG_MATH_EMULATION if (read_cr0 () &X86_CR0_EM ) {struct math_emu_info info = { };
arch/x86/kernel/xsave.c +3 -7
@@ -168,7 +168,7 @@ int save_i387_xstate(void __user *buf)if (!used_math ())return 0 ; -if (task_thread_info (tsk)->status &TS_USEDFPU ) { +if (user_has_fpu ()) {if (use_xsave ()) err =xsave_user (buf);else
@@ -176,8 +176,7 @@ int save_i387_xstate(void __user *buf)if (err)return err; -task_thread_info (tsk)->status &= ~TS_USEDFPU ; -stts (); +user_fpu_end (); }else {sanitize_i387_state (tsk); if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
@@ -292,10 +291,7 @@ int restore_i387_xstate(void __user *bufreturn err; } -if (!(task_thread_info (current)->status &TS_USEDFPU )) { -clts (); -task_thread_info (current)->status |=TS_USEDFPU ; - } +user_fpu_begin ();if (use_xsave ()) err =restore_user_xstate (buf);else
Greg KH
maintainerPATCH 50/73 i387: move TS_USEDFPU clearing out of __save_init_fpu and into callers
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit b6c66418dcad0fcf83cd1d0a39482db37bf4fc41 upstream.
Touching TS_USEDFPU without touching CR0.TS is confusing, so don't do it. By moving it into the callers, we always do the TS_USEDFPU next to the CR0.TS accesses in the source code, and it's much easier to see how the two go hand in hand.
--- arch/x86/include/asm/i387.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/x86/include/asm/i387.h +6 -3
@@ -259,7 +259,6 @@ static inline void fpu_save_init(structstatic inline void __save_init_fpu (struct task_struct *tsk) {fpu_save_init (&tsk->thread.fpu); -task_thread_info (tsk)->status &= ~TS_USEDFPU ; }static inline int fpu_fxrstor_checking (struct fpu *fpu)
@@ -290,6 +289,7 @@ static inline void __unlazy_fpu(struct t {if (task_thread_info (tsk)->status &TS_USEDFPU ) {__save_init_fpu (tsk); +task_thread_info (tsk)->status &= ~TS_USEDFPU ;stts (); }else tsk->fpu_counter =0 ;
@@ -356,9 +356,11 @@ static inline void kernel_fpu_begin(voidWARN_ON_ONCE (!irq_fpu_usable ());preempt_disable (); -if (me->status &TS_USEDFPU ) +if (me->status &TS_USEDFPU ) {__save_init_fpu (me->task); -else + me->status &= ~TS_USEDFPU ; +/* We do 'stts()' in kernel_fpu_end() */ + }else clts (); }
@@ -449,6 +451,7 @@ static inline void save_init_fpu(structWARN_ON_ONCE (!(task_thread_info (tsk)->status &TS_USEDFPU ));preempt_disable ();__save_init_fpu (tsk); +task_thread_info (tsk)->status &= ~TS_USEDFPU ;stts ();preempt_enable (); }
Greg KH
maintainerPATCH 51/73 i387: dont ever touch TS_USEDFPU directly, use helper functions
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 6d59d7a9f5b723a7ac1925c136e93ec83c0c3043 upstream.
This creates three helper functions that do the TS_USEDFPU accesses, and makes everybody that used to do it by hand use those helpers instead.
In addition, there's a couple of helper functions for the "change both CR0.TS and TS_USEDFPU at the same time" case, and the places that do that together have been changed to use those. That means that we have fewer random places that open-code this situation.
The intent is partly to clarify the code without actually changing any semantics yet (since we clearly still have some hard to reproduce bug in this area), but also to make it much easier to use another approach entirely to caching the CR0.TS bit for software accesses.
Right now we use a bit in the thread-info 'status' variable (this patch does not change that), but we might want to make it a full field of its own or even make it a per-cpu variable.
--- arch/x86/include/asm/i387.h | 75 ++++++++++++++++++++++++++++++++------------ arch/x86/kernel/traps.c | 2 - arch/x86/kernel/xsave.c | 2 - arch/x86/kvm/vmx.c | 2 - 4 files changed, 58 insertions(+), 23 deletions(-)
arch/x86/include/asm/i387.h +55 -20
@@ -280,6 +280,47 @@ static inline int restore_fpu_checking(s }/* +* Software FPU state helpers. Careful: these need to +* be preemption protection *and* they need to be +* properly paired with the CR0.TS changes! +*/ +static inline int __thread_has_fpu (struct thread_info *ti) +{ +return ti->status &TS_USEDFPU ; +} + +/* Must be paired with an 'stts' after! */ +static inline void __thread_clear_has_fpu (struct thread_info *ti) +{ + ti->status &= ~TS_USEDFPU ; +} + +/* Must be paired with a 'clts' before! */ +static inline void __thread_set_has_fpu (struct thread_info *ti) +{ + ti->status |=TS_USEDFPU ; +} + +/* +* Encapsulate the CR0.TS handling together with the +* software flag. +* +* These generally need preemption protection to work, +* do try to avoid using these on their own. +*/ +static inline void __thread_fpu_end (struct thread_info *ti) +{ +__thread_clear_has_fpu (ti); +stts (); +} + +static inline void __thread_fpu_begin (struct thread_info *ti) +{ +clts (); +__thread_set_has_fpu (ti); +} + +/* * Signal frame handlers... */ extern int save_i387_xstate (void __user *buf);
@@ -287,23 +328,21 @@ extern int restore_i387_xstate(void __usstatic inline void __unlazy_fpu (struct task_struct *tsk) { -if (task_thread_info (tsk)->status &TS_USEDFPU ) { +if (__thread_has_fpu (task_thread_info (tsk))) {__save_init_fpu (tsk); -task_thread_info (tsk)->status &= ~TS_USEDFPU ; -stts (); +__thread_fpu_end (task_thread_info (tsk)); }else tsk->fpu_counter =0 ; }static inline void __clear_fpu (struct task_struct *tsk) { -if (task_thread_info (tsk)->status &TS_USEDFPU ) { +if (__thread_has_fpu (task_thread_info (tsk))) {/* Ignore delayed exceptions from user space */ asmvolatile ("1: fwait\n" "2:\n" _ASM_EXTABLE(1b, 2b)); -task_thread_info (tsk)->status &= ~TS_USEDFPU ; -stts (); +__thread_fpu_end (task_thread_info (tsk)); } }
@@ -311,14 +350,14 @@ static inline void __clear_fpu(struct ta* Were we in an interrupt that interrupted kernel mode? * * We can do a kernel_fpu_begin/end() pair *ONLY* if that -* pair does nothing at all: TS_USEDFPU must be clear (so +* pair does nothing at all: the thread must not have fpu (so * that we don't try to save the FPU state), and TS must * be set (so that the clts/stts pair does nothing that is * visible in the interrupted kernel thread). */ static inline bool interrupted_kernel_fpu_idle (void ) { -return !(current_thread_info ()->status &TS_USEDFPU ) && +return !__thread_has_fpu (current_thread_info ()) && (read_cr0 () &X86_CR0_TS ); }
@@ -356,9 +395,9 @@ static inline void kernel_fpu_begin(voidWARN_ON_ONCE (!irq_fpu_usable ());preempt_disable (); -if (me->status &TS_USEDFPU ) { +if (__thread_has_fpu (me)) {__save_init_fpu (me->task); - me->status &= ~TS_USEDFPU ; +__thread_clear_has_fpu (me);/* We do 'stts()' in kernel_fpu_end() */ }else clts ();
@@ -422,24 +461,21 @@ static inline void irq_ts_restore(int TS*/ static inline int user_has_fpu (void ) { -return current_thread_info ()->status &TS_USEDFPU ; +return __thread_has_fpu (current_thread_info ()); }static inline void user_fpu_end (void ) {preempt_disable (); -current_thread_info ()->status &= ~TS_USEDFPU ; -stts (); +__thread_fpu_end (current_thread_info ());preempt_enable (); }static inline void user_fpu_begin (void ) {preempt_disable (); -if (!user_has_fpu ()) { -clts (); -current_thread_info ()->status |=TS_USEDFPU ; - } +if (!user_has_fpu ()) +__thread_fpu_begin (current_thread_info ());preempt_enable (); }
@@ -448,11 +484,10 @@ static inline void user_fpu_begin(void)*/ static inline void save_init_fpu (struct task_struct *tsk) { -WARN_ON_ONCE (!(task_thread_info (tsk)->status &TS_USEDFPU )); +WARN_ON_ONCE (!__thread_has_fpu (task_thread_info (tsk)));preempt_disable ();__save_init_fpu (tsk); -task_thread_info (tsk)->status &= ~TS_USEDFPU ; -stts (); +__thread_fpu_end (task_thread_info (tsk));preempt_enable (); }
arch/x86/kernel/traps.c +1 -1
@@ -734,7 +734,7 @@ void __math_state_restore(void)return ; } - thread->status |=TS_USEDFPU ;/* So we fnsave on switch_to() */ +__thread_set_has_fpu (thread);/* clts in caller! */ tsk->fpu_counter++; }
arch/x86/kernel/xsave.c +1 -1
@@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_sif (!fx)return ; -BUG_ON (task_thread_info (tsk)->status &TS_USEDFPU ); +BUG_ON (__thread_has_fpu (task_thread_info (tsk))); xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv;
arch/x86/kvm/vmx.c +1 -1
@@ -948,7 +948,7 @@ static void __vmx_load_host_state(struct#ifdef CONFIG_X86_64 wrmsrl (MSR_KERNEL_GS_BASE , vmx->msr_host_kernel_gs_base);#endif -if (current_thread_info ()->status &TS_USEDFPU ) +if (__thread_has_fpu (current_thread_info ()))clts ();load_gdt (&__get_cpu_var (host_gdt)); }
Greg KH
maintainerPATCH 52/73 i387: do not preload FPU state at task switch time
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit b3b0870ef3ffed72b92415423da864f440f57ad6 upstream.
Yes, taking the trap to re-load the FPU/MMX state is expensive, but so is spending several days looking for a bug in the state save/restore code. And the preload code has some rather subtle interactions with both paravirtualization support and segment state restore, so it's not nearly as simple as it should be.
Also, now that we no longer necessarily depend on a single bit (ie TS_USEDFPU) for keeping track of the state of the FPU, we migth be able to do better. If we are really switching between two processes that keep touching the FP state, save/restore is inevitable, but in the case of having one process that does most of the FPU usage, we may actually be able to do much better than the preloading.
In particular, we may be able to keep track of which CPU the process ran on last, and also per CPU keep track of which process' FP state that CPU has. For modern CPU's that don't destroy the FPU contents on save time, that would allow us to do a lazy restore by just re-enabling the existing FPU state - with no restore cost at all!
--- arch/x86/include/asm/i387.h | 1 - arch/x86/kernel/process_32.c | 20 -------------------- arch/x86/kernel/process_64.c | 23 ----------------------- arch/x86/kernel/traps.c | 35 +++++++++++------------------------ 4 files changed, 11 insertions(+), 68 deletions(-)
arch/x86/include/asm/i387.h +0 -1
@@ -30,7 +30,6 @@ extern void fpu_init(void);extern void mxcsr_feature_mask_init (void );extern int init_fpu (struct task_struct *child);extern void math_state_restore (void ); -extern void __math_state_restore (void );extern int dump_fpu (struct pt_regs *,struct user_i387_struct *);extern user_regset_active_fn fpregs_active, xfpregs_active;
arch/x86/kernel/process_32.c +0 -20
@@ -293,23 +293,11 @@ __switch_to(struct task_struct *prev_p, *next = &next_p->thread;int cpu =smp_processor_id ();struct tss_struct *tss = &per_cpu (init_tss, cpu); -bool preload_fpu;/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ -/* -* If the task has used fpu the last 5 timeslices, just do a full -* restore of the math state immediately to avoid the trap; the -* chances of needing FPU soon are obviously high now -*/ - preload_fpu =tsk_used_math (next_p) && next_p->fpu_counter >5 ; -__unlazy_fpu (prev_p); -/* we're going to use this soon, after a few expensive things */ -if (preload_fpu) -prefetch (next->fpu.state); -/* * Reload esp0. */
@@ -348,11 +336,6 @@ __switch_to(struct task_struct *prev_p, task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))__switch_to_xtra (prev_p, next_p, tss); -/* If we're going to preload the fpu context, make sure clts -is run while we're batching the cpu state updates. */ -if (preload_fpu) -clts (); -/* * Leave lazy mode, flushing any hypercalls made here. * This must be done before restoring TLS segments so
@@ -362,9 +345,6 @@ __switch_to(struct task_struct *prev_p,*/ arch_end_context_switch (next_p); -if (preload_fpu) -__math_state_restore (); -/* * Restore %gs if needed (which is common) */
arch/x86/kernel/process_64.c +0 -23
@@ -377,18 +377,6 @@ __switch_to(struct task_struct *prev_p,int cpu =smp_processor_id ();struct tss_struct *tss = &per_cpu (init_tss, cpu);unsigned fsindex, gsindex; -bool preload_fpu; - -/* -* If the task has used fpu the last 5 timeslices, just do a full -* restore of the math state immediately to avoid the trap; the -* chances of needing FPU soon are obviously high now -*/ - preload_fpu =tsk_used_math (next_p) && next_p->fpu_counter >5 ; - -/* we're going to use this soon, after a few expensive things */ -if (preload_fpu) -prefetch (next->fpu.state);/* * Reload esp0, LDT and the page table pointer:
@@ -421,10 +409,6 @@ __switch_to(struct task_struct *prev_p,/* Must be after DS reload */ __unlazy_fpu (prev_p); -/* Make sure cpu is ready for new context */ -if (preload_fpu) -clts (); -/* * Leave lazy mode, flushing any hypercalls made here. * This must be done before restoring TLS segments so
@@ -483,13 +467,6 @@ __switch_to(struct task_struct *prev_p, task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))__switch_to_xtra (prev_p, next_p, tss); -/* -* Preload the FPU context, now that we've determined that the -* task is likely to be using it. -*/ -if (preload_fpu) -__math_state_restore (); -return prev_p; }
arch/x86/kernel/traps.c +11 -24
@@ -717,28 +717,6 @@ asmlinkage void __attribute__((weak)) sm }/* -* __math_state_restore assumes that cr0.TS is already clear and the -* fpu state is all ready for use. Used during context switch. -*/ -void __math_state_restore (void ) -{ -struct thread_info *thread =current_thread_info (); -struct task_struct *tsk = thread->task; - -/* -* Paranoid restore. send a SIGSEGV if we fail to restore the state. -*/ -if (unlikely (restore_fpu_checking (tsk))) { -stts (); -force_sig (SIGSEGV , tsk); -return ; - } - -__thread_set_has_fpu (thread);/* clts in caller! */ - tsk->fpu_counter++; -} - -/* * 'math_state_restore()' saves the current math information in the * old math state array, and gets the new ones from the current task *
@@ -768,9 +746,18 @@ void math_state_restore(void)local_irq_disable (); } -clts ();/* Allow maths ops (or we recurse) */ +__thread_fpu_begin (thread); -__math_state_restore (); +/* +* Paranoid restore. send a SIGSEGV if we fail to restore the state. +*/ +if (unlikely (restore_fpu_checking (tsk))) { +__thread_fpu_end (thread); +force_sig (SIGSEGV , tsk); +return ; + } + + tsk->fpu_counter++; }EXPORT_SYMBOL_GPL (math_state_restore);
Greg KH
maintainerPATCH 53/73 i387: move AMD K7/K8 fpu fxsave/fxrstor workaround from save to restore
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 4903062b5485f0e2c286a23b44c9b59d9b017d53 upstream.
The AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is pending. In order to not leak FIP state from one process to another, we need to do a floating point load after the fxsave of the old process, and before the fxrstor of the new FPU state. That resets the state to the (uninteresting) kernel load, rather than some potentially sensitive user information.
We used to do this directly after the FPU state save, but that is actually very inconvenient, since it
(a) corrupts what is potentially perfectly good FPU state that we might want to lazy avoid restoring later and
(b) on x86-64 it resulted in a very annoying ordering constraint, where "__unlazy_fpu()" in the task switch needs to be delayed until after the DS segment has been reloaded just to get the new DS value.
Coupling it to the fxrstor instead of the fxsave automatically avoids both of these issues, and also ensures that we only do it when actually necessary (the FP state after a save may never actually get used). It's simply a much more natural place for the leaked state cleanup.
--- arch/x86/include/asm/i387.h | 19 ------------------- arch/x86/kernel/process_64.c | 5 ++--- arch/x86/kernel/traps.c | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 22 deletions(-)
arch/x86/include/asm/i387.h +0 -19
@@ -211,15 +211,6 @@ static inline void fpu_fxsave(struct fpu#endif /* CONFIG_X86_64 */ -/* We need a safe address that is cheap to find and that is already -in L1 during context switch. The best choices are unfortunately -different for UP and SMP */ -#ifdef CONFIG_SMP -#define safe_address (__per_cpu_offset[0]) -#else -#define safe_address (kstat_cpu(0).cpustat.user) -#endif -/* * These must be called with preempt disabled */
@@ -243,16 +234,6 @@ static inline void fpu_save_init(structif (unlikely (fpu->state->fxsave.swd &X87_FSW_ES )) asmvolatile ("fnclex" ); - -/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception -is pending. Clear the x87 state here by setting it to fixed -values. safe_address is a random variable that should be in L1 */ - alternative_input( - ASM_NOP8 ASM_NOP2, -"emms\n\t" /* clear stack tags */ -"fildl %P[addr]" ,/* set F?P to defined value */ - X86_FEATURE_FXSAVE_LEAK, - [addr] "m" (safe_address)); }static inline void __save_init_fpu (struct task_struct *tsk)
arch/x86/kernel/process_64.c +2 -3
@@ -378,6 +378,8 @@ __switch_to(struct task_struct *prev_p,struct tss_struct *tss = &per_cpu (init_tss, cpu);unsigned fsindex, gsindex; +__unlazy_fpu (prev_p); +/* * Reload esp0, LDT and the page table pointer: */
@@ -406,9 +408,6 @@ __switch_to(struct task_struct *prev_p,load_TLS (next, cpu); -/* Must be after DS reload */ -__unlazy_fpu (prev_p); -/* * Leave lazy mode, flushing any hypercalls made here. * This must be done before restoring TLS segments so
arch/x86/kernel/traps.c +14 -0
@@ -731,6 +731,10 @@ void math_state_restore(void)struct thread_info *thread =current_thread_info ();struct task_struct *tsk = thread->task; +/* We need a safe address that is cheap to find and that is already +in L1. We just brought in "thread->task", so use that */ +#define safe_address (thread->task) +if (!tsk_used_math (tsk)) {local_irq_enable ();/*
@@ -748,6 +752,16 @@ void math_state_restore(void)__thread_fpu_begin (thread); +/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception +is pending. Clear the x87 state here by setting it to fixed +values. safe_address is a random variable that should be in L1 */ + alternative_input( + ASM_NOP8 ASM_NOP2, +"emms\n\t" /* clear stack tags */ +"fildl %P[addr]" ,/* set F?P to defined value */ + X86_FEATURE_FXSAVE_LEAK, + [addr] "m" (safe_address)); +/* * Paranoid restore. send a SIGSEGV if we fail to restore the state. */
Greg KH
maintainerPATCH 54/73 i387: move TS_USEDFPU flag from thread_info to task_struct
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit f94edacf998516ac9d849f7bc6949a703977a7f3 upstream.
This moves the bit that indicates whether a thread has ownership of the FPU from the TS_USEDFPU bit in thread_info->status to a word of its own (called 'has_fpu') in task_struct->thread.has_fpu.
This fixes two independent bugs at the same time:
- changing 'thread_info->status' from the scheduler causes nasty problems for the other users of that variable, since it is defined to be thread-synchronous (that's what the "TS_" part of the naming was supposed to indicate).
So perfectly valid code could (and did) do
ti->status |= TS_RESTORE_SIGMASK;
and the compiler was free to do that as separate load, or and store instructions. Which can cause problems with preemption, since a task switch could happen in between, and change the TS_USEDFPU bit. The change to TS_USEDFPU would be overwritten by the final store.
In practice, this seldom happened, though, because the 'status' field was seldom used more than once, so gcc would generally tend to generate code that used a read-modify-write instruction and thus happened to avoid this problem - RMW instructions are naturally low fat and preemption-safe.
- On x86-32, the current_thread_info() pointer would, during interrupts and softirqs, point to a *copy* of the real thread_info, because x86-32 uses %esp to calculate the thread_info address, and thus the separate irq (and softirq) stacks would cause these kinds of odd thread_info copy aliases.
This is normally not a problem, since interrupts aren't supposed to look at thread information anyway (what thread is running at interrupt time really isn't very well-defined), but it confused the heck out of irq_fpu_usable() and the code that tried to squirrel away the FPU state.
(It also caused untold confusion for us poor kernel developers).
It also turns out that using 'task_struct' is actually much more natural for most of the call sites that care about the FPU state, since they tend to work with the task struct for other reasons anyway (ie scheduling). And the FPU data that we are going to save/restore is found there too.
Thanks to Arjan Van De Ven <[email protected]> for pointing us to the %esp issue.
--- arch/x86/include/asm/i387.h | 44 ++++++++++++++++++------------------- arch/x86/include/asm/processor.h | 1 arch/x86/include/asm/thread_info.h | 2 - arch/x86/kernel/traps.c | 11 ++++----- arch/x86/kernel/xsave.c | 2 - arch/x86/kvm/vmx.c | 2 - 6 files changed, 30 insertions(+), 32 deletions(-)
arch/x86/include/asm/i387.h +22 -22
@@ -264,21 +264,21 @@ static inline int restore_fpu_checking(s* be preemption protection *and* they need to be * properly paired with the CR0.TS changes! */ -static inline int __thread_has_fpu (struct thread_info *ti) +static inline int __thread_has_fpu (struct task_struct *tsk) { -return ti->status &TS_USEDFPU ; +return tsk->thread.has_fpu; }/* Must be paired with an 'stts' after! */ -static inline void __thread_clear_has_fpu (struct thread_info *ti) +static inline void __thread_clear_has_fpu (struct task_struct *tsk) { - ti->status &= ~TS_USEDFPU ; + tsk->thread.has_fpu =0 ; }/* Must be paired with a 'clts' before! */ -static inline void __thread_set_has_fpu (struct thread_info *ti) +static inline void __thread_set_has_fpu (struct task_struct *tsk) { - ti->status |=TS_USEDFPU ; + tsk->thread.has_fpu =1 ; }/*
@@ -288,16 +288,16 @@ static inline void __thread_set_has_fpu(* These generally need preemption protection to work, * do try to avoid using these on their own. */ -static inline void __thread_fpu_end (struct thread_info *ti) +static inline void __thread_fpu_end (struct task_struct *tsk) { -__thread_clear_has_fpu (ti); +__thread_clear_has_fpu (tsk);stts (); } -static inline void __thread_fpu_begin (struct thread_info *ti) +static inline void __thread_fpu_begin (struct task_struct *tsk) {clts (); -__thread_set_has_fpu (ti); +__thread_set_has_fpu (tsk); }/*
@@ -308,21 +308,21 @@ extern int restore_i387_xstate(void __usstatic inline void __unlazy_fpu (struct task_struct *tsk) { -if (__thread_has_fpu (task_thread_info (tsk))) { +if (__thread_has_fpu (tsk)) {__save_init_fpu (tsk); -__thread_fpu_end (task_thread_info (tsk)); +__thread_fpu_end (tsk); }else tsk->fpu_counter =0 ; }static inline void __clear_fpu (struct task_struct *tsk) { -if (__thread_has_fpu (task_thread_info (tsk))) { +if (__thread_has_fpu (tsk)) {/* Ignore delayed exceptions from user space */ asmvolatile ("1: fwait\n" "2:\n" _ASM_EXTABLE(1b, 2b)); -__thread_fpu_end (task_thread_info (tsk)); +__thread_fpu_end (tsk); } }
@@ -337,7 +337,7 @@ static inline void __clear_fpu(struct ta*/ static inline bool interrupted_kernel_fpu_idle (void ) { -return !__thread_has_fpu (current_thread_info ()) && +return !__thread_has_fpu (current) && (read_cr0 () &X86_CR0_TS ); }
@@ -371,12 +371,12 @@ static inline bool irq_fpu_usable(void)static inline void kernel_fpu_begin (void ) { -struct thread_info *me =current_thread_info (); +struct task_struct *me = current;WARN_ON_ONCE (!irq_fpu_usable ());preempt_disable ();if (__thread_has_fpu (me)) { -__save_init_fpu (me->task); +__save_init_fpu (me);__thread_clear_has_fpu (me);/* We do 'stts()' in kernel_fpu_end() */ }else
@@ -441,13 +441,13 @@ static inline void irq_ts_restore(int TS*/ static inline int user_has_fpu (void ) { -return __thread_has_fpu (current_thread_info ()); +return __thread_has_fpu (current); }static inline void user_fpu_end (void ) {preempt_disable (); -__thread_fpu_end (current_thread_info ()); +__thread_fpu_end (current);preempt_enable (); }
@@ -455,7 +455,7 @@ static inline void user_fpu_begin(void) {preempt_disable ();if (!user_has_fpu ()) -__thread_fpu_begin (current_thread_info ()); +__thread_fpu_begin (current);preempt_enable (); }
@@ -464,10 +464,10 @@ static inline void user_fpu_begin(void)*/ static inline void save_init_fpu (struct task_struct *tsk) { -WARN_ON_ONCE (!__thread_has_fpu (task_thread_info (tsk))); +WARN_ON_ONCE (!__thread_has_fpu (tsk));preempt_disable ();__save_init_fpu (tsk); -__thread_fpu_end (task_thread_info (tsk)); +__thread_fpu_end (tsk);preempt_enable (); }
arch/x86/include/asm/processor.h +1 -0
@@ -454,6 +454,7 @@ struct thread_struct {unsigned long trap_no;unsigned long error_code;/* floating point and extended processor state */ +unsigned long has_fpu;struct fpu fpu;#ifdef CONFIG_X86_32 /* Virtual 86 mode info */
arch/x86/include/asm/thread_info.h +0 -2
@@ -242,8 +242,6 @@ static inline struct thread_info *curren* ever touches our thread-synchronous status, so we don't * have to worry about atomic accesses. */ -#define TS_USEDFPU 0x0001/* FPU was used by this task -this quantum (SMP) */ #define TS_COMPAT 0x0002/* 32bit syscall active (64BIT)*/ #define TS_POLLING 0x0004/* idle task polling need_resched, skip sending interrupt */
arch/x86/kernel/traps.c +5 -6
@@ -728,12 +728,11 @@ asmlinkage void __attribute__((weak)) sm*/ void math_state_restore (void ) { -struct thread_info *thread =current_thread_info (); -struct task_struct *tsk = thread->task; +struct task_struct *tsk = current;/* We need a safe address that is cheap to find and that is already -in L1. We just brought in "thread->task", so use that */ -#define safe_address (thread->task) +in L1. We're just bringing in "tsk->thread.has_fpu", so use that */ +#define safe_address (tsk->thread.has_fpu)if (!tsk_used_math (tsk)) {local_irq_enable ();
@@ -750,7 +749,7 @@ void math_state_restore(void)local_irq_disable (); } -__thread_fpu_begin (thread); +__thread_fpu_begin (tsk);/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is pending. Clear the x87 state here by setting it to fixed
@@ -766,7 +765,7 @@ void math_state_restore(void)* Paranoid restore. send a SIGSEGV if we fail to restore the state. */ if (unlikely (restore_fpu_checking (tsk))) { -__thread_fpu_end (thread); +__thread_fpu_end (tsk);force_sig (SIGSEGV , tsk);return ; }
arch/x86/kernel/xsave.c +1 -1
@@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_sif (!fx)return ; -BUG_ON (__thread_has_fpu (task_thread_info (tsk))); +BUG_ON (__thread_has_fpu (tsk)); xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv;
arch/x86/kvm/vmx.c +1 -1
@@ -948,7 +948,7 @@ static void __vmx_load_host_state(struct#ifdef CONFIG_X86_64 wrmsrl (MSR_KERNEL_GS_BASE , vmx->msr_host_kernel_gs_base);#endif -if (__thread_has_fpu (current_thread_info ())) +if (__thread_has_fpu (current))clts ();load_gdt (&__get_cpu_var (host_gdt)); }
Greg KH
maintainerPATCH 55/73 i387: re-introduce FPU state preloading at context switch time
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linus Torvalds <[email protected]>
commit 34ddc81a230b15c0e345b6b253049db731499f7e upstream.
After all the FPU state cleanups and finally finding the problem that caused all our FPU save/restore problems, this re-introduces the preloading of FPU state that was removed in commit b3b0870ef3ff ("i387:
do not preload FPU state at task switch time").
However, instead of simply reverting the removal, this reimplements preloading with several fixes, most notably
- properly abstracted as a true FPU state switch, rather than as open-coded save and restore with various hacks.
In particular, implementing it as a proper FPU state switch allows us to optimize the CR0.TS flag accesses: there is no reason to set the TS bit only to then almost immediately clear it again. CR0 accesses are quite slow and expensive, don't flip the bit back and forth for no good reason.
- Make sure that the same model works for both x86-32 and x86-64, so that there are no gratuitous differences between the two due to the way they save and restore segment state differently due to architectural differences that really don't matter to the FPU state.
- Avoid exposing the "preload" state to the context switch routines, and in particular allow the concept of lazy state restore: if nothing else has used the FPU in the meantime, and the process is still on the same CPU, we can avoid restoring state from memory entirely, just re-expose the state that is still in the FPU unit.
That optimized lazy restore isn't actually implemented here, but the infrastructure is set up for it. Of course, older CPU's that use 'fnsave' to save the state cannot take advantage of this, since the state saving also trashes the state.
In other words, there is now an actual _design_ to the FPU state saving, rather than just random historical baggage. Hopefully it's easier to follow as a result.
--- arch/x86/include/asm/i387.h | 110 ++++++++++++++++++++++++++++++++++++------- arch/x86/kernel/process_32.c | 5 + arch/x86/kernel/process_64.c | 5 + arch/x86/kernel/traps.c | 55 ++++++++++++--------- 4 files changed, 133 insertions(+), 42 deletions(-)
arch/x86/include/asm/i387.h +93 -17
@@ -29,6 +29,7 @@ extern unsigned int sig_xstate_size;extern void fpu_init (void );extern void mxcsr_feature_mask_init (void );extern int init_fpu (struct task_struct *child); +extern void __math_state_restore (struct task_struct *);extern void math_state_restore (void );extern int dump_fpu (struct pt_regs *,struct user_i387_struct *);
@@ -212,9 +213,10 @@ static inline void fpu_fxsave(struct fpu#endif /* CONFIG_X86_64 */ /* -* These must be called with preempt disabled +* These must be called with preempt disabled. Returns +* 'true' if the FPU state is still intact. */ -static inline void fpu_save_init (struct fpu *fpu) +static inline int fpu_save_init (struct fpu *fpu) {if (use_xsave ()) {fpu_xsave (fpu);
@@ -223,22 +225,33 @@ static inline void fpu_save_init(struct* xsave header may indicate the init state of the FP. */ if (!(fpu->state->xsave.xsave_hdr.xstate_bv &XSTATE_FP )) -return ; +return 1 ; }else if (use_fxsr ()) {fpu_fxsave (fpu); }else { asmvolatile ("fnsave %[fx]; fwait" : [fx]"=m" (fpu->state->fsave)); -return ; +return 0 ; } -if (unlikely (fpu->state->fxsave.swd &X87_FSW_ES )) +/* +* If exceptions are pending, we need to clear them so +* that we don't randomly get exceptions later. +* +* FIXME! Is this perhaps only true for the old-style +* irq13 case? Maybe we could leave the x87 state +* intact otherwise? +*/ +if (unlikely (fpu->state->fxsave.swd &X87_FSW_ES )) { asmvolatile ("fnclex" ); +return 0 ; + } +return 1 ; } -static inline void __save_init_fpu (struct task_struct *tsk) +static inline int __save_init_fpu (struct task_struct *tsk) { -fpu_save_init (&tsk->thread.fpu); +return fpu_save_init (&tsk->thread.fpu); }static inline int fpu_fxrstor_checking (struct fpu *fpu)
@@ -301,20 +314,79 @@ static inline void __thread_fpu_begin(st }/* -* Signal frame handlers... +* FPU state switching for scheduling. +* +* This is a two-stage process: +* +* - switch_fpu_prepare() saves the old state and +* sets the new state of the CR0.TS bit. This is +* done within the context of the old process. +* +* - switch_fpu_finish() restores the new state as +* necessary. */ -extern int save_i387_xstate (void __user *buf); -extern int restore_i387_xstate (void __user *buf); +typedef struct {int preload; }fpu_switch_t ; + +/* +* FIXME! We could do a totally lazy restore, but we need to +* add a per-cpu "this was the task that last touched the FPU +* on this CPU" variable, and the task needs to have a "I last +* touched the FPU on this CPU" and check them. +* +* We don't do that yet, so "fpu_lazy_restore()" always returns +* false, but some day.. +*/ +#define fpu_lazy_restore (tsk) (0) +#define fpu_lazy_state_intact (tsk) do { } while (0) -static inline void __unlazy_fpu (struct task_struct *tsk) +static inline fpu_switch_t switch_fpu_prepare (struct task_struct *old,struct task_struct *new) { -if (__thread_has_fpu (tsk)) { -__save_init_fpu (tsk); -__thread_fpu_end (tsk); - }else - tsk->fpu_counter =0 ; +fpu_switch_t fpu; + + fpu.preload =tsk_used_math (new) && new->fpu_counter >5 ; +if (__thread_has_fpu (old)) { +if (__save_init_fpu (old)) +fpu_lazy_state_intact (old); +__thread_clear_has_fpu (old); + old->fpu_counter++; + +/* Don't change CR0.TS if we just switch! */ +if (fpu.preload) { +__thread_set_has_fpu (new); +prefetch (new->thread.fpu.state); + }else +stts (); + }else { + old->fpu_counter =0 ; +if (fpu.preload) { +if (fpu_lazy_restore (new)) + fpu.preload =0 ; +else +prefetch (new->thread.fpu.state); +__thread_fpu_begin (new); + } + } +return fpu; +} + +/* +* By the time this gets called, we've already cleared CR0.TS and +* given the process the FPU if we are going to preload the FPU +* state - all we need to do is to conditionally restore the register +* state itself. +*/ +static inline void switch_fpu_finish (struct task_struct *new,fpu_switch_t fpu) +{ +if (fpu.preload) +__math_state_restore (new); } +/* +* Signal frame handlers... +*/ +extern int save_i387_xstate (void __user *buf); +extern int restore_i387_xstate (void __user *buf); +static inline void __clear_fpu (struct task_struct *tsk) {if (__thread_has_fpu (tsk)) {
@@ -474,7 +546,11 @@ static inline void save_init_fpu(structstatic inline void unlazy_fpu (struct task_struct *tsk) {preempt_disable (); -__unlazy_fpu (tsk); +if (__thread_has_fpu (tsk)) { +__save_init_fpu (tsk); +__thread_fpu_end (tsk); + }else + tsk->fpu_counter =0 ;preempt_enable (); }
arch/x86/kernel/process_32.c +4 -1
@@ -293,10 +293,11 @@ __switch_to(struct task_struct *prev_p, *next = &next_p->thread;int cpu =smp_processor_id ();struct tss_struct *tss = &per_cpu (init_tss, cpu); +fpu_switch_t fpu;/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ -__unlazy_fpu (prev_p); + fpu =switch_fpu_prepare (prev_p, next_p);/* * Reload esp0.
@@ -351,6 +352,8 @@ __switch_to(struct task_struct *prev_p,if (prev->gs | next->gs)lazy_load_gs (next->gs); +switch_fpu_finish (next_p, fpu); +percpu_write (current_task, next_p);return prev_p;
arch/x86/kernel/process_64.c +4 -1
@@ -377,8 +377,9 @@ __switch_to(struct task_struct *prev_p,int cpu =smp_processor_id ();struct tss_struct *tss = &per_cpu (init_tss, cpu);unsigned fsindex, gsindex; +fpu_switch_t fpu; -__unlazy_fpu (prev_p); + fpu =switch_fpu_prepare (prev_p, next_p);/* * Reload esp0, LDT and the page table pointer:
@@ -448,6 +449,8 @@ __switch_to(struct task_struct *prev_p,wrmsrl (MSR_KERNEL_GS_BASE , next->gs); prev->gsindex = gsindex; +switch_fpu_finish (next_p, fpu); +/* * Switch the PDA and FPU contexts. */
arch/x86/kernel/traps.c +32 -23
73 lines not on this page · raw message
Greg KH
maintainerPATCH 56/73 usb-storage: fix freezing of the scanning thread
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Stern <[email protected]>
commit bb94a406682770a35305daaa241ccdb7cab399de upstream.
This patch (as1521b) fixes the interaction between usb-storage's scanning thread and the freezer. The current implementation has a
race: If the device is unplugged shortly after being plugged in and just as a system sleep begins, the scanning thread may get frozen before the khubd task. Khubd won't be able to freeze until the disconnect processing is complete, and the disconnect processing can't proceed until the scanning thread finishes, so the sleep transition will fail.
The implementation in the 3.2 kernel suffers from an additional problem. There the scanning thread calls set_freezable_with_signal(), and the signals sent by the freezer will mess up the thread's I/O delays, which are all interruptible.
The solution to both problems is the same: Replace the kernel thread used for scanning with a delayed-work routine on the system freezable work queue. Freezable work queues have the nice property that you can cancel a work item even while the work queue is frozen, and no signals are needed.
The 3.2 version of this patch solves the problem in Bugzilla #42730.
--- drivers/usb/storage/usb.c | 91 ++++++++++++++++------------------------------ drivers/usb/storage/usb.h | 7 ++- 2 files changed, 36 insertions(+), 62 deletions(-)
drivers/usb/storage/usb.c +32 -59
@@ -788,15 +788,19 @@ static void quiesce_and_remove_host(strustruct Scsi_Host *host =us_to_host (us);/* If the device is really gone, cut short reset delays */ -if (us->pusb_dev->state ==USB_STATE_NOTATTACHED ) +if (us->pusb_dev->state ==USB_STATE_NOTATTACHED ) {set_bit (US_FLIDX_DISCONNECTING , &us->dflags); +wake_up (&us->delay_wait); + } -/* Prevent SCSI-scanning (if it hasn't started yet) -* and wait for the SCSI-scanning thread to stop. +/* Prevent SCSI scanning (if it hasn't started yet) +* or wait for the SCSI-scanning routine to stop. */ -set_bit (US_FLIDX_DONT_SCAN , &us->dflags); -wake_up (&us->delay_wait); -wait_for_completion (&us->scanning_done); +cancel_delayed_work_sync (&us->scan_dwork); + +/* Balance autopm calls if scanning was cancelled */ +if (test_bit (US_FLIDX_SCAN_PENDING , &us->dflags)) +usb_autopm_put_interface_no_suspend (us->pusb_intf);/* Removing the host will perform an orderly shutdown: caches * synchronized, disks spun down, etc.
@@ -823,52 +827,28 @@ static void release_everything(struct usscsi_host_put (us_to_host (us)); } -/* Thread to carry out delayed SCSI-device scanning */ -static int usb_stor_scan_thread (void * __us) +/* Delayed-work routine to carry out SCSI-device scanning */ +static void usb_stor_scan_dwork (struct work_struct *work) { -struct us_data *us = (struct us_data *)__us; + struct us_data *us = container_of(work, struct us_data, + scan_dwork.work);struct device *dev = &us->pusb_intf->dev; -dev_dbg (dev,"device found\n" ); - -set_freezable_with_signal (); -/* -* Wait for the timeout to expire or for a disconnect -* -* We can't freeze in this thread or we risk causing khubd to -* fail to freeze, but we can't be non-freezable either. Nor can -* khubd freeze while waiting for scanning to complete as it may -* hold the device lock, causing a hang when suspending devices. -* So we request a fake signal when freezing and use -* interruptible sleep to kick us out of our wait early when -* freezing happens. -*/ -if (delay_use >0 ) { -dev_dbg (dev,"waiting for device to settle " -"before scanning\n" ); -wait_event_interruptible_timeout (us->delay_wait, -test_bit (US_FLIDX_DONT_SCAN , &us->dflags), - delay_use *HZ ); - } - -/* If the device is still connected, perform the scanning */ -if (!test_bit (US_FLIDX_DONT_SCAN , &us->dflags)) { - -/* For bulk-only devices, determine the max LUN value */ -if (us->protocol ==USB_PR_BULK && - !(us->fflags &US_FL_SINGLE_LUN )) { -mutex_lock (&us->dev_mutex); - us->max_lun =usb_stor_Bulk_max_lun (us); -mutex_unlock (&us->dev_mutex); - } -scsi_scan_host (us_to_host (us)); -dev_dbg (dev,"scan complete\n" ); +dev_dbg (dev,"starting scan\n" ); -/* Should we unbind if no devices were detected? */ +/* For bulk-only devices, determine the max LUN value */ +if (us->protocol ==USB_PR_BULK && !(us->fflags &US_FL_SINGLE_LUN )) { +mutex_lock (&us->dev_mutex); + us->max_lun =usb_stor_Bulk_max_lun (us); +mutex_unlock (&us->dev_mutex); } +scsi_scan_host (us_to_host (us)); +dev_dbg (dev,"scan complete\n" ); + +/* Should we unbind if no devices were detected? */ usb_autopm_put_interface (us->pusb_intf); -complete_and_exit (&us->scanning_done,0 ); +clear_bit (US_FLIDX_SCAN_PENDING , &us->dflags); }static unsigned int usb_stor_sg_tablesize (struct usb_interface *intf)
@@ -915,7 +895,7 @@ int usb_stor_probe1(struct us_data **pusinit_completion (&us->cmnd_ready);init_completion (&(us->notify));init_waitqueue_head (&us->delay_wait); -init_completion (&us->scanning_done); +INIT_DELAYED_WORK (&us->scan_dwork, usb_stor_scan_dwork);/* Associate the us_data structure with the USB device */ result =associate_dev (us, intf);
@@ -946,7 +926,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);/* Second part of general USB mass-storage probing */ int usb_stor_probe2 (struct us_data *us) { -struct task_struct *th;int result;struct device *dev = &us->pusb_intf->dev;
@@ -987,20 +966,14 @@ int usb_stor_probe2(struct us_data *us) goto BadDevice; } -/* Start up the thread for delayed SCSI-device scanning */ - th =kthread_create (usb_stor_scan_thread, us,"usb-stor-scan" ); -if (IS_ERR (th)) { -dev_warn (dev, -"Unable to start the device-scanning thread\n" ); -complete (&us->scanning_done); -quiesce_and_remove_host (us); - result =PTR_ERR (th); - goto BadDevice; - } - +/* Submit the delayed_work for SCSI-device scanning */ usb_autopm_get_interface_no_resume (us->pusb_intf); -wake_up_process (th); +set_bit (US_FLIDX_SCAN_PENDING , &us->dflags); +if (delay_use >0 ) +dev_dbg (dev,"waiting for device to settle before scanning\n" ); +queue_delayed_work (system_freezable_wq, &us->scan_dwork, + delay_use *HZ );return 0 ;/* We come here if there are any problems */
drivers/usb/storage/usb.h +4 -3
@@ -47,6 +47,7 @@#include <linux/blkdev.h> #include <linux/completion.h> #include <linux/mutex.h> +#include <linux/workqueue.h> #include <scsi/scsi_host.h> struct us_data ;
@@ -72,7 +73,7 @@ struct us_unusual_dev {#define US_FLIDX_DISCONNECTING 3/* disconnect in progress */ #define US_FLIDX_RESETTING 4/* device reset in progress */ #define US_FLIDX_TIMED_OUT 5/* SCSI midlayer timed out */ -#define US_FLIDX_DONT_SCAN 6/* don't scan (disconnect) */ +#define US_FLIDX_SCAN_PENDING 6/* scanning not yet done */ #define US_FLIDX_REDO_READ10 7/* redo READ(10) command */ #define US_FLIDX_READ10_WORKED 8/* previous READ(10) succeeded */
@@ -147,8 +148,8 @@ struct us_data {/* mutual exclusion and synchronization structures */ struct completion cmnd_ready;/* to sleep thread on */ struct completion notify;/* thread begin/end */ -wait_queue_head_t delay_wait;/* wait during scan, reset */ -struct completion scanning_done;/* wait for scan thread */ +wait_queue_head_t delay_wait;/* wait during reset */ +struct delayed_work scan_dwork;/* for async scanning */ /* subdriver information */ void *extra;/* Any extra data */
Greg KH
maintainerPATCH 57/73 USB: Dont fail USB3 probe on missing legacy PCI IRQ.
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sarah Sharp <[email protected]>
commit 68d07f64b8a11a852d48d1b05b724c3e20c0d94b upstream
Intel has a PCI USB xhci host controller on a new platform. It doesn't have a line IRQ definition in BIOS. The Linux driver refuses to initialize this controller, but Windows works well because it only depends on MSI.
Actually, Linux also can work for MSI. This patch avoids the line IRQ checking for USB3 HCDs in usb core PCI probe. It allows the xHCI driver to try to enable MSI or MSI-X first. It will fail the probe if MSI enabling failed and there's no legacy PCI IRQ.
This patch should be backported to kernels as old as 2.6.32.
[Maintainer note: This patch is a backport of commit 68d07f64b8a11a852d48d1b05b724c3e20c0d94b "USB: Don't fail USB3 probe on missing legacy PCI IRQ." to the 3.0 kernel. Note, the original patch description was wrong. We should not back port this to kernels older than 2.6.36, since that was the first kernel to support MSI and MSI-X for xHCI hosts. These systems will just not work without MSI support, so the probe should fail on kernels older than 2.6.36.]
--- drivers/usb/core/hcd-pci.c | 5 ++++- drivers/usb/core/hcd.c | 6 ++++-- drivers/usb/host/xhci.c | 5 +++++ 3 files changed, 13 insertions(+), 3 deletions(-)
drivers/usb/core/hcd-pci.c +4 -1
@@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dereturn -ENODEV ; dev->current_state =PCI_D0 ; -if (!dev->irq) { +/* The xHCI driver supports MSI and MSI-X, +* so don't fail if the BIOS doesn't provide a legacy IRQ. +*/ +if (!dev->irq && (driver->flags &HCD_MASK ) !=HCD_USB3 ) {dev_err (&dev->dev,"Found HC with no IRQ. Check BIOS/PCI %s setup!\n" ,pci_name (dev));
drivers/usb/core/hcd.c +4 -2
@@ -2435,8 +2435,10 @@ int usb_add_hcd(struct usb_hcd *hcd, && device_can_wakeup(&hcd->self.root_hub->dev))dev_dbg (hcd->self.controller,"supports USB remote wakeup\n" ); -/* enable irqs just before we start the controller */ -if (usb_hcd_is_primary_hcd (hcd)) { +/* enable irqs just before we start the controller, +* if the BIOS provides legacy PCI irqs. +*/ +if (usb_hcd_is_primary_hcd (hcd) && irqnum) { retval =usb_hcd_request_irqs (hcd, irqnum, irqflags);if (retval) goto err_request_irq;
drivers/usb/host/xhci.c +5 -0
@@ -444,6 +444,11 @@ int xhci_run(struct usb_hcd *hcd)if (ret) { legacy_irq: +if (!pdev->irq) { +xhci_err (xhci,"No msi-x/msi found and " +"no IRQ in BIOS\n" ); +return -EINVAL ; + }/* fall back to legacy interrupt*/ ret =request_irq (pdev->irq, &usb_hcd_irq,IRQF_SHARED , hcd->irq_descr, hcd);
Greg KH
maintainerPATCH 58/73 x86/amd: Fix L1i and L2 cache sharing information for AMD family 15h processors
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Herrmann <[email protected]>
commit 32c3233885eb10ac9cb9410f2f8cd64b8df2b2a1 upstream.
For L1 instruction cache and L2 cache the shared CPU information is wrong. On current AMD family 15h CPUs those caches are shared between both cores of a compute unit.
This fixes https://bugzilla.kernel.org/show_bug.cgi?id=42607
--- arch/x86/kernel/cpu/intel_cacheinfo.c | 44 +++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +36 -8
@@ -330,8 +330,7 @@ static void __cpuinit amd_calc_l3_indice l3->indices = (max (max3 (sc0, sc1, sc2), sc3) <<10 ) -1 ; } -static void __cpuinit amd_init_l3_cache (struct _cpuid4_info_regs *this_leaf, -int index) +static void __cpuinit amd_init_l3_cache (struct _cpuid4_info_regs *this_leaf,int index) {static struct amd_l3_cache *__cpuinitdata l3_caches;int node;
@@ -748,14 +747,16 @@ static DEFINE_PER_CPU(struct _cpuid4_inf#define CPUID4_INFO_IDX (x, y) (&((per_cpu(ici_cpuid4_info, x))[y]))#ifdef CONFIG_SMP -static void __cpuinit cache_shared_cpu_map_setup (unsigned int cpu,int index) + +static int __cpuinit cache_shared_amd_cpu_map_setup (unsigned int cpu,int index) { -struct _cpuid4_info *this_leaf, *sibling_leaf; -unsigned long num_threads_sharing; -int index_msb, i, sibling; +struct _cpuid4_info *this_leaf; +int ret, i, sibling;struct cpuinfo_x86 *c = &cpu_data (cpu); -if ((index ==3 ) && (c->x86_vendor ==X86_VENDOR_AMD )) { + ret =0 ; +if (index ==3 ) { + ret =1 ;for_each_cpu (i,cpu_llc_shared_mask (cpu)) {if (!per_cpu (ici_cpuid4_info, i))continue ;
@@ -766,8 +767,35 @@ static void __cpuinit cache_shared_cpu_mset_bit (sibling, this_leaf->shared_cpu_map); } } -return ; + }else if ((c->x86 ==0x15 ) && ((index ==1 ) || (index ==2 ))) { + ret =1 ; +for_each_cpu (i,cpu_sibling_mask (cpu)) { +if (!per_cpu (ici_cpuid4_info, i)) +continue ; + this_leaf =CPUID4_INFO_IDX (i, index); +for_each_cpu (sibling,cpu_sibling_mask (cpu)) { +if (!cpu_online (sibling)) +continue ; +set_bit (sibling, this_leaf->shared_cpu_map); + } + } } + +return ret; +} + +static void __cpuinit cache_shared_cpu_map_setup (unsigned int cpu,int index) +{ +struct _cpuid4_info *this_leaf, *sibling_leaf; +unsigned long num_threads_sharing; +int index_msb, i; +struct cpuinfo_x86 *c = &cpu_data (cpu); + +if (c->x86_vendor ==X86_VENDOR_AMD ) { +if (cache_shared_amd_cpu_map_setup (cpu, index)) +return ; + } + this_leaf =CPUID4_INFO_IDX (cpu, index); num_threads_sharing =1 + this_leaf->eax.split.num_threads_sharing;
Greg KH
maintainerPATCH 59/73 ath9k: stop on rates with idx -1 in ath9k rate controls .tx_status
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Roskin <[email protected]>
commit 2504a6423b9ab4c36df78227055995644de19edb upstream.
Rate control algorithms are supposed to stop processing when they encounter a rate with the index -1. Checking for rate->count not being zero is not enough.
Allowing a rate with negative index leads to memory corruption in ath_debug_stat_rc().
One consequence of the bug is discussed at
https://bugzilla.redhat.com/show_bug.cgi?id=768639
--- drivers/net/wireless/ath/ath9k/rc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/ath9k/rc.c +1 -1
@@ -1328,7 +1328,7 @@ static void ath_tx_status(void *priv, st fc = hdr->frame_control;for (i =0 ; i < sc->hw->max_rates; i++) {struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; -if (!rate->count) +if (rate->idx <0 || !rate->count)break ; final_ts_idx = i;
Greg KH
maintainerPATCH 60/73 genirq: Unmask oneshot irqs when thread was not woken
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
commit ac5637611150281f398bb7a47e3fcb69a09e7803 upstream.
When the primary handler of an interrupt which is marked IRQ_ONESHOT returns IRQ_HANDLED or IRQ_NONE, then the interrupt thread is not woken and the unmask logic of the interrupt line is never invoked. This keeps the interrupt masked forever.
This was not noticed as most IRQ_ONESHOT users wake the thread unconditionally (usually because they cannot access the underlying device from hard interrupt context). Though this behaviour was nowhere documented and not necessarily intentional. Some drivers can avoid the thread wakeup in certain cases and run into the situation where the interrupt line s kept masked.
Handle it gracefully.
--- kernel/irq/chip.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
kernel/irq/chip.c +23 -2
@@ -312,6 +312,24 @@ out_unlock: }EXPORT_SYMBOL_GPL (handle_simple_irq); +/* +* Called unconditionally from handle_level_irq() and only for oneshot +* interrupts from handle_fasteoi_irq() +*/ +static void cond_unmask_irq (struct irq_desc *desc) +{ +/* +* We need to unmask in the following cases: +* - Standard level irq (IRQF_ONESHOT is not set) +* - Oneshot irq which did not wake the thread (caused by a +* spurious interrupt or a primary handler handling it +* completely). +*/ +if (!irqd_irq_disabled (&desc->irq_data) && +irqd_irq_masked (&desc->irq_data) && !desc->threads_oneshot) +unmask_irq (desc); +} +/** * handle_level_irq - Level type irq handler * @irq: the interrupt number
@@ -344,8 +362,8 @@ handle_level_irq(unsigned int irq, struchandle_irq_event (desc); -if (!irqd_irq_disabled (&desc->irq_data) && !(desc->istate &IRQS_ONESHOT )) -unmask_irq (desc); +cond_unmask_irq (desc); + out_unlock:raw_spin_unlock (&desc->lock); }
@@ -399,6 +417,9 @@ handle_fasteoi_irq(unsigned int irq, strpreflow_handler (desc);handle_irq_event (desc); +if (desc->istate &IRQS_ONESHOT ) +cond_unmask_irq (desc); + out_eoi: desc->irq_data.chip->irq_eoi (&desc->irq_data); out_unlock:
Greg KH
maintainerPATCH 61/73 genirq: Handle pending irqs in irq_startup()
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
commit b4bc724e82e80478cba5fe9825b62e71ddf78757 upstream.
An interrupt might be pending when irq_startup() is called, but the startup code does not invoke the resend logic. In some cases this prevents the device from issuing another interrupt which renders the device non functional.
Call the resend function in irq_startup() to keep things going.
--- kernel/irq/autoprobe.c | 4 ++-- kernel/irq/chip.c | 17 ++++++++++------- kernel/irq/internals.h | 2 +- kernel/irq/manage.c | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-)
kernel/irq/autoprobe.c +2 -2
@@ -53,7 +53,7 @@ unsigned long probe_irq_on(void)if (desc->irq_data.chip->irq_set_type) desc->irq_data.chip->irq_set_type (&desc->irq_data,IRQ_TYPE_PROBE ); -irq_startup (desc); +irq_startup (desc, false); }raw_spin_unlock_irq (&desc->lock); }
@@ -70,7 +70,7 @@ unsigned long probe_irq_on(void)raw_spin_lock_irq (&desc->lock);if (!desc->action &&irq_settings_can_probe (desc)) { desc->istate |=IRQS_AUTODETECT |IRQS_WAITING ; -if (irq_startup (desc)) +if (irq_startup (desc, false)) desc->istate |=IRQS_PENDING ; }raw_spin_unlock_irq (&desc->lock);
kernel/irq/chip.c +10 -7
@@ -157,19 +157,22 @@ static void irq_state_set_masked(structirqd_set (&desc->irq_data,IRQD_IRQ_MASKED ); } -int irq_startup (struct irq_desc *desc) +int irq_startup (struct irq_desc *desc,bool resend) { +int ret =0 ; +irq_state_clr_disabled (desc); desc->depth =0 ;if (desc->irq_data.chip->irq_startup) { -int ret = desc->irq_data.chip->irq_startup (&desc->irq_data); + ret = desc->irq_data.chip->irq_startup (&desc->irq_data);irq_state_clr_masked (desc); -return ret; + }else { +irq_enable (desc); } - -irq_enable (desc); -return 0 ; +if (resend) +check_irq_resend (desc, desc->irq_data.irq); +return ret; }void irq_shutdown (struct irq_desc *desc)
@@ -596,7 +599,7 @@ __irq_set_handler(unsigned int irq, irq_irq_settings_set_noprobe (desc);irq_settings_set_norequest (desc);irq_settings_set_nothread (desc); -irq_startup (desc); +irq_startup (desc, true); } out:irq_put_desc_busunlock (desc, flags);
kernel/irq/internals.h +1 -1
@@ -67,7 +67,7 @@ extern int __irq_set_trigger(struct irq_extern void __disable_irq (struct irq_desc *desc,unsigned int irq,bool susp);extern void __enable_irq (struct irq_desc *desc,unsigned int irq,bool resume); -extern int irq_startup (struct irq_desc *desc); +extern int irq_startup (struct irq_desc *desc,bool resend);extern void irq_shutdown (struct irq_desc *desc);extern void irq_enable (struct irq_desc *desc);extern void irq_disable (struct irq_desc *desc);
kernel/irq/manage.c +1 -1
@@ -1018,7 +1018,7 @@ __setup_irq(unsigned int irq, struct irq desc->istate |=IRQS_ONESHOT ;if (irq_settings_can_autoenable (desc)) -irq_startup (desc); +irq_startup (desc, true);else /* Undo nested disables: */ desc->depth =1 ;
Greg KH
maintainerPATCH 62/73 scsi_scan: Fix Poison overwritten warning caused by using freed shost
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huajun Li <[email protected]>
commit 267a6ad4aefaafbde607804c60945bcf97f91c1b upstream.
In do_scan_async(), calling scsi_autopm_put_host(shost) may reference freed shost, and cause Posison overwitten warning.
Yes, this case can happen, for example, an USB is disconnected just when do_scan_async() thread starts to run, then scsi_host_put() called in scsi_finish_async_scan() will lead to shost be freed(because the refcount of shost->shost_gendev decreases to 1 after USB disconnects), at this point, if references shost again, system will show following warning msg.
To make scsi_autopm_put_host(shost) always reference a valid shost, put it just before scsi_host_put() in function scsi_finish_async_scan().
[ 299.281565] =============================================================================
[ 299.281634] BUG kmalloc-4096 (Tainted: G I ): Poison overwritten
[ 299.281682] -----------------------------------------------------------------------------
[ 299.281684]
[ 299.281752] INFO: 0xffff880056c305d0-0xffff880056c305d0. First byte
0x6a instead of 0x6b
[ 299.281816] INFO: Allocated in scsi_host_alloc+0x4a/0x490 age=1688
cpu=1 pid=2004
[ 299.281870] __slab_alloc+0x617/0x6c1
[ 299.281901] __kmalloc+0x28c/0x2e0
[ 299.281931] scsi_host_alloc+0x4a/0x490
[ 299.281966] usb_stor_probe1+0x5b/0xc40 [usb_storage]
[ 299.282010] storage_probe+0xa4/0xe0 [usb_storage]
[ 299.282062] usb_probe_interface+0x172/0x330 [usbcore]
[ 299.282105] driver_probe_device+0x257/0x3b0
[ 299.282138] __driver_attach+0x103/0x110
[ 299.282171] bus_for_each_dev+0x8e/0xe0
[ 299.282201] driver_attach+0x26/0x30
[ 299.282230] bus_add_driver+0x1c4/0x430
[ 299.282260] driver_register+0xb6/0x230
[ 299.282298] usb_register_driver+0xe5/0x270 [usbcore]
[ 299.282337] 0xffffffffa04ab03d
[ 299.282364] do_one_initcall+0x47/0x230
[ 299.282396] sys_init_module+0xa0f/0x1fe0
[ 299.282429] INFO: Freed in scsi_host_dev_release+0x18a/0x1d0 age=85
cpu=0 pid=2008
[ 299.282482] __slab_free+0x3c/0x2a1
[ 299.282510] kfree+0x296/0x310
[ 299.282536] scsi_host_dev_release+0x18a/0x1d0
[ 299.282574] device_release+0x74/0x100
[ 299.282606] kobject_release+0xc7/0x2a0
[ 299.282637] kobject_put+0x54/0xa0
[ 299.282668] put_device+0x27/0x40
[ 299.282694] scsi_host_put+0x1d/0x30
[ 299.282723] do_scan_async+0x1fc/0x2b0
[ 299.282753] kthread+0xdf/0xf0
[ 299.282782] kernel_thread_helper+0x4/0x10
[ 299.282817] INFO: Slab 0xffffea00015b0c00 objects=7 used=7 fp=0x
(null) flags=0x100000000004080
[ 299.282882] INFO: Object 0xffff880056c30000 @offset=0 fp=0x (null)
[ 299.282884]...
--- drivers/scsi/scsi_scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/scsi_scan.c +2 -2
@@ -1815,6 +1815,7 @@ static void scsi_finish_async_scan(struc }spin_unlock (&async_scan_lock); +scsi_autopm_put_host (shost);scsi_host_put (shost);kfree (data); }
@@ -1841,7 +1842,6 @@ static int do_scan_async(void *_data)do_scsi_scan_host (shost);scsi_finish_async_scan (data); -scsi_autopm_put_host (shost);return 0 ; }
@@ -1869,7 +1869,7 @@ void scsi_scan_host(struct Scsi_Host *sh p =kthread_run (do_scan_async, data,"scsi_scan_%d" , shost->host_no);if (IS_ERR (p))do_scan_async (data); -/* scsi_autopm_put_host(shost) is called in do_scan_async() */ +/* scsi_autopm_put_host(shost) is called in scsi_finish_async_scan() */ }EXPORT_SYMBOL (scsi_scan_host);
Greg KH
maintainerPATCH 63/73 scsi_pm: Fix bug in the SCSI power management handler
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Stern <[email protected]>
commit fea6d607e154cf96ab22254ccb48addfd43d4cb5 upstream.
This patch (as1520) fixes a bug in the SCSI layer's power management implementation.
LUN scanning can be carried out asynchronously in do_scan_async(), and sd uses an asynchronous thread for the time-consuming parts of disk probing in sd_probe_async(). Currently nothing coordinates these async threads with system sleep transitions; they can and do attempt to continue scanning/probing SCSI devices even after the host adapter has been suspended. As one might expect, the outcome is not ideal.
This is what the "prepare" stage of system suspend was created for. After the prepare callback has been called for a host, target, or device, drivers are not allowed to register any children underneath them. Currently the SCSI prepare callback is not implemented; this patch rectifies that omission.
For SCSI hosts, the prepare routine calls scsi_complete_async_scans() to wait until async scanning is finished. It might be slightly more efficient to wait only until the host in question has been scanned, but there's currently no way to do that. Besides, during a sleep transition we will ultimately have to wait until all the host scanning has finished anyway.
For SCSI devices, the prepare routine calls async_synchronize_full() to wait until sd probing is finished. The routine does nothing for SCSI targets, because asynchronous target scanning is done only as part of host scanning.
--- drivers/scsi/scsi_pm.c | 16 ++++++++++++++++ drivers/scsi/scsi_priv.h | 1 + 2 files changed, 17 insertions(+)
drivers/scsi/scsi_pm.c +16 -0
@@ -6,6 +6,7 @@*/ #include <linux/pm_runtime.h> +#include <linux/async.h> #include <scsi/scsi.h> #include <scsi/scsi_device.h>
@@ -68,6 +69,19 @@ static int scsi_bus_resume_common(structreturn err; } +static int scsi_bus_prepare (struct device *dev) +{ +if (scsi_is_sdev_device (dev)) { +/* sd probing uses async_schedule. Wait until it finishes. */ +async_synchronize_full (); + + }else if (scsi_is_host_device (dev)) { +/* Wait until async scanning is finished */ +scsi_complete_async_scans (); + } +return 0 ; +} +static int scsi_bus_suspend (struct device *dev) {return scsi_bus_suspend_common (dev,PMSG_SUSPEND );
@@ -86,6 +100,7 @@ static int scsi_bus_poweroff(struct devi#else /* CONFIG_PM_SLEEP */ #define scsi_bus_resume_common NULL +#define scsi_bus_prepare NULL#define scsi_bus_suspend NULL#define scsi_bus_freeze NULL#define scsi_bus_poweroff NULL
@@ -194,6 +209,7 @@ void scsi_autopm_put_host(struct Scsi_Ho#endif /* CONFIG_PM_RUNTIME */ const struct dev_pm_ops scsi_bus_pm_ops = { + .prepare = scsi_bus_prepare, .suspend = scsi_bus_suspend, .resume = scsi_bus_resume_common, .freeze = scsi_bus_freeze,
drivers/scsi/scsi_priv.h +1 -0
@@ -110,6 +110,7 @@ extern void scsi_exit_procfs(void);#endif /* CONFIG_PROC_FS */ /* scsi_scan.c */ +extern int scsi_complete_async_scans (void );extern int scsi_scan_host_selected (struct Scsi_Host *,unsigned int ,unsigned int ,unsigned int ,int );extern void scsi_forget_host (struct Scsi_Host *);
Greg KH
maintainerPATCH 64/73 ipvs: fix matching of fwmark templates during scheduling
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Horman <[email protected]>
commit e0aac52e17a3db68fe2ceae281780a70fc69957f upstream.
Commit f11017ec2d1859c661f4e2b12c4a8d250e1f47cf (2.6.37)
moved the fwmark variable in subcontext that is invalidated before reaching the ip_vs_ct_in_get call. As vaddr is provided as pointer in the param structure make sure the fwmark variable is in same context. As the fwmark templates can not be matched, more and more template connections are created and the controlled connections can not go to single real server.
--- net/netfilter/ipvs/ip_vs_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/ipvs/ip_vs_core.c +1 -1
@@ -233,6 +233,7 @@ ip_vs_sched_persist(struct ip_vs_service__be16 dport =0 ;/* destination port to forward */ unsigned int flags;struct ip_vs_conn_param param; +const union nf_inet_addr fwmark = { .ip =htonl (svc->fwmark) };union nf_inet_addr snet;/* source network of the client, after masking */
@@ -268,7 +269,6 @@ ip_vs_sched_persist(struct ip_vs_service {int protocol = iph.protocol;const union nf_inet_addr *vaddr = &iph.daddr; -const union nf_inet_addr fwmark = { .ip =htonl (svc->fwmark) };__be16 vport =0 ;if (dst_port == svc->port) {
Greg KH
maintainerPATCH 65/73 jme: Fix FIFO flush issue
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guo-Fu Tseng <[email protected]>
commit ba9adbe67e288823ac1deb7f11576ab5653f833e upstream.
Set the RX FIFO flush watermark lower. According to Federico and JMicron's reply, setting it to 16QW would be stable on most platforms. Otherwise, user might experience packet drop issue.
--- drivers/net/jme.c | 10 +--------- drivers/net/jme.h | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-)
drivers/net/jme.c +1 -9
@@ -2228,19 +2228,11 @@ jme_change_mtu(struct net_device *netdev ((new_mtu) < IPV6_MIN_MTU))return -EINVAL ; -if (new_mtu >4000 ) { - jme->reg_rxcs &= ~RXCS_FIFOTHNP ; - jme->reg_rxcs |=RXCS_FIFOTHNP_64QW ; -jme_restart_rx_engine (jme); - }else { - jme->reg_rxcs &= ~RXCS_FIFOTHNP ; - jme->reg_rxcs |=RXCS_FIFOTHNP_128QW ; -jme_restart_rx_engine (jme); - } netdev->mtu = new_mtu;netdev_update_features (netdev); +jme_restart_rx_engine (jme);jme_reset_link (jme);return 0 ;
drivers/net/jme.h +1 -1
@@ -734,7 +734,7 @@ enum jme_rxcs_values {RXCS_RETRYCNT_60 =0x00000F00 ,RXCS_DEFAULT =RXCS_FIFOTHTP_128T | -RXCS_FIFOTHNP_128QW | +RXCS_FIFOTHNP_16QW |RXCS_DMAREQSZ_128B | RXCS_RETRYGAP_256ns | RXCS_RETRYCNT_32,
Greg KH
maintainerPATCH 66/73 davinci_emac: Do not free all rx dma descriptors during init
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Riesch <[email protected]>
commit 5d69703263d588dbb03f4e57091afd8942d96e6d upstream.
This patch fixes a regression that was introduced by
commit 0a5f38467765ee15478db90d81e40c269c8dda20davinci_emac: Add Carrier Link OK check in Davinci RX Handler
Said commit adds a check whether the carrier link is ok. If the link is not ok, the skb is freed and no new dma descriptor added to the rx dma channel. This causes trouble during initialization when the carrier status has not yet been updated. If a lot of packets are received while netif_carrier_ok returns false, all dma descriptors are freed and the rx dma transfer is stopped.
The bug occurs when the board is connected to a network with lots of traffic and the ifconfig down/up is done, e.g., when reconfiguring the interface with DHCP.
The bug can be reproduced by flood pinging the davinci board while doing ifconfig eth0 down
ifconfig eth0 up
on the board.
After that, the rx path stops working and the overrun value reported by ifconfig is counting up.
This patch reverts commit 0a5f38467765ee15478db90d81e40c269c8dda20 and instead issues warnings only if cpdma_chan_submit returns -ENOMEM.
--- drivers/net/davinci_emac.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/davinci_emac.c +4 -2
@@ -1008,7 +1008,7 @@ static void emac_rx_handler(void *token,int ret;/* free and bail if we are shutting down */ -if (unlikely (!netif_running (ndev) || !netif_carrier_ok (ndev))) { +if (unlikely (!netif_running (ndev))) {dev_kfree_skb_any (skb);return ; }
@@ -1037,7 +1037,9 @@ static void emac_rx_handler(void *token, recycle: ret =cpdma_chan_submit (priv->rxchan, skb, skb->data,skb_tailroom (skb),GFP_KERNEL ); -if (WARN_ON (ret <0 )) + +WARN_ON (ret == -ENOMEM ); +if (unlikely (ret <0 ))dev_kfree_skb_any (skb); }
Greg KH
maintainerPATCH 67/73 builddeb: Dont create files in /tmp with predictable names
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Hutchings <[email protected]>
commit 6c635224602d760c1208ada337562f40d8ae93a5 upstream.
The current use of /tmp for file lists is insecure. Put them under $objtree/debian instead.
--- scripts/package/builddeb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
scripts/package/builddeb +6 -6
@@ -238,14 +238,14 @@ EOF fi # Build header package -(cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > /tmp/files$$) -(cd $srctree; find arch/$SRCARCH/include include scripts -type f >> /tmp/files$$) -(cd $objtree; find .config Module.symvers include scripts -type f >> /tmp/objfiles$$) +(cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") +(cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles") +(cd $objtree; find .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") destdir=$kernel_headers_dir/usr/src/linux-headers-$version mkdir -p "$destdir" -(cd $srctree; tar -c -f - -T /tmp/files$$) | (cd $destdir; tar -xf -) -(cd $objtree; tar -c -f - -T /tmp/objfiles$$) | (cd $destdir; tar -xf -) -rm -f /tmp/files$$ /tmp/objfiles$$ +(cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -) +(cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -) +rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" arch=$(dpkg --print-architecture) cat <<EOF >> debian/control
Greg KH
maintainerPATCH 68/73 hdpvr: fix race conditon during start of streaming
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Janne Grunau <[email protected]>
commit afa159538af61f1a65d48927f4e949fe514fb4fc upstream.
status has to be set to STREAMING before the streaming worker is queued. hdpvr_transmit_buffers() will exit immediately otherwise.
--- drivers/media/video/hdpvr/hdpvr-video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/media/video/hdpvr/hdpvr-video.c +2 -1
@@ -284,12 +284,13 @@ static int hdpvr_start_streaming(structhdpvr_config_call (dev,CTRL_START_STREAMING_VALUE ,0x00 ); + dev->status =STATUS_STREAMING ; +INIT_WORK (&dev->worker, hdpvr_transmit_buffers);queue_work (dev->workqueue, &dev->worker);v4l2_dbg (MSG_BUFFER , hdpvr_debug, &dev->v4l2_dev,"streaming started\n" ); - dev->status =STATUS_STREAMING ;return 0 ; }
Greg KH
maintainerPATCH 69/73 hwmon: (f75375s) Fix register write order when setting fans to full speed
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolaus Schulz <[email protected]>
commit c1c1a3d012fe5e82a9a025fb4b5a4f8ee67a53f6 upstream.
By hwmon sysfs interface convention, setting pwm_enable to zero sets a fan to full speed. In the f75375s driver, this need be done by enabling manual fan control, plus duty mode for the F875387 chip, and then setting the maximum duty cycle. Fix a bug where the two necessary register writes were swapped, effectively discarding the setting to full-speed.
--- drivers/hwmon/f75375s.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/hwmon/f75375s.c +3 -2
@@ -304,8 +304,6 @@ static int set_pwm_enable_direct(structcase 0 :/* Full speed */ fanmode |= (3 <<FAN_CTRL_MODE (nr)); data->pwm[nr] =255 ; -f75375_write8 (client,F75375_REG_FAN_PWM_DUTY (nr), - data->pwm[nr]);break ;case 1 :/* PWM */ fanmode |= (3 <<FAN_CTRL_MODE (nr));
@@ -318,6 +316,9 @@ static int set_pwm_enable_direct(struct }f75375_write8 (client,F75375_REG_FAN_TIMER , fanmode); data->pwm_enable[nr] = val; +if (val ==0 ) +f75375_write8 (client,F75375_REG_FAN_PWM_DUTY (nr), + data->pwm[nr]);return 0 ; }
Greg KH
maintainerPATCH 70/73 epoll: introduce POLLFREE to flush ->signalfd_wqh before kfree()
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <[email protected]>
commit d80e731ecab420ddcb79ee9d0ac427acbc187b4b upstream.
This patch is intentionally incomplete to simplify the review. It ignores ep_unregister_pollwait() which plays with the same wqh. See the next change.
epoll assumes that the EPOLL_CTL_ADD'ed file controls everything f_op->poll() needs. In particular it assumes that the wait queue can't go away until eventpoll_release(). This is not true in case of signalfd, the task which does EPOLL_CTL_ADD uses its ->sighand which is not connected to the file.
This patch adds the special event, POLLFREE, currently only for epoll. It expects that init_poll_funcptr()'ed hook should do the necessary cleanup. Perhaps it should be defined as EPOLLFREE in eventpoll.
__cleanup_sighand() is changed to do wake_up_poll(POLLFREE) if ->signalfd_wqh is not empty, we add the new signalfd_cleanup() helper.
ep_poll_callback(POLLFREE) simply does list_del_init(task_list). This make this poll entry inconsistent, but we don't care. If you share epoll fd which contains our sigfd with another process you should blame yourself. signalfd is "really special". I simply do not know how we can define the "right" semantics if it used with epoll.
The main problem is, epoll calls signalfd_poll() once to establish the connection with the wait queue, after that signalfd_poll(NULL) returns the different/inconsistent results depending on who does EPOLL_CTL_MOD/signalfd_read/etc. IOW: apart from sigmask, signalfd has nothing to do with the file, it works with the current thread.
In short: this patch is the hack which tries to fix the symptoms. It also assumes that nobody can take tasklist_lock under epoll locks, this seems to be true.
Note:
- we do not have wake_up_all_poll() but wake_up_poll() is fine, poll/epoll doesn't use WQ_FLAG_EXCLUSIVE.
- signalfd_cleanup() uses POLLHUP along with POLLFREE, we need a couple of simple changes in eventpoll.c to make sure it can't be "lost".
--- fs/eventpoll.c | 4 ++++ fs/signalfd.c | 11 +++++++++++ include/asm-generic/poll.h | 2 ++ include/linux/signalfd.h | 5 ++++- kernel/fork.c | 5 ++++- 5 files changed, 25 insertions(+), 2 deletions(-)
fs/eventpoll.c +4 -0
@@ -827,6 +827,10 @@ static int ep_poll_callback(wait_queue_tstruct epitem *epi =ep_item_from_wait (wait);struct eventpoll *ep = epi->ep; +/* the caller holds eppoll_entry->whead->lock */ +if ((unsigned long )key &POLLFREE ) +list_del_init (&wait->task_list); +spin_lock_irqsave (&ep->lock, flags);/*
fs/signalfd.c +11 -0
@@ -30,6 +30,17 @@#include <linux/signalfd.h> #include <linux/syscalls.h> +void signalfd_cleanup (struct sighand_struct *sighand) +{ +wait_queue_head_t *wqh = &sighand->signalfd_wqh; + +if (likely (!waitqueue_active (wqh))) +return ; + +/* wait_queue_t->func(POLLFREE) should do remove_wait_queue() */ +wake_up_poll (wqh,POLLHUP |POLLFREE ); +} +struct signalfd_ctx {sigset_t sigmask; };
include/asm-generic/poll.h +2 -0
@@ -28,6 +28,8 @@#define POLLRDHUP 0x2000#endif +#define POLLFREE 0x4000/* currently only for epoll */ +struct pollfd {int fd;short events;
include/linux/signalfd.h +4 -1
@@ -61,13 +61,16 @@ static inline void signalfd_notify(strucwake_up (&tsk->sighand->signalfd_wqh); } +extern void signalfd_cleanup (struct sighand_struct *sighand); +#else /* CONFIG_SIGNALFD */ static inline void signalfd_notify (struct task_struct *tsk,int sig) { } +static inline void signalfd_cleanup (struct sighand_struct *sighand) { } +#endif /* CONFIG_SIGNALFD */ #endif /* __KERNEL__ */ #endif /* _LINUX_SIGNALFD_H */ -
kernel/fork.c +4 -1
@@ -67,6 +67,7 @@#include <linux/user-return-notifier.h> #include <linux/oom.h> #include <linux/khugepaged.h> +#include <linux/signalfd.h> #include <asm/pgtable.h> #include <asm/pgalloc.h>
@@ -917,8 +918,10 @@ static int copy_sighand(unsigned long clvoid __cleanup_sighand (struct sighand_struct *sighand) { -if (atomic_dec_and_test (&sighand->count)) +if (atomic_dec_and_test (&sighand->count)) { +signalfd_cleanup (sighand);kmem_cache_free (sighand_cachep, sighand); + } }
Greg KH
maintainerPATCH 71/73 epoll: ep_unregister_pollwait() can use the freed pwq->whead
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <[email protected]>
commit 971316f0503a5c50633d07b83b6db2f15a3a5b00 upstream.
signalfd_cleanup() ensures that ->signalfd_wqh is not used, but this is not enough. eppoll_entry->whead still points to the memory we are going to free, ep_unregister_pollwait()->remove_wait_queue() is obviously unsafe.
Change ep_poll_callback(POLLFREE) to set eppoll_entry->whead = NULL, change ep_unregister_pollwait() to check pwq->whead != NULL under rcu_read_lock() before remove_wait_queue(). We add the new helper, ep_remove_wait_queue(), for this.
This works because sighand_cachep is SLAB_DESTROY_BY_RCU and because ->signalfd_wqh is initialized in sighand_ctor(), not in copy_sighand. ep_unregister_pollwait()->remove_wait_queue() can play with already freed and potentially reused ->sighand, but this is fine. This memory must have the valid ->signalfd_wqh until rcu_read_unlock().
--- fs/eventpoll.c | 30 +++++++++++++++++++++++++++--- fs/signalfd.c | 6 +++++- 2 files changed, 32 insertions(+), 4 deletions(-)
fs/eventpoll.c +27 -3
@@ -299,6 +299,11 @@ static inline int ep_is_linked(struct lireturn !list_empty (p); } +static inline struct eppoll_entry *ep_pwq_from_wait (wait_queue_t *p) +{ + return container_of(p, struct eppoll_entry, wait); +} +/* Get the "struct epitem" from a wait queue pointer */ static inline struct epitem *ep_item_from_wait (wait_queue_t *p) {
@@ -446,6 +451,18 @@ static void ep_poll_safewake(wait_queue_put_cpu (); } +static void ep_remove_wait_queue (struct eppoll_entry *pwq) +{ +wait_queue_head_t *whead; + +rcu_read_lock (); +/* If it is cleared by POLLFREE, it should be rcu-safe */ + whead =rcu_dereference (pwq->whead); +if (whead) +remove_wait_queue (whead, &pwq->wait); +rcu_read_unlock (); +} +/* * This function unregisters poll callbacks from the associated file * descriptor. Must be called with "mtx" held (or "epmutex" if called from
@@ -460,7 +477,7 @@ static void ep_unregister_pollwait(struc pwq = list_first_entry(lsthead, struct eppoll_entry, llink);list_del (&pwq->llink); -remove_wait_queue (pwq->whead, &pwq->wait); +ep_remove_wait_queue (pwq);kmem_cache_free (pwq_cache, pwq); } }
@@ -827,9 +844,16 @@ static int ep_poll_callback(wait_queue_tstruct epitem *epi =ep_item_from_wait (wait);struct eventpoll *ep = epi->ep; -/* the caller holds eppoll_entry->whead->lock */ -if ((unsigned long )key &POLLFREE ) +if ((unsigned long )key &POLLFREE ) { +ep_pwq_from_wait (wait)->whead =NULL ; +/* +* whead = NULL above can race with ep_remove_wait_queue() +* which can do another remove_wait_queue() after us, so we +* can't use __remove_wait_queue(). whead->lock is held by +* the caller. +*/ list_del_init (&wait->task_list); + }spin_lock_irqsave (&ep->lock, flags);
fs/signalfd.c +5 -1
@@ -33,7 +33,11 @@void signalfd_cleanup (struct sighand_struct *sighand) {wait_queue_head_t *wqh = &sighand->signalfd_wqh; - +/* +* The lockless check can race with remove_wait_queue() in progress, +* but in this case its caller should run under rcu_read_lock() and +* sighand_cachep is SLAB_DESTROY_BY_RCU, we can safely return. +*/ if (likely (!waitqueue_active (wqh)))return ;
Greg KH
maintainerPATCH 72/73 epoll: limit paths
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Baron <[email protected]>
commit 28d82dc1c4edbc352129f97f4ca22624d1fe61de upstream.
The current epoll code can be tickled to run basically indefinitely in both loop detection path check (on ep_insert()), and in the wakeup paths. The programs that tickle this behavior set up deeply linked networks of epoll file descriptors that cause the epoll algorithms to traverse them indefinitely. A couple of these sample programs have been previously posted in this thread: https://lkml.org/lkml/2011/2/25/297.
To fix the loop detection path check algorithms, I simply keep track of the epoll nodes that have been already visited. Thus, the loop detection becomes proportional to the number of epoll file descriptor and links. This dramatically decreases the run-time of the loop check algorithm. In one diabolical case I tried it reduced the run-time from 15 mintues (all in kernel time) to .3 seconds.
Fixing the wakeup paths could be done at wakeup time in a similar manner by keeping track of nodes that have already been visited, but the complexity is harder, since there can be multiple wakeups on different cpus...Thus, I've opted to limit the number of possible wakeup paths when the paths are created.
This is accomplished, by noting that the end file descriptor points that are found during the loop detection pass (from the newly added link), are actually the sources for wakeup events. I keep a list of these file descriptors and limit the number and length of these paths that emanate from these 'source file descriptors'. In the current implemetation I allow 1000 paths of length 1, 500 of length 2, 100 of length 3, 50 of length 4 and 10 of length 5. Note that it is sufficient to check the 'source file descriptors' reachable from the newly added link, since no other 'source file descriptors' will have newly added links. This allows us to check only the wakeup paths that may have gotten too long, and not re-check all possible wakeup paths on the system.
In terms of the path limit selection, I think its first worth noting that the most common case for epoll, is probably the model where you have 1 epoll file descriptor that is monitoring n number of 'source file descriptors'. In this case, each 'source file descriptor' has a 1 path of length 1. Thus, I believe that the limits I'm proposing are quite reasonable and in fact may be too generous. Thus, I'm hoping that the proposed limits will not prevent any workloads that currently work to fail.
In terms of locking, I have extended the use of the 'epmutex' to all epoll_ctl add and remove operations. Currently its only used in a subset of the add paths. I need to hold the epmutex, so that we can correctly traverse a coherent graph, to check the number of paths. I believe that this additional locking is probably ok, since its in the setup/teardown paths, and doesn't affect the running paths, but it certainly is going to add some extra overhead. Also, worth noting is that the epmuex was recently added to the ep_ctl add operations in the initial path loop detection code using the argument that it was not on a critical path.
Another thing to note here, is the length of epoll chains that is allowed. Currently, eventpoll.c defines:
/* Maximum number of nesting allowed inside epoll sets */ #define EP_MAX_NESTS 4
This basically means that I am limited to a graph depth of 5 (EP_MAX_NESTS
+ 1). However, this limit is currently only enforced during the loop check detection code, and only when the epoll file descriptors are added in a certain order. Thus, this limit is currently easily bypassed. The newly added check for wakeup paths, stricly limits the wakeup paths to a length of 5, regardless of the order in which ep's are linked together. Thus, a side-effect of the new code is a more consistent enforcement of the graph depth.
Thus far, I've tested this, using the sample programs previously mentioned, which now either return quickly or return -EINVAL. I've also testing using the piptest.c epoll tester, which showed no difference in performance. I've also created a number of different epoll networks and tested that they behave as expectded.
I believe this solves the original diabolical test cases, while still preserving the sane epoll nesting.
--- fs/eventpoll.c | 234 +++++++++++++++++++++++++++++++++++++++++----- include/linux/eventpoll.h | 1 include/linux/fs.h | 1 3 files changed, 211 insertions(+), 25 deletions(-)
fs/eventpoll.c +209 -25
@@ -197,6 +197,12 @@ struct eventpoll {/* The user that created the eventpoll descriptor */ struct user_struct *user; + +struct file *file; + +/* used to optimize loop detection check */ +int visited; +struct list_head visited_list_link; };/* Wait structure used by the poll hooks */
@@ -255,6 +261,15 @@ static struct kmem_cache *epi_cache __re/* Slab cache used to allocate "struct eppoll_entry" */ static struct kmem_cache *pwq_cache__read_mostly ; +/* Visited nodes during ep_loop_check(), so we can unset them when we finish */ +static LIST_HEAD (visited_list); + +/* +* List of files with newly added links, where we may need to limit the number +* of emanating paths. Protected by the epmutex. +*/ +static LIST_HEAD (tfile_check_list); +#ifdef CONFIG_SYSCTL #include <linux/sysctl.h>
@@ -276,6 +291,12 @@ ctl_table epoll_table[] = { };#endif /* CONFIG_SYSCTL */ +static const struct file_operations eventpoll_fops; + +static inline int is_file_epoll (struct file *f) +{ +return f->f_op == &eventpoll_fops; +}/* Setup the structure that is used as key for the RB tree */ static inline void ep_set_ffd(struct epoll_filefd *ffd,
@@ -728,12 +749,6 @@ static const struct file_operations even .llseek = noop_llseek, }; -/* Fast test to see if the file is an evenpoll file */ -static inline int is_file_epoll (struct file *f) -{ -return f->f_op == &eventpoll_fops; -} -/* * This is called from eventpoll_release() to unlink files from the eventpoll * interface. We need to have this facility to cleanup correctly files that are
@@ -954,6 +969,99 @@ static void ep_rbtree_insert(struct evenrb_insert_color (&epi->rbn, &ep->rbr); } + + +#define PATH_ARR_SIZE 5 +/* +* These are the number paths of length 1 to 5, that we are allowing to emanate +* from a single file of interest. For example, we allow 1000 paths of length +* 1, to emanate from each file of interest. This essentially represents the +* potential wakeup paths, which need to be limited in order to avoid massive +* uncontrolled wakeup storms. The common use case should be a single ep which +* is connected to n file sources. In this case each file source has 1 path +* of length 1. Thus, the numbers below should be more than sufficient. These +* path limits are enforced during an EPOLL_CTL_ADD operation, since a modify +* and delete can't add additional paths. Protected by the epmutex. +*/ +static const int path_limits[PATH_ARR_SIZE ] = {1000 ,500 ,100 ,50 ,10 }; +static int path_count[PATH_ARR_SIZE ]; + +static int path_count_inc (int nests) +{ +if (++path_count[nests] > path_limits[nests]) +return -1 ; +return 0 ; +} + +static void path_count_init (void ) +{ +int i; + +for (i =0 ; i <PATH_ARR_SIZE ; i++) + path_count[i] =0 ; +} + +static int reverse_path_check_proc (void *priv,void *cookie,int call_nests) +{ +int error =0 ; +struct file *file = priv; +struct file *child_file; +struct epitem *epi; + +list_for_each_entry (epi, &file->f_ep_links, fllink) { + child_file = epi->ep->file; +if (is_file_epoll (child_file)) { +if (list_empty (&child_file->f_ep_links)) { +if (path_count_inc (call_nests)) { + error =-1 ; +break ; + } + }else { + error =ep_call_nested (&poll_loop_ncalls, +EP_MAX_NESTS , + reverse_path_check_proc, + child_file, child_file, + current); + } +if (error !=0 ) +break ; + }else { +printk (KERN_ERR "reverse_path_check_proc: " +"file is not an ep!\n" ); + } + } +return error; +} + +/** +* reverse_path_check - The tfile_check_list is list of file *, which have +* links that are proposed to be newly added. We need to +* make sure that those added links don't add too many +* paths such that we will spend all our time waking up +* eventpoll objects. +* +* Returns: Returns zero if the proposed links don't create too many paths, +* -1 otherwise. +*/ +static int reverse_path_check (void ) +{ +int length =0 ; +int error =0 ; +struct file *current_file; + +/* let's call this for all tfiles */ +list_for_each_entry (current_file, &tfile_check_list, f_tfile_llink) { + length++; +path_count_init (); + error =ep_call_nested (&poll_loop_ncalls,EP_MAX_NESTS , + reverse_path_check_proc, current_file, + current_file, current); +if (error) +break ; + } +return error; +} +/* * Must be called with "mtx" held. */
@@ -1015,6 +1123,11 @@ static int ep_insert(struct eventpoll *e*/ ep_rbtree_insert (ep, epi); +/* now check if we've created too many backpaths */ + error = -EINVAL ; +if (reverse_path_check ()) + goto error_remove_epi; +/* We have to drop the new item inside our item list to keep track of it */ spin_lock_irqsave (&ep->lock, flags);
@@ -1039,6 +1152,14 @@ static int ep_insert(struct eventpoll *ereturn 0 ; +error_remove_epi: +spin_lock (&tfile->f_lock); +if (ep_is_linked (&epi->fllink)) +list_del_init (&epi->fllink); +spin_unlock (&tfile->f_lock); + +rb_erase (&epi->rbn, &ep->rbr); + error_unregister:ep_unregister_pollwait (ep, epi);
@@ -1303,18 +1424,36 @@ static int ep_loop_check_proc(void *privint error =0 ;struct file *file = priv;struct eventpoll *ep = file->private_data; +struct eventpoll *ep_tovisit;struct rb_node *rbp;struct epitem *epi;mutex_lock_nested (&ep->mtx, call_nests +1 ); + ep->visited =1 ; +list_add (&ep->visited_list_link, &visited_list);for (rbp =rb_first (&ep->rbr); rbp; rbp =rb_next (rbp)) { epi = rb_entry(rbp, struct epitem, rbn);if (unlikely (is_file_epoll (epi->ffd.file))) { + ep_tovisit = epi->ffd.file->private_data; +if (ep_tovisit->visited) +continue ; error =ep_call_nested (&poll_loop_ncalls,EP_MAX_NESTS , - ep_loop_check_proc, epi->ffd.file, - epi->ffd.file->private_data, current); + ep_loop_check_proc, epi->ffd.file, + ep_tovisit, current);if (error !=0 )break ; + }else { +/* +* If we've reached a file that is not associated with +* an ep, then we need to check if the newly added +* links are going to add too many wakeup paths. We do +* this by adding it to the tfile_check_list, if it's +* not already there, and calling reverse_path_check() +* during ep_insert(). +*/ +if (list_empty (&epi->ffd.file->f_tfile_llink)) +list_add (&epi->ffd.file->f_tfile_llink, + &tfile_check_list); } }mutex_unlock (&ep->mtx);
@@ -1335,8 +1474,31 @@ static int ep_loop_check_proc(void *priv*/ static int ep_loop_check (struct eventpoll *ep,struct file *file) { -return ep_call_nested (&poll_loop_ncalls,EP_MAX_NESTS , +int ret; +struct eventpoll *ep_cur, *ep_next; + + ret =ep_call_nested (&poll_loop_ncalls,EP_MAX_NESTS , ep_loop_check_proc, file, ep, current); +/* clear visited list */ +list_for_each_entry_safe (ep_cur, ep_next, &visited_list, + visited_list_link) { + ep_cur->visited =0 ; +list_del (&ep_cur->visited_list_link); + } +return ret; +} + +static void clear_tfile_check_list (void ) +{ +struct file *file; + +/* first clear the tfile_check_list */ +while (!list_empty (&tfile_check_list)) { + file = list_first_entry(&tfile_check_list, struct file, + f_tfile_llink); +list_del_init (&file->f_tfile_llink); + } +INIT_LIST_HEAD (&tfile_check_list); }/*
@@ -1344,8 +1506,9 @@ static int ep_loop_check(struct eventpol*/ SYSCALL_DEFINE1(epoll_create1, int, flags) { -int error; +int error, fd;struct eventpoll *ep =NULL ; +struct file *file;/* Check the EPOLL_* constant for consistency. */ BUILD_BUG_ON (EPOLL_CLOEXEC !=O_CLOEXEC );
@@ -1362,11 +1525,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flag* Creates all the items needed to setup an eventpoll file. That is, * a file structure and a free file descriptor. */ - error =anon_inode_getfd ("[eventpoll]" , &eventpoll_fops, ep, + fd =get_unused_fd_flags (O_RDWR | (flags &O_CLOEXEC )); +if (fd <0 ) { + error = fd; + goto out_free_ep; + } + file =anon_inode_getfile ("[eventpoll]" , &eventpoll_fops, ep,O_RDWR | (flags &O_CLOEXEC )); -if (error <0 ) -ep_free (ep); - +if (IS_ERR (file)) { + error =PTR_ERR (file); + goto out_free_fd; + } +fd_install (fd, file); + ep->file = file; +return fd; + +out_free_fd: +put_unused_fd (fd); +out_free_ep: +ep_free (ep);return error; }
@@ -1432,21 +1609,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, in/* * When we insert an epoll file descriptor, inside another epoll file * descriptor, there is the change of creating closed loops, which are -* better be handled here, than in more critical paths. +* better be handled here, than in more critical paths. While we are +* checking for loops we also determine the list of files reachable +* and hang them on the tfile_check_list, so we can check that we +* haven't created too many possible wakeup paths. * -* We hold epmutex across the loop check and the insert in this case, in -* order to prevent two separate inserts from racing and each doing the -* insert "at the same time" such that ep_loop_check passes on both -* before either one does the insert, thereby creating a cycle. +* We need to hold the epmutex across both ep_insert and ep_remove +* b/c we want to make sure we are looking at a coherent view of +* epoll network. */ -if (unlikely (is_file_epoll (tfile) && op ==EPOLL_CTL_ADD )) { +if (op ==EPOLL_CTL_ADD || op ==EPOLL_CTL_DEL ) {mutex_lock (&epmutex); did_lock_epmutex =1 ; - error = -ELOOP ; -if (ep_loop_check (ep, tfile) !=0 ) - goto error_tgt_fput; } - +if (op ==EPOLL_CTL_ADD ) { +if (is_file_epoll (tfile)) { + error = -ELOOP ; +if (ep_loop_check (ep, tfile) !=0 ) + goto error_tgt_fput; + }else +list_add (&tfile->f_tfile_llink, &tfile_check_list); + }mutex_lock_nested (&ep->mtx,0 );
@@ -1465,6 +1648,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, in error =ep_insert (ep, &epds, tfile, fd); }else error = -EEXIST ; +clear_tfile_check_list ();break ;case EPOLL_CTL_DEL :if (epi)
@@ -1483,7 +1667,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, inmutex_unlock (&ep->mtx); error_tgt_fput: -if (unlikely (did_lock_epmutex)) +if (did_lock_epmutex)mutex_unlock (&epmutex);fput (tfile);
include/linux/eventpoll.h +1 -0
@@ -61,6 +61,7 @@ struct file;static inline void eventpoll_init_file (struct file *file) {INIT_LIST_HEAD (&file->f_ep_links); +INIT_LIST_HEAD (&file->f_tfile_llink); }
include/linux/fs.h +1 -0
@@ -969,6 +969,7 @@ struct file {#ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_head f_ep_links; +struct list_head f_tfile_llink;#endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping;#ifdef CONFIG_DEBUG_WRITECOUNT
Greg KH
maintainerPATCH 73/73 cdrom: use copy_to_user() without the underscores
In reply to Greg KH3.0-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
commit 822bfa51ce44f2c63c300fdb76dc99c4d5a5ca9f upstream.
"nframes" comes from the user and "nframes * CD_FRAMESIZE_RAW" can wrap on 32 bit systems. That would have been ok if we used the same wrapped value for the copy, but we use a shifted value. We should just use the checked version of copy_to_user() because it's not going to make a difference to the speed.
--- drivers/cdrom/cdrom.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
drivers/cdrom/cdrom.c +1 -7
@@ -2114,11 +2114,6 @@ static int cdrom_read_cdda_old(struct cdif (!nr)return -ENOMEM ; -if (!access_ok (VERIFY_WRITE , ubuf, nframes *CD_FRAMESIZE_RAW )) { - ret = -EFAULT ; - goto out; - } - cgc.data_direction =CGC_DATA_READ ;while (nframes >0 ) {if (nr > nframes)
@@ -2127,7 +2122,7 @@ static int cdrom_read_cdda_old(struct cd ret =cdrom_read_block (cdi, &cgc, lba, nr,1 ,CD_FRAMESIZE_RAW );if (ret)break ; -if (__copy_to_user (ubuf, cgc.buffer,CD_FRAMESIZE_RAW * nr)) { +if (copy_to_user (ubuf, cgc.buffer,CD_FRAMESIZE_RAW * nr)) { ret = -EFAULT ;break ; }
@@ -2135,7 +2130,6 @@ static int cdrom_read_cdda_old(struct cd nframes -= nr; lba += nr; } -out:kfree (cgc.buffer);return ret; }