I am announcing the review cycle for the 3.5.7.10 stable release. This new
release contains 102 patches, which are posted as a response to this
message. They are also available at the following repository:
git://kernel.ubuntu.com/ubuntu/linux.git linux-3.5.y-review
If there are any problems, or if anything is missing, please answer to
this or to any of the followup patches. Note that any answer should be
made at maximum in 3 days, after that the final release of 3.5.7.10 will be
made.
For more information about the 3.5.y.z extended stable tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
Included below are the diffstat and shortlog for this release.
-Luis
--
arch/arm/mach-cns3xxx/core.c | 16 +-
arch/arm/mach-cns3xxx/include/mach/cns3xxx.h | 16 +-
arch/tile/kernel/setup.c | 25 ++-
drivers/base/regmap/regcache-rbtree.c | 2 +-
drivers/block/aoe/aoecmd.c | 3 +-
drivers/block/loop.c | 9 +-
drivers/block/xen-blkback/blkback.c | 38 +++-
drivers/block/xen-blkback/common.h | 25 +++
drivers/bluetooth/ath3k.c | 4 +
drivers/bluetooth/btusb.c | 2 +
drivers/char/virtio_console.c | 21 +-
drivers/firmware/efivars.c | 93 ++++++++-
drivers/gpu/drm/i915/intel_opregion.c | 23 ++-
drivers/hid/hid-ids.h | 6 +
drivers/hid/usbhid/hid-quirks.c | 2 +
drivers/infiniband/ulp/ipoib/ipoib_cm.c | 8 +-
drivers/iommu/amd_iommu.c | 22 +--
drivers/net/bonding/bond_main.c | 91 +++------
drivers/net/bonding/bond_sysfs.c | 121 ++++++------
drivers/net/can/sja1000/plx_pci.c | 4 +-
drivers/net/can/sja1000/sja1000.c | 6 +-
drivers/net/can/sja1000/sja1000.h | 2 +-
drivers/net/ethernet/atheros/atl1e/atl1e.h | 1 -
drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 19 +-
drivers/net/ethernet/broadcom/tg3.c | 7 +-
drivers/net/ethernet/davicom/dm9000.c | 214 +++++++++++----------
drivers/net/ethernet/davicom/dm9000.h | 11 +-
drivers/net/ethernet/marvell/sky2.c | 2 +-
drivers/net/ethernet/marvell/sky2.h | 2 +-
drivers/net/ethernet/micrel/ks8851.c | 2 +-
.../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 4 +-
drivers/net/ethernet/ti/cpsw.c | 2 +-
drivers/net/ethernet/ti/davinci_emac.c | 2 +-
drivers/net/usb/smsc75xx.c | 12 +-
drivers/net/wireless/ath/ath9k/ar9003_calib.c | 4 +
drivers/net/wireless/ath/ath9k/xmit.c | 26 +--
drivers/net/wireless/b43/dma.c | 65 +++++--
drivers/net/wireless/b43/phy_n.c | 8 +-
drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 9 +
drivers/net/wireless/iwlwifi/iwl-ucode.c | 4 +-
drivers/net/wireless/mwifiex/init.c | 8 +
drivers/net/wireless/rtlwifi/usb.c | 1 +
drivers/staging/comedi/drivers/s626.c | 2 +-
drivers/thermal/thermal_sys.c | 1 +
drivers/tty/serial/atmel_serial.c | 11 +-
drivers/tty/vt/vc_screen.c | 6 +-
drivers/usb/host/xhci-ring.c | 24 +--
drivers/usb/host/xhci.h | 4 +
drivers/usb/serial/ark3116.c | 10 +-
drivers/usb/serial/ch341.c | 11 +-
drivers/usb/serial/cypress_m8.c | 14 +-
drivers/usb/serial/f81232.c | 9 +-
drivers/usb/serial/ftdi_sio.c | 20 +-
drivers/usb/serial/ftdi_sio_ids.h | 7 +
drivers/usb/serial/io_edgeport.c | 12 +-
drivers/usb/serial/io_ti.c | 12 +-
drivers/usb/serial/mct_u232.c | 14 +-
drivers/usb/serial/mos7840.c | 16 +-
drivers/usb/serial/oti6858.c | 10 +-
drivers/usb/serial/pl2303.c | 11 +-
drivers/usb/serial/quatech2.c | 12 +-
drivers/usb/serial/spcp8x5.c | 9 +-
drivers/usb/serial/ssu100.c | 12 +-
drivers/usb/serial/ti_usb_3410_5052.c | 10 +-
drivers/usb/serial/usb-serial.c | 1 +
fs/block_dev.c | 1 +
fs/btrfs/extent-tree.c | 49 ++++-
fs/btrfs/extent_io.c | 33 ++++
fs/btrfs/extent_io.h | 2 +
fs/btrfs/inode.c | 14 ++
fs/btrfs/scrub.c | 3 +-
fs/btrfs/tree-log.c | 5 +-
fs/dcache.c | 16 +-
fs/nfs/blocklayout/blocklayoutdm.c | 4 +-
fs/nfs/idmap.c | 13 +-
fs/nfs/nfs4proc.c | 14 --
fs/nfs/pnfs.c | 19 +-
fs/nfsd/nfs4xdr.c | 2 +-
fs/reiserfs/xattr.c | 4 +-
fs/sysfs/dir.c | 17 +-
fs/ubifs/super.c | 12 +-
fs/udf/udf_sb.h | 2 +-
include/linux/thermal.h | 2 +-
include/linux/unix_diag.h | 4 +-
include/linux/usb/serial.h | 2 +
include/xen/interface/io/blkif.h | 10 +
kernel/time/tick-broadcast.c | 3 +-
kernel/time/tick-sched.c | 5 +
kernel/trace/trace.c | 50 +++--
kernel/trace/trace.h | 7 +
kernel/trace/trace_irqsoff.c | 19 +-
kernel/trace/trace_sched_wakeup.c | 18 +-
mm/mmap.c | 2 +-
mm/nommu.c | 2 +-
net/8021q/vlan.c | 14 +-
net/bluetooth/sco.c | 1 +
net/core/dev.c | 7 +-
net/ipv4/tcp_input.c | 7 +-
net/ipv4/tcp_output.c | 7 +-
net/ipv6/addrconf.c | 26 +--
net/ipv6/ip6_input.c | 21 ++
net/irda/af_irda.c | 6 +-
net/mac80211/sta_info.c | 12 +-
net/netlink/genetlink.c | 1 +
net/sunrpc/sched.c | 9 +-
net/unix/af_unix.c | 7 +-
106 files changed, 1043 insertions(+), 589 deletions(-)
Al Viro (2):
Nest rename_lock inside vfsmount_lock
vt: synchronize_rcu() under spinlock is not nice...
Amit Shah (2):
virtio: console: rename cvq_lock to c_ivq_lock
virtio: console: add locking around c_ovq operations
Anatol Pomozov (1):
loop: prevent bdev freeing while device in use
Andrey Vagin (1):
net: fix *_DIAG_MAX constants
Artem Bityutskiy (1):
UBIFS: make space fixup work in the remount case
Bing Zhao (1):
mwifiex: cancel cmd timer and free curr_cmd in shutdown process
Chris Mason (1):
Btrfs: fix race between mmap writes and compression
Chris Metcalf (1):
tile: expect new initramfs name from hypervisor file system
Cong Wang (1):
8021q: fix a potential use-after-free
David Vrabel (1):
xen/blkback: correctly respond to unknown, non-native requests
Emmanuel Grumbach (1):
iwlwifi: dvm: don't send HCMD in restart flow
Eric Dumazet (4):
net: remove a WARN_ON() in net_enable_timestamp()
tcp: preserve ACK clocking in TSO
aoe: reserve enough headroom on skbs
net: add a synchronize_net() in netdev_rx_handler_unregister()
Felix Fietkau (2):
ath9k_hw: revert chainmask to user configuration after calibration
ath9k: limit tx path hang check to normal data queues
Frederic Weisbecker (1):
nohz: Make tick_nohz_irq_exit() irq safe
Hannes Frederic Sowa (3):
atl1e: drop pci-msi support because of packet corruption
ipv6: don't accept multicast traffic with scope 0
ipv6: don't accept node local multicast traffic from the wire
Hong Zhiguo (1):
ipv6: fix bad free of addrconf_init_net
Ian Abbott (1):
staging: comedi: s626: fix continuous acquisition
Iestyn C. Elfick (1):
b43: A fix for DMA transmission sequence errors
J. Bruce Fields (1):
nfsd4: reject "negative" acl lengths
Jan Beulich (1):
xen-blkback: fix dispatch_rw_block_io() error path
Jan Kara (2):
udf: Fix bitmap overflow on large filesystems with small block size
reiserfs: Fix warning and inode leak when deleting inode with xattrs
Jan Stancek (1):
mm: prevent mmap_cache race in find_vma()
Jiri Kosina (1):
HID: usbhid: fix build problem
Joerg Roedel (1):
iommu/amd: Make sure dma_ops are set for hotplug devices
Johan Hovold (17):
USB: serial: add modem-status-change wait queue
USB: ark3116: fix use-after-free in TIOCMIWAIT
USB: ch341: fix use-after-free in TIOCMIWAIT
USB: cypress_m8: fix use-after-free in TIOCMIWAIT
USB: f81232: fix use-after-free in TIOCMIWAIT
USB: ftdi_sio: fix use-after-free in TIOCMIWAIT
USB: io_edgeport: fix use-after-free in TIOCMIWAIT
USB: io_ti: fix use-after-free in TIOCMIWAIT
USB: mct_u232: fix use-after-free in TIOCMIWAIT
USB: mos7840: fix broken TIOCMIWAIT
USB: mos7840: fix use-after-free in TIOCMIWAIT
USB: oti6858: fix use-after-free in TIOCMIWAIT
USB: pl2303: fix use-after-free in TIOCMIWAIT
USB: quatech2: fix use-after-free in TIOCMIWAIT
USB: spcp8x5: fix use-after-free in TIOCMIWAIT
USB: ssu100: fix use-after-free in TIOCMIWAIT
USB: ti_usb_3410_5052: fix use-after-free in TIOCMIWAIT
Johannes Berg (1):
mac80211: always synchronize_net() during station removal
Josef Bacik (4):
Btrfs: fix space leak when we fail to reserve metadata space
Btrfs: limit the global reserve to 512mb
Btrfs: don't drop path when printing out tree errors in scrub
Btrfs: use set_nlink if our i_nlink is 0
Joseph CHANG (1):
DM9000B: driver initialization upgrade
Josh Boyer (2):
HID: usbhid: quirk for Realtek Multi-card reader
HID: usbhid: quirk for MSI GX680R led panel
Jussi Kivilinna (1):
rtlwifi: usb: add missing freeing of skbuff
Kees Cook (2):
net/irda: add missing error path release_sock call
tg3: fix length overflow in VPD firmware parsing
Konstantin Holoborodko (1):
usb: ftdi_sio: Add support for Mitsubishi FX-USB-AW/-BD
Lars-Peter Clausen (1):
regmap: cache Fix regcache-rbtree sync
Lekensteyn (1):
i915: initialize CADL in opregion
Lingzhu Xiang (2):
tracing: Protect tracer flags with trace_types_lock
tracing: Prevent buffer overwrite disabled for latency tracers
Mac Lin (1):
ARM: cns3xxx: fix mapping of private memory region
Marc Kleine-Budde (1):
can: sja1000: fix define conflict on SH
Mark Rutland (1):
clockevents: Don't allow dummy broadcast timers
Masatake YAMATO (2):
thermal: shorten too long mcast group name
genetlink: trigger BUG_ON if a group name is too long
Matt Fleming (2):
efivars: explicitly calculate length of VariableName
efivars: Handle duplicate names from get_next_variable()
[email protected] (1):
ks8851: Fix interpretation of rxlen field.
Mike Marciniszyn (1):
IPoIB: Fix send lockup due to missed TX completion
Ming Lei (5):
Bluetooth: Add support for Dell[QCA 0cf3:0036]
Bluetooth: Add support for Dell[QCA 0cf3:817a]
sysfs: handle failure path correctly for readdir()
USB: serial: fix hang when opening port
sysfs: fix race between readdir and lseek
Mirko Lindner (2):
sky2: Receive Overflows not counted
sky2: Threshold for Pause Packet is set wrong
Mugunthan V N (2):
drivers: net: ethernet: davinci_emac: use netif_wake_queue() while restarting tx queue
drivers: net: ethernet: cpsw: use netif_wake_queue() while restarting tx queue
Paul Moore (1):
unix: fix a race condition in unix_release()
Pawel Wieczorkiewicz (1):
tty: atmel_serial_probe(): index of atmel_ports[] fix
Rafał Miłecki (2):
b43: N-PHY: increase initial value of "mind" in RSSI calibration
b43: N-PHY: use more bits for offset in RSSI calibration
Richard Guy Briggs (1):
thermal: return an error on failure to register thermal class
Steve Glendinning (1):
smsc75xx: fix jumbo frame support
Trond Myklebust (3):
NFSv4: Fix the string length returned by the idmapper
NFSv4.1: Fix a race in pNFS layoutcommit
SUNRPC: Add barriers to ensure read ordering in rpc_wake_up_task_queue_locked
Veaceslav Falico (3):
bonding: remove already created master sysfs link on failure
pch_gbe: fix ip_summed checksum reporting on rx
bonding: get netdev_rx_handler_unregister out of locks
Vinicius Costa Gomes (1):
Bluetooth: Fix not closing SCO sockets in the BT_CONNECT2 state
Vivek Gautam (1):
usb: xhci: Fix TRB transfer length macro used for Event TRB.
Yuchung Cheng (1):
tcp: undo spurious timeout after SACK reneging
fanchaoting (1):
pnfs-block: removing DM device maybe cause oops when call dev_remove
[email protected] (2):
bonding: fix miimon and arp_interval delayed work race conditions
bonding: fix disabling of arp_interval and miimon
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawel Wieczorkiewicz <[email protected]>
commit 503bded92da283b2f31d87e054c4c6d30c3c2340 upstream.
Index of atmel_ports[ATMEL_MAX_UART] should be smaller
than ATMEL_MAX_UART.
Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
Acked-by: Nicolas Ferre <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/tty/serial/atmel_serial.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 3d7e1ee..ed7cd37 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -159,7 +159,7 @@ struct atmel_uart_port {
};
static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
-static unsigned long atmel_ports_in_use;
+static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART);
#ifdef SUPPORT_SYSRQ
static struct console atmel_console;
@@ -1785,15 +1785,14 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
if (ret < 0)
/* port id not found in platform data nor device-tree aliases:
* auto-enumerate it */
- ret = find_first_zero_bit(&atmel_ports_in_use,
- sizeof(atmel_ports_in_use));
+ ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART);
- if (ret > ATMEL_MAX_UART) {
+ if (ret >= ATMEL_MAX_UART) {
ret = -ENODEV;
goto err;
}
- if (test_and_set_bit(ret, &atmel_ports_in_use)) {
+ if (test_and_set_bit(ret, atmel_ports_in_use)) {
/* port already in use */
ret = -EBUSY;
goto err;
@@ -1867,7 +1866,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
/* "port" is allocated statically, so we shouldn't free it */
- clear_bit(port->line, &atmel_ports_in_use);
+ clear_bit(port->line, atmel_ports_in_use);
clk_put(atmel_port->clk);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit e5110f411d2ee35bf8d202ccca2e89c633060dca upstream.
In case of 'if (filp->f_pos == 0 or 1)' of sysfs_readdir(),
the failure from filldir() isn't handled, and the reference counter
of the sysfs_dirent object pointed by filp->private_data will be
released without clearing filp->private_data, so use after free
bug will be triggered later.
This patch returns immeadiately under the situation for fixing the bug,
and it is reasonable to return from readdir() when filldir() fails.
Reported-by: Dave Jones <[email protected]>
Tested-by: Sasha Levin <[email protected]>
Signed-off-by: Ming Lei <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/sysfs/dir.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 5a035b5..2ee0864 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -1021,6 +1021,8 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
ino = parent_sd->s_ino;
if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0)
filp->f_pos++;
+ else
+ return 0;
}
if (filp->f_pos == 1) {
if (parent_sd->s_parent)
@@ -1029,6 +1031,8 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
ino = parent_sd->s_ino;
if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
filp->f_pos++;
+ else
+ return 0;
}
mutex_lock(&sysfs_mutex);
for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit d8fe29e9dea8d7d61fd140d8779326856478fc62 upstream.
A user reported a panic where we were panicing somewhere in
tree_backref_for_extent from scrub_print_warning. He only captured the trace
but looking at scrub_print_warning we drop the path right before we mess with
the extent buffer to print out a bunch of stuff, which isn't right. So fix this
by dropping the path after we use the eb if we need to. Thanks,
Signed-off-by: Josef Bacik <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
fs/btrfs/scrub.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index b223620..5aeffbe 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -385,7 +385,6 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
eb = path->nodes[0];
ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
item_size = btrfs_item_size_nr(eb, path->slots[0]);
- btrfs_release_path(path);
if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
do {
@@ -401,7 +400,9 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
ret < 0 ? -1 : ref_level,
ret < 0 ? -1 : ref_root);
} while (ret != 1);
+ btrfs_release_path(path);
} else {
+ btrfs_release_path(path);
swarn.path = path;
iterate_extent_inodes(fs_info, found_key.objectid,
extent_item_pos, 1,
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit e670c6af12517d08a403487b1122eecf506021cf upstream.
Make sure waiting processes are woken on modem-status changes.
Currently processes are only woken on termios changes regardless of
whether the modem status has changed.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/mos7840.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 1b5ea51..be5f09b 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -442,6 +442,9 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
icount->rng++;
smp_wmb();
}
+
+ mos7840_port->delta_msr_cond = 1;
+ wake_up_interruptible(&mos7840_port->delta_msr_wait);
}
}
@@ -2096,8 +2099,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
mos7840_port->read_urb_busy = false;
}
}
- wake_up(&mos7840_port->delta_msr_wait);
- mos7840_port->delta_msr_cond = 1;
dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x",
mos7840_port->shadowLCR);
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 5018860321dc7a9e50a75d5f319bc981298fb5b7 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/ark3116.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index f8ce97d..15bd068 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -68,7 +68,6 @@ static int is_irda(struct usb_serial *serial)
}
struct ark3116_private {
- wait_queue_head_t delta_msr_wait;
struct async_icount icount;
int irda; /* 1 for irda device */
@@ -148,7 +147,6 @@ static int ark3116_attach(struct usb_serial *serial)
if (!priv)
return -ENOMEM;
- init_waitqueue_head(&priv->delta_msr_wait);
mutex_init(&priv->hw_lock);
spin_lock_init(&priv->status_lock);
@@ -461,10 +459,14 @@ static int ark3116_ioctl(struct tty_struct *tty,
case TIOCMIWAIT:
for (;;) {
struct async_icount prev = priv->icount;
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
if ((prev.rng == priv->icount.rng) &&
(prev.dsr == priv->icount.dsr) &&
(prev.dcd == priv->icount.dcd) &&
@@ -585,7 +587,7 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
priv->icount.dcd++;
if (msr & UART_MSR_TERI)
priv->icount.rng++;
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
}
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 69f87f40d2b98e8b4ab82a121fd2bd584690b887 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backported to 3.5; adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/quatech2.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index e1065f8..1c2c0ba 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -132,7 +132,6 @@ struct qt2_port_private {
u8 shadowLSR;
u8 shadowMSR;
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
struct async_icount icount;
struct usb_serial_port *port;
@@ -528,8 +527,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- wait_event_interruptible(priv->delta_msr_wait,
- ((priv->icount.rng != prev.rng) ||
+ wait_event_interruptible(port->delta_msr_wait,
+ (port->serial->disconnected ||
+ (priv->icount.rng != prev.rng) ||
(priv->icount.dsr != prev.dsr) ||
(priv->icount.dcd != prev.dcd) ||
(priv->icount.cts != prev.cts)));
@@ -537,6 +537,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
cur = priv->icount;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -881,7 +884,6 @@ static int qt2_attach(struct usb_serial *serial)
spin_lock_init(&port_priv->lock);
spin_lock_init(&port_priv->urb_lock);
- init_waitqueue_head(&port_priv->delta_msr_wait);
port_priv->port = serial->port[pcount];
@@ -1015,7 +1017,7 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
if (newMSR & UART_MSR_TERI)
port_priv->icount.rng++;
- wake_up_interruptible(&port_priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
}
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit f4541d60a449afd40448b06496dcd510f505928e upstream.
A long standing problem with TSO is the fact that tcp_tso_should_defer()
rearms the deferred timer, while it should not.
Current code leads to following bad bursty behavior :
20:11:24.484333 IP A > B: . 297161:316921(19760) ack 1 win 119
20:11:24.484337 IP B > A: . ack 263721 win 1117
20:11:24.485086 IP B > A: . ack 265241 win 1117
20:11:24.485925 IP B > A: . ack 266761 win 1117
20:11:24.486759 IP B > A: . ack 268281 win 1117
20:11:24.487594 IP B > A: . ack 269801 win 1117
20:11:24.488430 IP B > A: . ack 271321 win 1117
20:11:24.489267 IP B > A: . ack 272841 win 1117
20:11:24.490104 IP B > A: . ack 274361 win 1117
20:11:24.490939 IP B > A: . ack 275881 win 1117
20:11:24.491775 IP B > A: . ack 277401 win 1117
20:11:24.491784 IP A > B: . 316921:332881(15960) ack 1 win 119
20:11:24.492620 IP B > A: . ack 278921 win 1117
20:11:24.493448 IP B > A: . ack 280441 win 1117
20:11:24.494286 IP B > A: . ack 281961 win 1117
20:11:24.495122 IP B > A: . ack 283481 win 1117
20:11:24.495958 IP B > A: . ack 285001 win 1117
20:11:24.496791 IP B > A: . ack 286521 win 1117
20:11:24.497628 IP B > A: . ack 288041 win 1117
20:11:24.498459 IP B > A: . ack 289561 win 1117
20:11:24.499296 IP B > A: . ack 291081 win 1117
20:11:24.500133 IP B > A: . ack 292601 win 1117
20:11:24.500970 IP B > A: . ack 294121 win 1117
20:11:24.501388 IP B > A: . ack 295641 win 1117
20:11:24.501398 IP A > B: . 332881:351881(19000) ack 1 win 119
While the expected behavior is more like :
20:19:49.259620 IP A > B: . 197601:202161(4560) ack 1 win 119
20:19:49.260446 IP B > A: . ack 154281 win 1212
20:19:49.261282 IP B > A: . ack 155801 win 1212
20:19:49.262125 IP B > A: . ack 157321 win 1212
20:19:49.262136 IP A > B: . 202161:206721(4560) ack 1 win 119
20:19:49.262958 IP B > A: . ack 158841 win 1212
20:19:49.263795 IP B > A: . ack 160361 win 1212
20:19:49.264628 IP B > A: . ack 161881 win 1212
20:19:49.264637 IP A > B: . 206721:211281(4560) ack 1 win 119
20:19:49.265465 IP B > A: . ack 163401 win 1212
20:19:49.265886 IP B > A: . ack 164921 win 1212
20:19:49.266722 IP B > A: . ack 166441 win 1212
20:19:49.266732 IP A > B: . 211281:215841(4560) ack 1 win 119
20:19:49.267559 IP B > A: . ack 167961 win 1212
20:19:49.268394 IP B > A: . ack 169481 win 1212
20:19:49.269232 IP B > A: . ack 171001 win 1212
20:19:49.269241 IP A > B: . 215841:221161(5320) ack 1 win 119
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Yuchung Cheng <[email protected]>
Cc: Van Jacobson <[email protected]>
Cc: Neal Cardwell <[email protected]>
Cc: Nandita Dukkipati <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/ipv4/tcp_output.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 1195760..e0cd660 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1604,8 +1604,11 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
goto send_now;
}
- /* Ok, it looks like it is advisable to defer. */
- tp->tso_deferred = 1 | (jiffies << 1);
+ /* Ok, it looks like it is advisable to defer.
+ * Do not rearm the timer if already set to not break TCP ACK clocking.
+ */
+ if (!tp->tso_deferred)
+ tp->tso_deferred = 1 | (jiffies << 1);
return true;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit 27a737ff7cb062fb9cbceba9b44d60aa74862bfa upstream.
If there are keys left during station removal, then a
synchronize_net() will be done (for each key, I have a
patch to address this for 3.10), otherwise it won't be
done at all which causes issues because the station
could be used for TX while it's being removed from the
driver -- that might confuse the driver.
Fix this by always doing synchronize_net() if no key
was present any more.
Signed-off-by: Johannes Berg <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
net/mac80211/sta_info.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index fec8eab..91eb0c5 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -664,6 +664,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
struct ieee80211_sub_if_data *sdata;
int ret, i, ac;
struct tid_ampdu_tx *tid_tx;
+ bool have_key = false;
might_sleep();
@@ -691,12 +692,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
list_del_rcu(&sta->list);
mutex_lock(&local->key_mtx);
- for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
__ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
- if (sta->ptk)
+ have_key = true;
+ }
+ if (sta->ptk) {
__ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
+ have_key = true;
+ }
mutex_unlock(&local->key_mtx);
+ if (!have_key)
+ synchronize_net();
+
sta->dead = true;
local->num_sta--;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Veaceslav Falico <[email protected]>
commit fcd99434fb5c137274d2e15dd2a6a7455f0f29ff upstream.
Now that netdev_rx_handler_unregister contains synchronize_net(), we need
to call it outside of bond->lock, cause it might sleep. Also, remove the
already unneded synchronize_net().
Signed-off-by: Veaceslav Falico <[email protected]>
Acked-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/bonding/bond_main.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1b6e13d..1a6b118 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1965,12 +1965,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
return -EINVAL;
}
+ write_unlock_bh(&bond->lock);
/* unregister rx_handler early so bond_handle_frame wouldn't be called
* for this slave anymore.
*/
netdev_rx_handler_unregister(slave_dev);
- write_unlock_bh(&bond->lock);
- synchronize_net();
write_lock_bh(&bond->lock);
if (!bond->params.fail_over_mac) {
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Frederic Sowa <[email protected]>
commit 1c4a154e5253687c51123956dfcee9e9dfa8542d upstream.
Erik Hugne's errata proposal (Errata ID: 3480) to RFC4291 has been
verified: http://www.rfc-editor.org/errata_search.php?eid=3480
We have to check for pkt_type and loopback flag because either the
packets are allowed to travel over the loopback interface (in which case
pkt_type is PACKET_HOST and IFF_LOOPBACK flag is set) or they travel
over a non-loopback interface back to us (in which case PACKET_TYPE is
PACKET_LOOPBACK and IFF_LOOPBACK flag is not set).
Cc: Erik Hugne <[email protected]>
Cc: YOSHIFUJI Hideaki <[email protected]>
Signed-off-by: Hannes Frederic Sowa <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/ipv6/ip6_input.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 311eac7..594a4ec 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -111,6 +111,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
ipv6_addr_loopback(&hdr->daddr))
goto err;
+ /* RFC4291 Errata ID: 3480
+ * Interface-Local scope spans only a single interface on a
+ * node and is useful only for loopback transmission of
+ * multicast. Packets with interface-local scope received
+ * from another node must be discarded.
+ */
+ if (!(skb->pkt_type == PACKET_LOOPBACK ||
+ dev->flags & IFF_LOOPBACK) &&
+ ipv6_addr_is_multicast(&hdr->daddr) &&
+ IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
+ goto err;
+
/* RFC4291 2.7
* Nodes must not originate a packet to a multicast address whose scope
* field contains the reserved value 0; if such a packet is received, it
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Metcalf <[email protected]>
commit ff7f3efb9abf986f4ecd8793a9593f7ca4d6431a upstream.
The current Tilera boot infrastructure now provides the initramfs
to Linux as a Tilera-hypervisor file named "initramfs", rather than
"initramfs.cpio.gz", as before. (This makes it reasonable to use
other compression techniques than gzip on the file without having to
worry about the name causing confusion.) Adapt to use the new name,
but also fall back to checking for the old name.
Cc'ing to stable so that older kernels will remain compatible with
newer Tilera boot infrastructure.
Signed-off-by: Chris Metcalf <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
arch/tile/kernel/setup.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index dd87f34..3d2190b 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -990,15 +990,8 @@ void __cpuinit setup_cpu(int boot)
#ifdef CONFIG_BLK_DEV_INITRD
-/*
- * Note that the kernel can potentially support other compression
- * techniques than gz, though we don't do so by default. If we ever
- * decide to do so we can either look for other filename extensions,
- * or just allow a file with this name to be compressed with an
- * arbitrary compressor (somewhat counterintuitively).
- */
static int __initdata set_initramfs_file;
-static char __initdata initramfs_file[128] = "initramfs.cpio.gz";
+static char __initdata initramfs_file[128] = "initramfs";
static int __init setup_initramfs_file(char *str)
{
@@ -1012,9 +1005,9 @@ static int __init setup_initramfs_file(char *str)
early_param("initramfs_file", setup_initramfs_file);
/*
- * We look for an "initramfs.cpio.gz" file in the hvfs.
- * If there is one, we allocate some memory for it and it will be
- * unpacked to the initramfs.
+ * We look for a file called "initramfs" in the hvfs. If there is one, we
+ * allocate some memory for it and it will be unpacked to the initramfs.
+ * If it's compressed, the initd code will uncompress it first.
*/
static void __init load_hv_initrd(void)
{
@@ -1024,10 +1017,16 @@ static void __init load_hv_initrd(void)
fd = hv_fs_findfile((HV_VirtAddr) initramfs_file);
if (fd == HV_ENOENT) {
- if (set_initramfs_file)
+ if (set_initramfs_file) {
pr_warning("No such hvfs initramfs file '%s'\n",
initramfs_file);
- return;
+ return;
+ } else {
+ /* Try old backwards-compatible name. */
+ fd = hv_fs_findfile((HV_VirtAddr)"initramfs.cpio.gz");
+ if (fd == HV_ENOENT)
+ return;
+ }
}
BUG_ON(fd < 0);
stat = hv_fs_fstat(fd);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Anatol Pomozov <[email protected]>
commit c1681bf8a7b1b98edee8b862a42c19c4e53205fd upstream.
struct block_device lifecycle is defined by its inode (see fs/block_dev.c) -
block_device allocated first time we access /dev/loopXX and deallocated on
bdev_destroy_inode. When we create the device "losetup /dev/loopXX afile"
we want that block_device stay alive until we destroy the loop device
with "losetup -d".
But because we do not hold /dev/loopXX inode its counter goes 0, and
inode/bdev can be destroyed at any moment. Usually it happens at memory
pressure or when user drops inode cache (like in the test below). When later in
loop_clr_fd() we want to use bdev we have use-after-free error with following
stack:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000280
bd_set_size+0x10/0xa0
loop_clr_fd+0x1f8/0x420 [loop]
lo_ioctl+0x200/0x7e0 [loop]
lo_compat_ioctl+0x47/0xe0 [loop]
compat_blkdev_ioctl+0x341/0x1290
do_filp_open+0x42/0xa0
compat_sys_ioctl+0xc1/0xf20
do_sys_open+0x16e/0x1d0
sysenter_dispatch+0x7/0x1a
To prevent use-after-free we need to grab the device in loop_set_fd()
and put it later in loop_clr_fd().
The issue is reprodusible on current Linus head and v3.3. Here is the test:
dd if=/dev/zero of=loop.file bs=1M count=1
while [ true ]; do
losetup /dev/loop0 loop.file
echo 2 > /proc/sys/vm/drop_caches
losetup -d /dev/loop0
done
[ Doing bdgrab/bput in loop_set_fd/loop_clr_fd is safe, because every
time we call loop_set_fd() we check that loop_device->lo_state is
Lo_unbound and set it to Lo_bound If somebody will try to set_fd again
it will get EBUSY. And if we try to loop_clr_fd() on unbound loop
device we'll get ENXIO.
loop_set_fd/loop_clr_fd (and any other loop ioctl) is called under
loop_device->lo_ctl_mutex. ]
Signed-off-by: Anatol Pomozov <[email protected]>
Cc: Al Viro <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/block/loop.c | 9 ++++++++-
fs/block_dev.c | 1 +
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index a77d9a5..c5e0f73 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -908,6 +908,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
lo->lo_flags |= LO_FLAGS_PARTSCAN;
if (lo->lo_flags & LO_FLAGS_PARTSCAN)
ioctl_by_bdev(bdev, BLKRRPART, 0);
+
+ /* Grab the block_device to prevent its destruction after we
+ * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
+ */
+ bdgrab(bdev);
return 0;
out_clr:
@@ -1004,8 +1009,10 @@ static int loop_clr_fd(struct loop_device *lo)
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
- if (bdev)
+ if (bdev) {
+ bdput(bdev);
invalidate_bdev(bdev);
+ }
set_capacity(lo->lo_disk, 0);
loop_sysfs_exit(lo);
if (bdev) {
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 77e86b3..1244094 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -604,6 +604,7 @@ struct block_device *bdgrab(struct block_device *bdev)
ihold(bdev->bd_inode);
return bdev;
}
+EXPORT_SYMBOL(bdgrab);
long nr_blockdev_pages(void)
{
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Stancek <[email protected]>
commit b6a9b7f6b1f21735a7456d534dc0e68e61359d2c upstream.
find_vma() can be called by multiple threads with read lock
held on mm->mmap_sem and any of them can update mm->mmap_cache.
Prevent compiler from re-fetching mm->mmap_cache, because other
readers could update it in the meantime:
thread 1 thread 2
|
find_vma() | find_vma()
struct vm_area_struct *vma = NULL; |
vma = mm->mmap_cache; |
if (!(vma && vma->vm_end > addr |
&& vma->vm_start <= addr)) { |
| mm->mmap_cache = vma;
return vma; |
^^ compiler may optimize this |
local variable out and re-read |
mm->mmap_cache |
This issue can be reproduced with gcc-4.8.0-1 on s390x by running
mallocstress testcase from LTP, which triggers:
kernel BUG at mm/rmap.c:1088!
Call Trace:
([<000003d100c57000>] 0x3d100c57000)
[<000000000023a1c0>] do_wp_page+0x2fc/0xa88
[<000000000023baae>] handle_pte_fault+0x41a/0xac8
[<000000000023d832>] handle_mm_fault+0x17a/0x268
[<000000000060507a>] do_protection_exception+0x1e2/0x394
[<0000000000603a04>] pgm_check_handler+0x138/0x13c
[<000003fffcf1f07a>] 0x3fffcf1f07a
Last Breaking-Event-Address:
[<000000000024755e>] page_add_new_anon_rmap+0xc2/0x168
Thanks to Jakub Jelinek for his insight on gcc and helping to
track this down.
Signed-off-by: Jan Stancek <[email protected]>
Acked-by: David Rientjes <[email protected]>
Signed-off-by: Hugh Dickins <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
mm/mmap.c | 2 +-
mm/nommu.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/mmap.c b/mm/mmap.c
index fa1f274..5603d88 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1610,7 +1610,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
/* Check the cache first. */
/* (Cache hit rate is typically around 35%.) */
- vma = mm->mmap_cache;
+ vma = ACCESS_ONCE(mm->mmap_cache);
if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {
struct rb_node *rb_node;
diff --git a/mm/nommu.c b/mm/nommu.c
index d4b0c10..a60db99 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -807,7 +807,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
struct vm_area_struct *vma;
/* check the cache first */
- vma = mm->mmap_cache;
+ vma = ACCESS_ONCE(mm->mmap_cache);
if (vma && vma->vm_start <= addr && vma->vm_end > addr)
return vma;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Fleming <[email protected]>
commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
It's not wise to assume VariableNameSize represents the length of
VariableName, as not all firmware updates VariableNameSize in the same
way (some don't update it at all if EFI_SUCCESS is returned). There
are even implementations out there that update VariableNameSize with
values that are both larger than the string returned in VariableName
and smaller than the buffer passed to GetNextVariableName(), which
resulted in the following bug report from Michael Schroeder,
> On HP z220 system (firmware version 1.54), some EFI variables are
> incorrectly named :
>
> ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
> /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d-00e098032b8c
The issue here is that because we blindly use VariableNameSize without
verifying its value, we can potentially read garbage values from the
buffer containing VariableName if VariableNameSize is larger than the
length of VariableName.
Since VariableName is a string, we can calculate its size by searching
for the terminating NULL character.
Reported-by: Frederic Crozat <[email protected]>
Cc: Matthew Garrett <[email protected]>
Cc: Josh Boyer <[email protected]>
Cc: Michael Schroeder <[email protected]>
Cc: Lee, Chun-Yi <[email protected]>
Cc: Lingzhu Xiang <[email protected]>
Cc: Seiji Aguchi <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
[ Backported for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
Signed-off-by: Lingzhu Xiang <[email protected]>
Reviewed-by: CAI Qian <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/firmware/efivars.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index bfd8f43..9a1968e 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -943,6 +943,31 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
}
/*
+ * Returns the size of variable_name, in bytes, including the
+ * terminating NULL character, or variable_name_size if no NULL
+ * character is found among the first variable_name_size bytes.
+ */
+static unsigned long var_name_strnsize(efi_char16_t *variable_name,
+ unsigned long variable_name_size)
+{
+ unsigned long len;
+ efi_char16_t c;
+
+ /*
+ * The variable name is, by definition, a NULL-terminated
+ * string, so make absolutely sure that variable_name_size is
+ * the value we expect it to be. If not, return the real size.
+ */
+ for (len = 2; len <= variable_name_size; len += sizeof(c)) {
+ c = variable_name[(len / sizeof(c)) - 1];
+ if (!c)
+ break;
+ }
+
+ return min(len, variable_name_size);
+}
+
+/*
* Let's not leave out systab information that snuck into
* the efivars driver
*/
@@ -1169,6 +1194,8 @@ int register_efivars(struct efivars *efivars,
&vendor_guid);
switch (status) {
case EFI_SUCCESS:
+ variable_name_size = var_name_strnsize(variable_name,
+ variable_name_size);
efivar_create_sysfs_entry(efivars,
variable_name_size,
variable_name,
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 35e5cbc0af240778e61113286c019837e06aeec6 upstream.
After commit 21d8a15a (lookup_one_len: don't accept . and ..) reiserfs
started failing to delete xattrs from inode. This was due to a buggy
test for '.' and '..' in fill_with_dentries() which resulted in passing
'.' and '..' entries to lookup_one_len() in some cases. That returned
error and so we failed to iterate over all xattrs of and inode.
Fix the test in fill_with_dentries() along the lines of the one in
lookup_one_len().
Reported-by: Pawel Zawora <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/reiserfs/xattr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 46fc1c2..048d990 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -187,8 +187,8 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,
if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
return -ENOSPC;
- if (name[0] == '.' && (name[1] == '\0' ||
- (name[1] == '.' && name[2] == '\0')))
+ if (name[0] == '.' && (namelen < 2 ||
+ (namelen == 2 && name[1] == '.')))
return 0;
dentry = lookup_one_len(name, dbuf->xadir, namelen);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Fleming <[email protected]>
commit e971318bbed610e28bb3fde9d548e6aaf0a6b02e upstream.
Some firmware exhibits a bug where the same VariableName and
VendorGuid values are returned on multiple invocations of
GetNextVariableName(). See,
https://bugzilla.kernel.org/show_bug.cgi?id=47631
As a consequence of such a bug, Andre reports hitting the following
WARN_ON() in the sysfs code after updating the BIOS on his, "Gigabyte
Technology Co., Ltd. To be filled by O.E.M./Z77X-UD3H, BIOS F19e
11/21/2012)" machine,
[ 0.581554] EFI Variables Facility v0.08 2004-May-17
[ 0.584914] ------------[ cut here ]------------
[ 0.585639] WARNING: at /home/andre/linux/fs/sysfs/dir.c:536 sysfs_add_one+0xd4/0x100()
[ 0.586381] Hardware name: To be filled by O.E.M.
[ 0.587123] sysfs: cannot create duplicate filename '/firmware/efi/vars/SbAslBufferPtrVar-01f33c25-764d-43ea-aeea-6b5a41f3f3e8'
[ 0.588694] Modules linked in:
[ 0.589484] Pid: 1, comm: swapper/0 Not tainted 3.8.0+ #7
[ 0.590280] Call Trace:
[ 0.591066] [<ffffffff81208954>] ? sysfs_add_one+0xd4/0x100
[ 0.591861] [<ffffffff810587bf>] warn_slowpath_common+0x7f/0xc0
[ 0.592650] [<ffffffff810588bc>] warn_slowpath_fmt+0x4c/0x50
[ 0.593429] [<ffffffff8134dd85>] ? strlcat+0x65/0x80
[ 0.594203] [<ffffffff81208954>] sysfs_add_one+0xd4/0x100
[ 0.594979] [<ffffffff81208b78>] create_dir+0x78/0xd0
[ 0.595753] [<ffffffff81208ec6>] sysfs_create_dir+0x86/0xe0
[ 0.596532] [<ffffffff81347e4c>] kobject_add_internal+0x9c/0x220
[ 0.597310] [<ffffffff81348307>] kobject_init_and_add+0x67/0x90
[ 0.598083] [<ffffffff81584a71>] ? efivar_create_sysfs_entry+0x61/0x1c0
[ 0.598859] [<ffffffff81584b2b>] efivar_create_sysfs_entry+0x11b/0x1c0
[ 0.599631] [<ffffffff8158517e>] register_efivars+0xde/0x420
[ 0.600395] [<ffffffff81d430a7>] ? edd_init+0x2f5/0x2f5
[ 0.601150] [<ffffffff81d4315f>] efivars_init+0xb8/0x104
[ 0.601903] [<ffffffff8100215a>] do_one_initcall+0x12a/0x180
[ 0.602659] [<ffffffff81d05d80>] kernel_init_freeable+0x13e/0x1c6
[ 0.603418] [<ffffffff81d05586>] ? loglevel+0x31/0x31
[ 0.604183] [<ffffffff816a6530>] ? rest_init+0x80/0x80
[ 0.604936] [<ffffffff816a653e>] kernel_init+0xe/0xf0
[ 0.605681] [<ffffffff816ce7ec>] ret_from_fork+0x7c/0xb0
[ 0.606414] [<ffffffff816a6530>] ? rest_init+0x80/0x80
[ 0.607143] ---[ end trace 1609741ab737eb29 ]---
There's not much we can do to work around and keep traversing the
variable list once we hit this firmware bug. Our only solution is to
terminate the loop because, as Lingzhu reports, some machines get
stuck when they encounter duplicate names,
> I had an IBM System x3100 M4 and x3850 X5 on which kernel would
> get stuck in infinite loop creating duplicate sysfs files because,
> for some reason, there are several duplicate boot entries in nvram
> getting GetNextVariableName into a circle of iteration (with
> period > 2).
Also disable the workqueue, as efivar_update_sysfs_entries() uses
GetNextVariableName() to figure out which variables have been created
since the last iteration. That algorithm isn't going to work if
GetNextVariableName() returns duplicates. Note that we don't disable
EFI variable creation completely on the affected machines, it's just
that any pstore dump-* files won't appear in sysfs until the next
boot.
Reported-by: Andre Heider <[email protected]>
Reported-by: Lingzhu Xiang <[email protected]>
Tested-by: Lingzhu Xiang <[email protected]>
Cc: Seiji Aguchi <[email protected]>
Cc: <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
[ Backported for 3.4-stable. Removed code related to pstore workqueue
but pulled in helper function variable_is_present from a93bc0c; Moved
the definition of __efivars to the top for being referenced in
variable_is_present. ]
Signed-off-by: Lingzhu Xiang <[email protected]>
Reviewed-by: CAI Qian <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/firmware/efivars.c | 66 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 63 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 9a1968e..2cbb675 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -122,6 +122,9 @@ struct efivar_attribute {
ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
};
+static struct efivars __efivars;
+static struct efivar_operations ops;
+
#define PSTORE_EFI_ATTRIBUTES \
(EFI_VARIABLE_NON_VOLATILE | \
EFI_VARIABLE_BOOTSERVICE_ACCESS | \
@@ -942,6 +945,28 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
return count;
}
+static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
+{
+ struct efivar_entry *entry, *n;
+ struct efivars *efivars = &__efivars;
+ unsigned long strsize1, strsize2;
+ bool found = false;
+
+ strsize1 = utf16_strsize(variable_name, 1024);
+ list_for_each_entry_safe(entry, n, &efivars->list, list) {
+ strsize2 = utf16_strsize(entry->var.VariableName, 1024);
+ if (strsize1 == strsize2 &&
+ !memcmp(variable_name, &(entry->var.VariableName),
+ strsize2) &&
+ !efi_guidcmp(entry->var.VendorGuid,
+ *vendor)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
+
/*
* Returns the size of variable_name, in bytes, including the
* terminating NULL character, or variable_name_size if no NULL
@@ -1154,6 +1179,28 @@ void unregister_efivars(struct efivars *efivars)
}
EXPORT_SYMBOL_GPL(unregister_efivars);
+/*
+ * Print a warning when duplicate EFI variables are encountered and
+ * disable the sysfs workqueue since the firmware is buggy.
+ */
+static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
+ unsigned long len16)
+{
+ size_t i, len8 = len16 / sizeof(efi_char16_t);
+ char *s8;
+
+ s8 = kzalloc(len8, GFP_KERNEL);
+ if (!s8)
+ return;
+
+ for (i = 0; i < len8; i++)
+ s8[i] = s16[i];
+
+ printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
+ s8, vendor_guid);
+ kfree(s8);
+}
+
int register_efivars(struct efivars *efivars,
const struct efivar_operations *ops,
struct kobject *parent_kobj)
@@ -1196,6 +1243,22 @@ int register_efivars(struct efivars *efivars,
case EFI_SUCCESS:
variable_name_size = var_name_strnsize(variable_name,
variable_name_size);
+
+ /*
+ * Some firmware implementations return the
+ * same variable name on multiple calls to
+ * get_next_variable(). Terminate the loop
+ * immediately as there is no guarantee that
+ * we'll ever see a different variable name,
+ * and may end up looping here forever.
+ */
+ if (variable_is_present(variable_name, &vendor_guid)) {
+ dup_variable_bug(variable_name, &vendor_guid,
+ variable_name_size);
+ status = EFI_NOT_FOUND;
+ break;
+ }
+
efivar_create_sysfs_entry(efivars,
variable_name_size,
variable_name,
@@ -1232,9 +1295,6 @@ out:
}
EXPORT_SYMBOL_GPL(register_efivars);
-static struct efivars __efivars;
-static struct efivar_operations ops;
-
/*
* For now we register the efi subsystem with the firmware subsystem
* and the vars subsystem with the efi subsystem. In the future, it
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Guy Briggs <[email protected]>
commit da28d966f6aa942ae836d09729f76a1647932309 upstream.
The return code from the registration of the thermal class is used to
unallocate resources, but this failure isn't passed back to the caller of
thermal_init. Return this failure back to the caller.
This bug was introduced in changeset 4cb18728 which overwrote the return code
when the variable was re-used to catch the return code of the registration of
the genetlink thermal socket family.
Signed-off-by: Richard Guy Briggs <[email protected]>
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/thermal/thermal_sys.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 022bacb..5c26dda 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -1383,6 +1383,7 @@ static int __init thermal_init(void)
idr_destroy(&thermal_cdev_idr);
mutex_destroy(&thermal_idr_lock);
mutex_destroy(&thermal_list_lock);
+ return result;
}
result = genetlink_init();
return result;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Artem Bityutskiy <[email protected]>
commit 67e753ca41782913d805ff4a8a2b0f60b26b7915 upstream.
The UBIFS space fixup is a useful feature which allows to fixup the "broken"
flash space at the time of the first mount. The "broken" space is usually the
result of using a "dumb" industrial flasher which is not able to skip empty
NAND pages and just writes all 0xFFs to the empty space, which has grave
side-effects for UBIFS when UBIFS trise to write useful data to those empty
pages.
The fix-up feature works roughly like this:
1. mkfs.ubifs sets the fixup flag in UBIFS superblock when creating the image
(see -F option)
2. when the file-system is mounted for the first time, UBIFS notices the fixup
flag and re-writes the entire media atomically, which may take really a lot
of time.
3. UBIFS clears the fixup flag in the superblock.
This works fine when the file system is mounted R/W for the very first time.
But it did not really work in the case when we first mount the file-system R/O,
and then re-mount R/W. The reason was that we started the fixup procedure too
late, which we cannot really do because we have to fixup the space before it
starts being used.
Signed-off-by: Artem Bityutskiy <[email protected]>
Reported-by: Mark Jackson <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/ubifs/super.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 5862dd9..202c0e4 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1579,6 +1579,12 @@ static int ubifs_remount_rw(struct ubifs_info *c)
c->remounting_rw = 1;
c->ro_mount = 0;
+ if (c->space_fixup) {
+ err = ubifs_fixup_free_space(c);
+ if (err)
+ return err;
+ }
+
err = check_free_space(c);
if (err)
goto out;
@@ -1695,12 +1701,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
err = dbg_check_space_info(c);
}
- if (c->space_fixup) {
- err = ubifs_fixup_free_space(c);
- if (err)
- goto out;
- }
-
mutex_unlock(&c->umount_mutex);
return err;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
commit 715230a44310a8cf66fbfb5a46f9a62a9b2de424 upstream.
Commit 184b89044fb6e2a74611dafa69b1dce0d98612c6 ("tg3: Use VPD fw version
when present") introduced VPD parsing that contained a potential length
overflow.
Limit the hardware's reported firmware string length (max 255 bytes) to
stay inside the driver's firmware string length (32 bytes). On overflow,
truncate the formatted firmware string instead of potentially overwriting
portions of the tg3 struct.
http://cansecwest.com/slides/2013/PrivateCore%20CSW%202013.pdf
Signed-off-by: Kees Cook <[email protected]>
Reported-by: Oded Horovitz <[email protected]>
Reported-by: Brad Spengler <[email protected]>
Cc: Matt Carlson <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/broadcom/tg3.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ca3be73..c2450f4 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -13617,8 +13617,11 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
if (j + len > block_end)
goto partno;
- memcpy(tp->fw_ver, &vpd_data[j], len);
- strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
+ if (len >= sizeof(tp->fw_ver))
+ len = sizeof(tp->fw_ver) - 1;
+ memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
+ snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len,
+ &vpd_data[j]);
}
partno:
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Shah <[email protected]>
commit 9ba5c80b1aea8648a3efe5f22dc1f7cacdfbeeb8 upstream.
When multiple ovq operations are being performed (lots of open/close
operations on virtio_console fds), the __send_control_msg() function can
get confused without locking.
A simple recipe to cause badness is:
* create a QEMU VM with two virtio-serial ports
* in the guest, do
while true;do echo abc >/dev/vport0p1;done
while true;do echo edf >/dev/vport0p2;done
In one run, this caused a panic in __send_control_msg(). In another, I
got
virtio_console virtio0: control-o:id 0 is not a head!
This also results repeated messages similar to these on the host:
qemu-kvm: virtio-serial-bus: Unexpected port id 478762112 for device virtio-serial-bus.0
qemu-kvm: virtio-serial-bus: Unexpected port id 478762368 for device virtio-serial-bus.0
Reported-by: FuXiangChun <[email protected]>
Signed-off-by: Amit Shah <[email protected]>
Reviewed-by: Wanlong Gao <[email protected]>
Reviewed-by: Asias He <[email protected]>
Signed-off-by: Rusty Russell <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/char/virtio_console.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 4c76834..957f293 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -132,6 +132,7 @@ struct ports_device {
/* To protect the vq operations for the control channel */
spinlock_t c_ivq_lock;
+ spinlock_t c_ovq_lock;
/* The current config space is stored here */
struct virtio_console_config config;
@@ -457,11 +458,13 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
vq = portdev->c_ovq;
sg_init_one(sg, &cpkt, sizeof(cpkt));
+ spin_lock(&portdev->c_ovq_lock);
if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) {
virtqueue_kick(vq);
while (!virtqueue_get_buf(vq, &len))
cpu_relax();
}
+ spin_unlock(&portdev->c_ovq_lock);
return 0;
}
@@ -1743,6 +1746,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
unsigned int nr_added_bufs;
spin_lock_init(&portdev->c_ivq_lock);
+ spin_lock_init(&portdev->c_ovq_lock);
INIT_WORK(&portdev->control_work, &control_work_handler);
nr_added_bufs = fill_queue(portdev->c_ivq,
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Mac Lin <[email protected]>
commit a3d9052c6296ad3398d3ad649c3c682c3e7ecfa6 upstream.
Since commit 0536bdf33faf (ARM: move iotable mappings within the vmalloc
region), the Cavium CNS3xxx cannot boot anymore.
This is caused by the pre-defined iotable mappings is not in the vmalloc
region. This patch move the iotable mappings into the vmalloc region, and
merge the MPCore private memory region (containing the SCU, the GIC and
the TWD) as a single region.
Signed-off-by: Mac Lin <[email protected]>
Signed-off-by: Anton Vorontsov <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
arch/arm/mach-cns3xxx/core.c | 16 +++-------------
arch/arm/mach-cns3xxx/include/mach/cns3xxx.h | 16 ++++++++--------
2 files changed, 11 insertions(+), 21 deletions(-)
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 031805b..7f26faf 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -22,19 +22,9 @@
static struct map_desc cns3xxx_io_desc[] __initdata = {
{
- .virtual = CNS3XXX_TC11MP_TWD_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT,
- .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE),
- .length = SZ_4K,
+ .virtual = CNS3XXX_TC11MP_SCU_BASE_VIRT,
+ .pfn = __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE),
+ .length = SZ_8K,
.type = MT_DEVICE,
}, {
.virtual = CNS3XXX_TIMER1_2_3_BASE_VIRT,
diff --git a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
index 191c8e5..b1021aa 100644
--- a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
+++ b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
@@ -94,10 +94,10 @@
#define RTC_INTR_STS_OFFSET 0x34
#define CNS3XXX_MISC_BASE 0x76000000 /* Misc Control */
-#define CNS3XXX_MISC_BASE_VIRT 0xFFF07000 /* Misc Control */
+#define CNS3XXX_MISC_BASE_VIRT 0xFB000000 /* Misc Control */
#define CNS3XXX_PM_BASE 0x77000000 /* Power Management Control */
-#define CNS3XXX_PM_BASE_VIRT 0xFFF08000
+#define CNS3XXX_PM_BASE_VIRT 0xFB001000
#define PM_CLK_GATE_OFFSET 0x00
#define PM_SOFT_RST_OFFSET 0x04
@@ -109,7 +109,7 @@
#define PM_PLL_HM_PD_OFFSET 0x1C
#define CNS3XXX_UART0_BASE 0x78000000 /* UART 0 */
-#define CNS3XXX_UART0_BASE_VIRT 0xFFF09000
+#define CNS3XXX_UART0_BASE_VIRT 0xFB002000
#define CNS3XXX_UART1_BASE 0x78400000 /* UART 1 */
#define CNS3XXX_UART1_BASE_VIRT 0xFFF0A000
@@ -130,7 +130,7 @@
#define CNS3XXX_I2S_BASE_VIRT 0xFFF10000
#define CNS3XXX_TIMER1_2_3_BASE 0x7C800000 /* Timer */
-#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFFF10800
+#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFB003000
#define TIMER1_COUNTER_OFFSET 0x00
#define TIMER1_AUTO_RELOAD_OFFSET 0x04
@@ -227,16 +227,16 @@
* Testchip peripheral and fpga gic regions
*/
#define CNS3XXX_TC11MP_SCU_BASE 0x90000000 /* IRQ, Test chip */
-#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFF000000
+#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFB004000
#define CNS3XXX_TC11MP_GIC_CPU_BASE 0x90000100 /* Test chip interrupt controller CPU interface */
-#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT 0xFF000100
+#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x100)
#define CNS3XXX_TC11MP_TWD_BASE 0x90000600
-#define CNS3XXX_TC11MP_TWD_BASE_VIRT 0xFF000600
+#define CNS3XXX_TC11MP_TWD_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x600)
#define CNS3XXX_TC11MP_GIC_DIST_BASE 0x90001000 /* Test chip interrupt controller distributor */
-#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT 0xFF001000
+#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x1000)
#define CNS3XXX_TC11MP_L220_BASE 0x92002000 /* L220 registers */
#define CNS3XXX_TC11MP_L220_BASE_VIRT 0xFF002000
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: "Iestyn C. Elfick" <[email protected]>
commit b251412db99ccd4495ce372fec7daee27bf06923 upstream.
Intermittently, b43 will report "Out of order TX status report on DMA ring".
When this happens, the driver must be reset before communication can resume.
The cause of the problem is believed to be an error in the closed-source
firmware; however, all versions of the firmware are affected.
This change uses the observation that the expected status is always 2 less
than the observed value, and supplies a fake status report to skip one
header/data pair.
Not all devices suffer from this problem, but it can occur several times
per second under heavy load. As each occurence kills the unmodified driver,
this patch makes if possible for the affected devices to function. The patch
logs only the first instance of the reset operation to prevent spamming
the logs.
Tested-by: Chris Vine <[email protected]>
Signed-off-by: Larry Finger <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/b43/dma.c | 65 ++++++++++++++++++++++++++++++++++--------
1 file changed, 53 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 38bc5a7..1221469 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
const struct b43_dma_ops *ops;
struct b43_dmaring *ring;
struct b43_dmadesc_meta *meta;
+ static const struct b43_txstatus fake; /* filled with 0 */
+ const struct b43_txstatus *txstat;
int slot, firstused;
bool frame_succeed;
+ int skip;
+ static u8 err_out1, err_out2;
ring = parse_cookie(dev, status->cookie, &slot);
if (unlikely(!ring))
@@ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
firstused = ring->current_slot - ring->used_slots + 1;
if (firstused < 0)
firstused = ring->nr_slots + firstused;
+
+ skip = 0;
if (unlikely(slot != firstused)) {
/* This possibly is a firmware bug and will result in
- * malfunction, memory leaks and/or stall of DMA functionality. */
- b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
- "Expected %d, but got %d\n",
- ring->index, firstused, slot);
- return;
+ * malfunction, memory leaks and/or stall of DMA functionality.
+ */
+ if (slot == next_slot(ring, next_slot(ring, firstused))) {
+ /* If a single header/data pair was missed, skip over
+ * the first two slots in an attempt to recover.
+ */
+ slot = firstused;
+ skip = 2;
+ if (!err_out1) {
+ /* Report the error once. */
+ b43dbg(dev->wl,
+ "Skip on DMA ring %d slot %d.\n",
+ ring->index, slot);
+ err_out1 = 1;
+ }
+ } else {
+ /* More than a single header/data pair were missed.
+ * Report this error once.
+ */
+ if (!err_out2)
+ b43dbg(dev->wl,
+ "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
+ ring->index, firstused, slot);
+ err_out2 = 1;
+ return;
+ }
}
ops = ring->ops;
@@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
slot, firstused, ring->index);
break;
}
+
if (meta->skb) {
struct b43_private_tx_info *priv_info =
- b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+ b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
- unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+ unmap_descbuffer(ring, meta->dmaaddr,
+ meta->skb->len, 1);
kfree(priv_info->bouncebuffer);
priv_info->bouncebuffer = NULL;
} else {
@@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
struct ieee80211_tx_info *info;
if (unlikely(!meta->skb)) {
- /* This is a scatter-gather fragment of a frame, so
- * the skb pointer must not be NULL. */
+ /* This is a scatter-gather fragment of a frame,
+ * so the skb pointer must not be NULL.
+ */
b43dbg(dev->wl, "TX status unexpected NULL skb "
"at slot %d (first=%d) on ring %d\n",
slot, firstused, ring->index);
@@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
/*
* Call back to inform the ieee80211 subsystem about
- * the status of the transmission.
+ * the status of the transmission. When skipping over
+ * a missed TX status report, use a status structure
+ * filled with zeros to indicate that the frame was not
+ * sent (frame_count 0) and not acknowledged
*/
- frame_succeed = b43_fill_txstatus_report(dev, info, status);
+ if (unlikely(skip))
+ txstat = &fake;
+ else
+ txstat = status;
+
+ frame_succeed = b43_fill_txstatus_report(dev, info,
+ txstat);
#ifdef CONFIG_B43_DEBUG
if (frame_succeed)
ring->nr_succeed_tx_packets++;
@@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
/* Everything unmapped and free'd. So it's not used anymore. */
ring->used_slots--;
- if (meta->is_last_fragment) {
+ if (meta->is_last_fragment && !skip) {
/* This is the last scatter-gather
* fragment of the frame. We are done. */
break;
}
slot = next_slot(ring, slot);
+ if (skip > 0)
+ --skip;
}
if (ring->stopped) {
B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Shah <[email protected]>
commit 165b1b8bbc17c9469b053bab78b11b7cbce6d161 upstream.
The cvq_lock was taken for the c_ivq. Rename the lock to make that
obvious.
We'll also add a lock around the c_ovq in the next commit, so there's no
ambiguity.
Signed-off-by: Amit Shah <[email protected]>
Reviewed-by: Asias He <[email protected]>
Reviewed-by: Wanlong Gao <[email protected]>
Signed-off-by: Rusty Russell <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/char/virtio_console.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index f77e341..4c76834 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -131,7 +131,7 @@ struct ports_device {
spinlock_t ports_lock;
/* To protect the vq operations for the control channel */
- spinlock_t cvq_lock;
+ spinlock_t c_ivq_lock;
/* The current config space is stored here */
struct virtio_console_config config;
@@ -1465,23 +1465,23 @@ static void control_work_handler(struct work_struct *work)
portdev = container_of(work, struct ports_device, control_work);
vq = portdev->c_ivq;
- spin_lock(&portdev->cvq_lock);
+ spin_lock(&portdev->c_ivq_lock);
while ((buf = virtqueue_get_buf(vq, &len))) {
- spin_unlock(&portdev->cvq_lock);
+ spin_unlock(&portdev->c_ivq_lock);
buf->len = len;
buf->offset = 0;
handle_control_message(portdev, buf);
- spin_lock(&portdev->cvq_lock);
+ spin_lock(&portdev->c_ivq_lock);
if (add_inbuf(portdev->c_ivq, buf) < 0) {
dev_warn(&portdev->vdev->dev,
"Error adding buffer to queue\n");
free_buf(buf);
}
}
- spin_unlock(&portdev->cvq_lock);
+ spin_unlock(&portdev->c_ivq_lock);
}
static void out_intr(struct virtqueue *vq)
@@ -1742,10 +1742,11 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
if (multiport) {
unsigned int nr_added_bufs;
- spin_lock_init(&portdev->cvq_lock);
+ spin_lock_init(&portdev->c_ivq_lock);
INIT_WORK(&portdev->control_work, &control_work_handler);
- nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+ nr_added_bufs = fill_queue(portdev->c_ivq,
+ &portdev->c_ivq_lock);
if (!nr_added_bufs) {
dev_err(&vdev->dev,
"Error allocating buffers for control queue\n");
@@ -1886,7 +1887,7 @@ static int virtcons_restore(struct virtio_device *vdev)
return ret;
if (use_multiport(portdev))
- fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+ fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
list_for_each_entry(port, &portdev->ports, list) {
port->in_vq = portdev->in_vqs[port->id];
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
commit e67dd874e60529dbd2e8232babb1e23479ba2ffa upstream.
We're using "mind" variable to find the VCM that got the best polling
results. For each VCM we calculte "currd" which is compared to the
"mind". For PHY rev3+ "currd" gets values around 14k-40k. Looking for a
value smaller than 40 makes no sense, so increase the initial value.
This fixes a regression introduced in 3.4 by commit:
e0c9a0219a8f542e3946fe972a68aacf8c3f906c
(my BCM4322 performance dropped from 18,4Mb/s to 9,26Mb/s)
Signed-off-by: Rafał Miłecki <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/b43/phy_n.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 1081188..5ae0b6a 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -1371,7 +1371,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
}
for (i = 0; i < 4; i++) {
s32 curr;
- s32 mind = 40;
+ s32 mind = 0x100000;
s32 minpoll = 249;
u8 minvcm = 0;
if (2 * core != i)
@@ -1554,7 +1554,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
}
for (i = 0; i < 4; i++) {
- s32 mind = 40;
+ s32 mind = 0x100000;
u8 minvcm = 0;
s32 minpoll = 249;
s32 curr;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
commit 2e1253d640eb7f8707d2591c93097c1e9f9c71d5 upstream.
When calculating "offset" for final RSSI calibration we're using numbers
bigger than s8 can hold. We have for example:
offset[j] = 232 - poll_results[j];
formula. If poll_results[j] is small enough (it usually is) we treat
number's bit as a sign bit. For example 232 - 1 becomes:
0xE8 - 0x1 = 0xE7, which is not 231 but -25.
This code was introduced in e0c9a0219a8f542e3946fe972a68aacf8c3f906c
and caused stability regression on some cards, for ex. BCM4322.
Signed-off-by: Rafał Miłecki <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/b43/phy_n.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 5ae0b6a..6be2f73 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -1320,7 +1320,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
u16 clip_off[2] = { 0xFFFF, 0xFFFF };
u8 vcm_final = 0;
- s8 offset[4];
+ s32 offset[4];
s32 results[8][4] = { };
s32 results_min[4] = { };
s32 poll_results[4] = { };
@@ -1487,7 +1487,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
u8 regs_save_radio[2];
u16 regs_save_phy[2];
- s8 offset[4];
+ s32 offset[4];
u8 core;
u8 rail;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde <[email protected]>
commit f901b6bc404b67d96eca739857c097e022727b71 upstream.
Thias patch fixes a define conflict between the SH architecture and the sja1000
driver:
drivers/net/can/sja1000/sja1000.h:59:0: warning:
"REG_SR" redefined [enabled by default]
arch/sh/include/asm/ptrace_32.h:25:0: note:
this is the location of the previous definition
A SJA1000_ prefix is added to the offending sja1000 define only, to make a
minimal patch suited for stable. A later patch will add a SJA1000_ prefix to
all defines in sja1000.h.
Reported-by: Fengguang Wu <[email protected]>
Signed-off-by: Marc Kleine-Budde <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/can/sja1000/plx_pci.c | 4 ++--
drivers/net/can/sja1000/sja1000.c | 6 +++---
drivers/net/can/sja1000/sja1000.h | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c
index 8bc9598..8099275 100644
--- a/drivers/net/can/sja1000/plx_pci.c
+++ b/drivers/net/can/sja1000/plx_pci.c
@@ -329,7 +329,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
*/
if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) ==
REG_CR_BASICCAN_INITIAL &&
- (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) &&
+ (priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_BASICCAN_INITIAL) &&
(priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL))
flag = 1;
@@ -341,7 +341,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
* See states on p. 23 of the Datasheet.
*/
if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL &&
- priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL &&
+ priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_PELICAN_INITIAL &&
priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL)
return flag;
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 5e10472..c2309ec 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -91,7 +91,7 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
*/
spin_lock_irqsave(&priv->cmdreg_lock, flags);
priv->write_reg(priv, REG_CMR, val);
- priv->read_reg(priv, REG_SR);
+ priv->read_reg(priv, SJA1000_REG_SR);
spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
}
@@ -496,7 +496,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
n++;
- status = priv->read_reg(priv, REG_SR);
+ status = priv->read_reg(priv, SJA1000_REG_SR);
/* check for absent controller due to hw unplug */
if (status == 0xFF && sja1000_is_absent(priv))
return IRQ_NONE;
@@ -515,7 +515,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
/* receive interrupt */
while (status & SR_RBS) {
sja1000_rx(dev);
- status = priv->read_reg(priv, REG_SR);
+ status = priv->read_reg(priv, SJA1000_REG_SR);
/* check for absent controller */
if (status == 0xFF && sja1000_is_absent(priv))
return IRQ_NONE;
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index 23fff06..2a79543 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -56,7 +56,7 @@
/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
#define REG_MOD 0x00
#define REG_CMR 0x01
-#define REG_SR 0x02
+#define SJA1000_REG_SR 0x02
#define REG_IR 0x03
#define REG_IER 0x04
#define REG_ALC 0x0B
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: "J. Bruce Fields" <[email protected]>
commit 64a817cfbded8674f345d1117b117f942a351a69 upstream.
Since we only enforce an upper bound, not a lower bound, a "negative"
length can get through here.
The symptom seen was a warning when we attempt to a kmalloc with an
excessive size.
Reported-by: Toralf Förster <[email protected]>
Signed-off-by: J. Bruce Fields <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/nfsd/nfs4xdr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1e83186..4684514 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -263,7 +263,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
iattr->ia_valid |= ATTR_SIZE;
}
if (bmval[0] & FATTR4_WORD0_ACL) {
- int nace;
+ u32 nace;
struct nfs4_ace *ace;
READ_BUF(4); len += 4;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Emmanuel Grumbach <[email protected]>
commit 2d5d50ee596361566f7f84300117cba7d7672bc5 upstream.
There is a race between the restart flow and the workers.
The workers are cancelled after the fw is already killed
and might send HCMD when there is fw to handle them.
Simply check that there is a fw to which the HCMD can be
sent before actually sending it.
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
[ luis: backported to 3.5:
- file rename: dvm/lib.c -> iwl-agn-lib.c
- file rename: dvm/ucode.c -> iwl-ucode.c
- adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 9 +++++++++
drivers/net/wireless/iwlwifi/iwl-ucode.c | 4 ++--
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index c31072d..b3dc9b6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1260,6 +1260,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
}
/*
+ * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag
+ * in iwl_down but cancel the workers only later.
+ */
+ if (!priv->ucode_loaded) {
+ IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id);
+ return -EIO;
+ }
+
+ /*
* Synchronous commands from this op-mode must hold
* the mutex, this ensures we don't try to send two
* (or more) synchronous commands at a time.
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c
index bc40dc6..d67d2b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c
@@ -425,6 +425,8 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
return -EIO;
}
+ priv->ucode_loaded = true;
+
/*
* This step takes a long time (60-80ms!!) and
* WoWLAN image should be loaded quickly, so
@@ -449,8 +451,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
return ret;
}
- priv->ucode_loaded = true;
-
return 0;
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Lars-Peter Clausen <[email protected]>
commit 8abac3ba51b5525354e9b2ec0eed1c9e95c905d9 upstream.
The last register block, which falls into the specified range, is not handled
correctly. The formula which calculates the number of register which should be
synced is inverse (and off by one). E.g. if all registers in that block should
be synced only one is synced, and if only one should be synced all (but one) are
synced. To calculate the number of registers that need to be synced we need to
subtract the number of the first register in the block from the max register
number and add one. This patch updates the code accordingly.
The issue was introduced in commit ac8d91c ("regmap: Supply ranges to the sync
operations").
Signed-off-by: Lars-Peter Clausen <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/base/regmap/regcache-rbtree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index e6732cf..79f4fca 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -398,7 +398,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
base = 0;
if (max < rbnode->base_reg + rbnode->blklen)
- end = rbnode->base_reg + rbnode->blklen - max;
+ end = max - rbnode->base_reg + 1;
else
end = rbnode->blklen;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Steve Glendinning <[email protected]>
commit 4c51e53689569398d656e631c17308d9b8e84650 upstream.
This patch enables RX of jumbo frames for LAN7500.
Previously the driver would transmit jumbo frames succesfully but
would drop received jumbo frames (incrementing the interface errors
count).
With this patch applied the device can succesfully receive jumbo
frames up to MTU 9000 (9014 bytes on the wire including ethernet
header).
Signed-off-by: Steve Glendinning <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/usb/smsc75xx.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 1c6e515..2e50fbb 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -724,8 +724,12 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
{
struct usbnet *dev = netdev_priv(netdev);
+ int ret;
+
+ if (new_mtu > MAX_SINGLE_PACKET_SIZE)
+ return -EINVAL;
- int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
+ ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
check_warn_return(ret, "Failed to set mac rx frame length");
return usbnet_change_mtu(netdev, new_mtu);
@@ -983,7 +987,7 @@ static int smsc75xx_reset(struct usbnet *dev)
netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x", buf);
- ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
+ ret = smsc75xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN);
check_warn_return(ret, "Failed to set max rx frame length");
ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
@@ -1127,8 +1131,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT))
dev->net->stats.rx_frame_errors++;
} else {
- /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
- if (unlikely(size > (ETH_FRAME_LEN + 12))) {
+ /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */
+ if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) {
netif_dbg(dev, rx_err, dev->net,
"size err rx_cmd_a=0x%08x", rx_cmd_a);
return 0;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Frederic Sowa <[email protected]>
commit 20314092c1b41894d8c181bf9aa6f022be2416aa upstream.
v2:
a) moved before multicast source address check
b) changed comment to netdev style
Cc: Erik Hugne <[email protected]>
Cc: YOSHIFUJI Hideaki <[email protected]>
Acked-by: YOSHIFUJI Hideaki <[email protected]>
Signed-off-by: Hannes Frederic Sowa <[email protected]>
Acked-by: YOSHIFUJI Hideaki <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/ipv6/ip6_input.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 61dfb1d..311eac7 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -111,6 +111,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
ipv6_addr_loopback(&hdr->daddr))
goto err;
+ /* RFC4291 2.7
+ * Nodes must not originate a packet to a multicast address whose scope
+ * field contains the reserved value 0; if such a packet is received, it
+ * must be silently dropped.
+ */
+ if (ipv6_addr_is_multicast(&hdr->daddr) &&
+ IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
+ goto err;
+
/*
* RFC4291 2.7
* Multicast addresses must not be used as source addresses in IPv6
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Veaceslav Falico <[email protected]>
commit 76a0e68129d7d24eb995a6871ab47081bbfa0acc upstream.
skb->ip_summed should be CHECKSUM_UNNECESSARY when the driver reports that
checksums were correct and CHECKSUM_NONE in any other case. They're
currently placed vice versa, which breaks the forwarding scenario. Fix it
by placing them as described above.
Signed-off-by: Veaceslav Falico <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 3787c64..9400ce8 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -1747,9 +1747,9 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
skb->protocol = eth_type_trans(skb, netdev);
if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
- skb->ip_summed = CHECKSUM_NONE;
- else
skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
napi_gro_receive(&adapter->napi, skb);
(*work_done)++;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 00cfec37484761a44a3b6f4675a54caa618210ae upstream.
commit 35d48903e97819 (bonding: fix rx_handler locking) added a race
in bonding driver, reported by Steven Rostedt who did a very good
diagnosis :
<quoting Steven>
I'm currently debugging a crash in an old 3.0-rt kernel that one of our
customers is seeing. The bug happens with a stress test that loads and
unloads the bonding module in a loop (I don't know all the details as
I'm not the one that is directly interacting with the customer). But the
bug looks to be something that may still be present and possibly present
in mainline too. It will just be much harder to trigger it in mainline.
In -rt, interrupts are threads, and can schedule in and out just like
any other thread. Note, mainline now supports interrupt threads so this
may be easily reproducible in mainline as well. I don't have the ability
to tell the customer to try mainline or other kernels, so my hands are
somewhat tied to what I can do.
But according to a core dump, I tracked down that the eth irq thread
crashed in bond_handle_frame() here:
slave = bond_slave_get_rcu(skb->dev);
bond = slave->bond; <--- BUG
the slave returned was NULL and accessing slave->bond caused a NULL
pointer dereference.
Looking at the code that unregisters the handler:
void netdev_rx_handler_unregister(struct net_device *dev)
{
ASSERT_RTNL();
RCU_INIT_POINTER(dev->rx_handler, NULL);
RCU_INIT_POINTER(dev->rx_handler_data, NULL);
}
Which is basically:
dev->rx_handler = NULL;
dev->rx_handler_data = NULL;
And looking at __netif_receive_skb() we have:
rx_handler = rcu_dereference(skb->dev->rx_handler);
if (rx_handler) {
if (pt_prev) {
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = NULL;
}
switch (rx_handler(&skb)) {
My question to all of you is, what stops this interrupt from happening
while the bonding module is unloading? What happens if the interrupt
triggers and we have this:
CPU0 CPU1
---- ----
rx_handler = skb->dev->rx_handler
netdev_rx_handler_unregister() {
dev->rx_handler = NULL;
dev->rx_handler_data = NULL;
rx_handler()
bond_handle_frame() {
slave = skb->dev->rx_handler;
bond = slave->bond; <-- NULL pointer dereference!!!
What protection am I missing in the bond release handler that would
prevent the above from happening?
</quoting Steven>
We can fix bug this in two ways. First is adding a test in
bond_handle_frame() and others to check if rx_handler_data is NULL.
A second way is adding a synchronize_net() in
netdev_rx_handler_unregister() to make sure that a rcu protected reader
has the guarantee to see a non NULL rx_handler_data.
The second way is better as it avoids an extra test in fast path.
Reported-by: Steven Rostedt <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Jiri Pirko <[email protected]>
Cc: Paul E. McKenney <[email protected]>
Acked-by: Steven Rostedt <[email protected]>
Reviewed-by: Paul E. McKenney <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/core/dev.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/core/dev.c b/net/core/dev.c
index 39aa9e6..845a83a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3121,6 +3121,7 @@ int netdev_rx_handler_register(struct net_device *dev,
if (dev->rx_handler)
return -EBUSY;
+ /* Note: rx_handler_data must be set before rx_handler */
rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
rcu_assign_pointer(dev->rx_handler, rx_handler);
@@ -3141,6 +3142,11 @@ void netdev_rx_handler_unregister(struct net_device *dev)
ASSERT_RTNL();
RCU_INIT_POINTER(dev->rx_handler, NULL);
+ /* a reader seeing a non NULL rx_handler in a rcu_read_lock()
+ * section has a guarantee to see a non NULL rx_handler_data
+ * as well.
+ */
+ synchronize_net();
RCU_INIT_POINTER(dev->rx_handler_data, NULL);
}
EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 91c5746425aed8f7188a351f1224a26aa232e4b3 upstream.
Some network drivers use a non default hard_header_len
Transmitted skb should take into account dev->hard_header_len, or risk
crashes or expensive reallocations.
In the case of aoe, lets reserve MAX_HEADER bytes.
David reported a crash in defxx driver, solved by this patch.
Reported-by: David Oostdyk <[email protected]>
Tested-by: David Oostdyk <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Ed Cashin <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/block/aoe/aoecmd.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 887f68f..db30542 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -30,8 +30,9 @@ new_skb(ulong len)
{
struct sk_buff *skb;
- skb = alloc_skb(len, GFP_ATOMIC);
+ skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC);
if (skb) {
+ skb_reserve(skb, MAX_HEADER);
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb->protocol = __constant_htons(ETH_P_AOE);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: "[email protected]" <[email protected]>
commit 14bc435ea54cb888409efb54fc6b76c13ef530e9 upstream.
According to the Datasheet (page 52):
15-12 Reserved
11-0 RXBC Receive Byte Count
This field indicates the present received frame byte size.
The code has a bug:
rxh = ks8851_rdreg32(ks, KS_RXFHSR);
rxstat = rxh & 0xffff;
rxlen = rxh >> 16; // BUG!!! 0xFFF mask should be applied
Signed-off-by: Max Nekludov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/micrel/ks8851.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 5e313e9..2a417c3 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -547,7 +547,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
for (; rxfc != 0; rxfc--) {
rxh = ks8851_rdreg32(ks, KS_RXFHSR);
rxstat = rxh & 0xffff;
- rxlen = rxh >> 16;
+ rxlen = (rxh >> 16) & 0xfff;
netif_dbg(ks, rx_status, ks->netdev,
"rx: stat 0x%04x, len 0x%04x\n", rxstat, rxlen);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Hong Zhiguo <[email protected]>
commit a79ca223e029aa4f09abb337accf1812c900a800 upstream.
Signed-off-by: Hong Zhiguo <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/ipv6/addrconf.c | 26 ++++++++++----------------
1 file changed, 10 insertions(+), 16 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index fc9ac78..00188b3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4658,26 +4658,20 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev)
static int __net_init addrconf_init_net(struct net *net)
{
- int err;
+ int err = -ENOMEM;
struct ipv6_devconf *all, *dflt;
- err = -ENOMEM;
- all = &ipv6_devconf;
- dflt = &ipv6_devconf_dflt;
+ all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
+ if (all == NULL)
+ goto err_alloc_all;
- if (!net_eq(net, &init_net)) {
- all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL);
- if (all == NULL)
- goto err_alloc_all;
+ dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
+ if (dflt == NULL)
+ goto err_alloc_dflt;
- dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
- if (dflt == NULL)
- goto err_alloc_dflt;
- } else {
- /* these will be inherited by all namespaces */
- dflt->autoconf = ipv6_defaults.autoconf;
- dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
- }
+ /* these will be inherited by all namespaces */
+ dflt->autoconf = ipv6_defaults.autoconf;
+ dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
net->ipv6.devconf_all = all;
net->ipv6.devconf_dflt = dflt;
--
1.8.1.2
On Mon, Apr 08, 2013 at 10:49:50AM +0100, Luis Henriques wrote:
> 3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
>
> ------------------
>
> From: Johan Hovold <[email protected]>
>
> commit e5b33dc9d16053c2ae4c2c669cf008829530364b upstream.
>
> Add modem-status-change wait queue to struct usb_serial_port that
> subdrivers can use to implement TIOCMIWAIT.
>
> Currently subdrivers use a private wait queue which may have been
> released when waking up after device disconnected.
>
> Note that we're adding a new wait queue rather than reusing the tty-port
> one as we do not want to get woken up at hangup (yet).
This one should be followed by eba0e3c3a0ba7b96f0 (USB: serial: fix hang
when opening port) which adds the missing queue initialisation. It
appears the next patch in your series starts using the wait queue
directly.
Thanks,
Johan
> Signed-off-by: Johan Hovold <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
> Signed-off-by: Luis Henriques <[email protected]>
> ---
> include/linux/usb/serial.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
> index 86c0b45..0b61f01 100644
> --- a/include/linux/usb/serial.h
> +++ b/include/linux/usb/serial.h
> @@ -66,6 +66,7 @@
> * port.
> * @flags: usb serial port flags
> * @write_wait: a wait_queue_head_t used by the port.
> + * @delta_msr_wait: modem-status-change wait queue
> * @work: work queue entry for the line discipline waking up.
> * @throttled: nonzero if the read urb is inactive to throttle the device
> * @throttle_req: nonzero if the tty wants to throttle us
> @@ -112,6 +113,7 @@ struct usb_serial_port {
>
> unsigned long flags;
> wait_queue_head_t write_wait;
> + wait_queue_head_t delta_msr_wait;
> struct work_struct work;
> char throttled;
> char throttle_req;
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrey Vagin <[email protected]>
commit ae5fc98728c8bbbd6d7cab0b9781671fc4419c1b upstream.
Follow the common pattern and define *_DIAG_MAX like:
[...]
__XXX_DIAG_MAX,
};
Because everyone is used to do:
struct nlattr *attrs[XXX_DIAG_MAX+1];
nla_parse([...], XXX_DIAG_MAX, [...]
Reported-by: Thomas Graf <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: Pavel Emelyanov <[email protected]>
Cc: Eric Dumazet <[email protected]>
Cc: "Paul E. McKenney" <[email protected]>
Cc: David Howells <[email protected]>
Signed-off-by: Andrey Vagin <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[ luis: backport to 3.5:
- fix unix_diag.h path
- packet_diag.h does not exist ]
Signed-off-by: Luis Henriques <[email protected]>
---
include/linux/unix_diag.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h
index b1d2bf1..0ff4d32 100644
--- a/include/linux/unix_diag.h
+++ b/include/linux/unix_diag.h
@@ -38,9 +38,11 @@ enum {
UNIX_DIAG_RQLEN,
UNIX_DIAG_MEMINFO,
- UNIX_DIAG_MAX,
+ __UNIX_DIAG_MAX,
};
+#define UNIX_DIAG_MAX (__UNIX_DIAG_MAX - 1)
+
struct unix_diag_vfs {
__u32 udiag_vfs_ino;
__u32 udiag_vfs_dev;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Frederic Sowa <[email protected]>
commit 188ab1b105c96656f6bcfb49d0d8bb1b1936b632 upstream.
Usage of pci-msi results in corrupted dma packet transfers to the host.
Reported-by: rebelyouth <[email protected]>
Cc: Huang, Xiong <[email protected]>
Tested-by: Christian Sünkenberg <[email protected]>
Signed-off-by: Hannes Frederic Sowa <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/atheros/atl1e/atl1e.h | 1 -
drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 19 ++-----------------
2 files changed, 2 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h
index 829b5ad..edfdf6b 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e.h
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h
@@ -438,7 +438,6 @@ struct atl1e_adapter {
struct atl1e_hw hw;
struct atl1e_hw_stats hw_stats;
- bool have_msi;
u32 wol;
u16 link_speed;
u16 link_duplex;
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 1220e51..38f7093 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1870,34 +1870,19 @@ static void atl1e_free_irq(struct atl1e_adapter *adapter)
struct net_device *netdev = adapter->netdev;
free_irq(adapter->pdev->irq, netdev);
-
- if (adapter->have_msi)
- pci_disable_msi(adapter->pdev);
}
static int atl1e_request_irq(struct atl1e_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
struct net_device *netdev = adapter->netdev;
- int flags = 0;
int err = 0;
- adapter->have_msi = true;
- err = pci_enable_msi(pdev);
- if (err) {
- netdev_dbg(netdev,
- "Unable to allocate MSI interrupt Error: %d\n", err);
- adapter->have_msi = false;
- }
-
- if (!adapter->have_msi)
- flags |= IRQF_SHARED;
- err = request_irq(pdev->irq, atl1e_intr, flags, netdev->name, netdev);
+ err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, netdev->name,
+ netdev);
if (err) {
netdev_dbg(adapter->netdev,
"Unable to allocate interrupt Error: %d\n", err);
- if (adapter->have_msi)
- pci_disable_msi(pdev);
return err;
}
netdev_dbg(netdev, "atl1e_request_irq OK\n");
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Veaceslav Falico <[email protected]>
commit 9fe16b78ee17579cb4f333534cf7043e94c67024 upstream.
If slave sysfs symlink failes to be created - we end up without removing
the master sysfs symlink. Remove it in case of failure.
Signed-off-by: Veaceslav Falico <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/bonding/bond_sysfs.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 9ea29aa..97c33c2 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -183,6 +183,11 @@ int bond_create_slave_symlinks(struct net_device *master,
sprintf(linkname, "slave_%s", slave->name);
ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
linkname);
+
+ /* free the master link created earlier in case of error */
+ if (ret)
+ sysfs_remove_link(&(slave->dev.kobj), "master");
+
return ret;
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph CHANG <[email protected]>
commit 6741f40d198c6a5feb23653a1efd4ca47f93d83d upstream.
Fix bug for DM9000 revision B which contain a DSP PHY
DM9000B use DSP PHY instead previouse DM9000 revisions' analog PHY,
So need extra change in initialization, For
explicity PHY Reset and PHY init parameter, and
first DM9000_NCR reset need NCR_MAC_LBK bit by dm9000_probe().
Following DM9000_NCR reset cause by dm9000_open() clear the
NCR_MAC_LBK bit.
Without this fix, Power-up FIFO pointers error happen around 2%
rate among Davicom's customers' boards. With this fix, All above
cases can be solved.
Signed-off-by: Joseph CHANG <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/davicom/dm9000.c | 214 +++++++++++++++++-----------------
drivers/net/ethernet/davicom/dm9000.h | 11 +-
2 files changed, 120 insertions(+), 105 deletions(-)
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 36499d5..a9628b6 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -257,6 +257,107 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
tmp = readl(reg);
}
+/*
+ * Sleep, either by using msleep() or if we are suspending, then
+ * use mdelay() to sleep.
+ */
+static void dm9000_msleep(board_info_t *db, unsigned int ms)
+{
+ if (db->in_suspend)
+ mdelay(ms);
+ else
+ msleep(ms);
+}
+
+/* Read a word from phyxcer */
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
+{
+ board_info_t *db = netdev_priv(dev);
+ unsigned long flags;
+ unsigned int reg_save;
+ int ret;
+
+ mutex_lock(&db->addr_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+
+ /* Fill the phyxcer register into REG_0C */
+ iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+ /* Issue phyxcer read command */
+ iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);
+
+ writeb(reg_save, db->io_addr);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ dm9000_msleep(db, 1); /* Wait read complete */
+
+ spin_lock_irqsave(&db->lock, flags);
+ reg_save = readb(db->io_addr);
+
+ iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */
+
+ /* The read data keeps on REG_0D & REG_0E */
+ ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+
+ /* restore the previous address */
+ writeb(reg_save, db->io_addr);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ mutex_unlock(&db->addr_lock);
+
+ dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
+ return ret;
+}
+
+/* Write a word to phyxcer */
+static void
+dm9000_phy_write(struct net_device *dev,
+ int phyaddr_unused, int reg, int value)
+{
+ board_info_t *db = netdev_priv(dev);
+ unsigned long flags;
+ unsigned long reg_save;
+
+ dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
+ mutex_lock(&db->addr_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+
+ /* Fill the phyxcer register into REG_0C */
+ iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+ /* Fill the written data into REG_0D & REG_0E */
+ iow(db, DM9000_EPDRL, value);
+ iow(db, DM9000_EPDRH, value >> 8);
+
+ /* Issue phyxcer write command */
+ iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);
+
+ writeb(reg_save, db->io_addr);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ dm9000_msleep(db, 1); /* Wait write complete */
+
+ spin_lock_irqsave(&db->lock, flags);
+ reg_save = readb(db->io_addr);
+
+ iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
+
+ /* restore the previous address */
+ writeb(reg_save, db->io_addr);
+
+ spin_unlock_irqrestore(&db->lock, flags);
+ mutex_unlock(&db->addr_lock);
+}
+
/* dm9000_set_io
*
* select the specified set of io routines to use with the
@@ -794,6 +895,9 @@ dm9000_init_dm9000(struct net_device *dev)
iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
+ dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
+ dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */
+
ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
/* if wol is needed, then always set NCR_WAKEEN otherwise we end
@@ -1200,109 +1304,6 @@ dm9000_open(struct net_device *dev)
return 0;
}
-/*
- * Sleep, either by using msleep() or if we are suspending, then
- * use mdelay() to sleep.
- */
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
-{
- if (db->in_suspend)
- mdelay(ms);
- else
- msleep(ms);
-}
-
-/*
- * Read a word from phyxcer
- */
-static int
-dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
-{
- board_info_t *db = netdev_priv(dev);
- unsigned long flags;
- unsigned int reg_save;
- int ret;
-
- mutex_lock(&db->addr_lock);
-
- spin_lock_irqsave(&db->lock,flags);
-
- /* Save previous register address */
- reg_save = readb(db->io_addr);
-
- /* Fill the phyxcer register into REG_0C */
- iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
- iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */
-
- writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock,flags);
-
- dm9000_msleep(db, 1); /* Wait read complete */
-
- spin_lock_irqsave(&db->lock,flags);
- reg_save = readb(db->io_addr);
-
- iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */
-
- /* The read data keeps on REG_0D & REG_0E */
- ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
-
- /* restore the previous address */
- writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock,flags);
-
- mutex_unlock(&db->addr_lock);
-
- dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
- return ret;
-}
-
-/*
- * Write a word to phyxcer
- */
-static void
-dm9000_phy_write(struct net_device *dev,
- int phyaddr_unused, int reg, int value)
-{
- board_info_t *db = netdev_priv(dev);
- unsigned long flags;
- unsigned long reg_save;
-
- dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
- mutex_lock(&db->addr_lock);
-
- spin_lock_irqsave(&db->lock,flags);
-
- /* Save previous register address */
- reg_save = readb(db->io_addr);
-
- /* Fill the phyxcer register into REG_0C */
- iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
- /* Fill the written data into REG_0D & REG_0E */
- iow(db, DM9000_EPDRL, value);
- iow(db, DM9000_EPDRH, value >> 8);
-
- iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */
-
- writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock, flags);
-
- dm9000_msleep(db, 1); /* Wait write complete */
-
- spin_lock_irqsave(&db->lock,flags);
- reg_save = readb(db->io_addr);
-
- iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
-
- /* restore the previous address */
- writeb(reg_save, db->io_addr);
-
- spin_unlock_irqrestore(&db->lock, flags);
- mutex_unlock(&db->addr_lock);
-}
-
static void
dm9000_shutdown(struct net_device *dev)
{
@@ -1501,7 +1502,12 @@ dm9000_probe(struct platform_device *pdev)
db->flags |= DM9000_PLATF_SIMPLE_PHY;
#endif
- dm9000_reset(db);
+ /* Fixing bug on dm9000_probe, takeover dm9000_reset(db),
+ * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo
+ * while probe stage.
+ */
+
+ iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST);
/* try multiple times, DM9000 sometimes gets the read wrong */
for (i = 0; i < 8; i++) {
diff --git a/drivers/net/ethernet/davicom/dm9000.h b/drivers/net/ethernet/davicom/dm9000.h
index 55688bd..9ce058a 100644
--- a/drivers/net/ethernet/davicom/dm9000.h
+++ b/drivers/net/ethernet/davicom/dm9000.h
@@ -69,7 +69,9 @@
#define NCR_WAKEEN (1<<6)
#define NCR_FCOL (1<<4)
#define NCR_FDX (1<<3)
-#define NCR_LBK (3<<1)
+
+#define NCR_RESERVED (3<<1)
+#define NCR_MAC_LBK (1<<1)
#define NCR_RST (1<<0)
#define NSR_SPEED (1<<7)
@@ -167,5 +169,12 @@
#define ISR_LNKCHNG (1<<5)
#define ISR_UNDERRUN (1<<4)
+/* Davicom MII registers.
+ */
+
+#define MII_DM_DSPCR 0x1b /* DSP Control Register */
+
+#define DSPCR_INIT_PARAM 0xE100 /* DSP init parameter */
+
#endif /* _DM9000X_H_ */
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: "[email protected]" <[email protected]>
commit fbb0c41b814d497c656fc7be9e35456f139cb2fb upstream.
First I would give three observations which will be used later.
Observation 1: if (delayed_work_pending(wq)) cancel_delayed_work(wq)
This usage is wrong because the pending bit is cleared just before the
work's fn is executed and if the function re-arms itself we might end up
with the work still running. It's safe to call cancel_delayed_work_sync()
even if the work is not queued at all.
Observation 2: Use of INIT_DELAYED_WORK()
Work needs to be initialized only once prior to (de/en)queueing.
Observation 3: IFF_UP is set only after ndo_open is called
Related race conditions:
1. Race between bonding_store_miimon() and bonding_store_arp_interval()
Because of Obs.1 we can end up having both works enqueued.
2. Multiple races with INIT_DELAYED_WORK()
Since the works are not protected by anything between INIT_DELAYED_WORK()
and calls to (en/de)queue it is possible for races between the following
functions:
(races are also possible between the calls to INIT_DELAYED_WORK()
and workqueue code)
bonding_store_miimon() - bonding_store_arp_interval(), bond_close(),
bond_open(), enqueued functions
bonding_store_arp_interval() - bonding_store_miimon(), bond_close(),
bond_open(), enqueued functions
3. By Obs.1 we need to change bond_cancel_all()
Bugs 1 and 2 are fixed by moving all work initializations in bond_open
which by Obs. 2 and Obs. 3 and the fact that we make sure that all works
are cancelled in bond_close(), is guaranteed not to have any work
enqueued.
Also RTNL lock is now acquired in bonding_store_miimon/arp_interval so
they can't race with bond_close and bond_open. The opposing work is
cancelled only if the IFF_UP flag is set and it is cancelled
unconditionally. The opposing work is already cancelled if the interface
is down so no need to cancel it again. This way we don't need new
synchronizations for the bonding workqueue. These bugs (and fixes) are
tied together and belong in the same patch.
Note: I have left 1 line intentionally over 80 characters (84) because I
didn't like how it looks broken down. If you'd prefer it otherwise,
then simply break it.
v2: Make description text < 75 columns
Signed-off-by: Nikolay Aleksandrov <[email protected]>
Signed-off-by: Jay Vosburgh <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/bonding/bond_main.c | 88 ++++++++++++----------------------------
drivers/net/bonding/bond_sysfs.c | 34 +++++-----------
2 files changed, 36 insertions(+), 86 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a8406dc..1b6e13d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3407,6 +3407,28 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
/*-------------------------- Device entry points ----------------------------*/
+static void bond_work_init_all(struct bonding *bond)
+{
+ INIT_DELAYED_WORK(&bond->mcast_work,
+ bond_resend_igmp_join_requests_delayed);
+ INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
+ INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ INIT_DELAYED_WORK(&bond->arp_work, bond_activebackup_arp_mon);
+ else
+ INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon);
+ INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
+}
+
+static void bond_work_cancel_all(struct bonding *bond)
+{
+ cancel_delayed_work_sync(&bond->mii_work);
+ cancel_delayed_work_sync(&bond->arp_work);
+ cancel_delayed_work_sync(&bond->alb_work);
+ cancel_delayed_work_sync(&bond->ad_work);
+ cancel_delayed_work_sync(&bond->mcast_work);
+}
+
static int bond_open(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
@@ -3429,41 +3451,27 @@ static int bond_open(struct net_device *bond_dev)
}
read_unlock(&bond->lock);
- INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
+ bond_work_init_all(bond);
if (bond_is_lb(bond)) {
/* bond_alb_initialize must be called before the timer
* is started.
*/
- if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
- /* something went wrong - fail the open operation */
+ if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB)))
return -ENOMEM;
- }
-
- INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
queue_delayed_work(bond->wq, &bond->alb_work, 0);
}
- if (bond->params.miimon) { /* link check interval, in milliseconds. */
- INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ if (bond->params.miimon) /* link check interval, in milliseconds. */
queue_delayed_work(bond->wq, &bond->mii_work, 0);
- }
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_activebackup_arp_mon);
- else
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_loadbalance_arp_mon);
-
queue_delayed_work(bond->wq, &bond->arp_work, 0);
if (bond->params.arp_validate)
bond->recv_probe = bond_arp_rcv;
}
if (bond->params.mode == BOND_MODE_8023AD) {
- INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
queue_delayed_work(bond->wq, &bond->ad_work, 0);
/* register to receive LACPDUs */
bond->recv_probe = bond_3ad_lacpdu_recv;
@@ -3478,34 +3486,10 @@ static int bond_close(struct net_device *bond_dev)
struct bonding *bond = netdev_priv(bond_dev);
write_lock_bh(&bond->lock);
-
bond->send_peer_notif = 0;
-
write_unlock_bh(&bond->lock);
- if (bond->params.miimon) { /* link check interval, in milliseconds. */
- cancel_delayed_work_sync(&bond->mii_work);
- }
-
- if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- cancel_delayed_work_sync(&bond->arp_work);
- }
-
- switch (bond->params.mode) {
- case BOND_MODE_8023AD:
- cancel_delayed_work_sync(&bond->ad_work);
- break;
- case BOND_MODE_TLB:
- case BOND_MODE_ALB:
- cancel_delayed_work_sync(&bond->alb_work);
- break;
- default:
- break;
- }
-
- if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work_sync(&bond->mcast_work);
-
+ bond_work_cancel_all(bond);
if (bond_is_lb(bond)) {
/* Must be called only after all
* slaves have been released
@@ -4384,26 +4368,6 @@ static void bond_setup(struct net_device *bond_dev)
bond_dev->features |= bond_dev->hw_features;
}
-static void bond_work_cancel_all(struct bonding *bond)
-{
- if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
- cancel_delayed_work_sync(&bond->mii_work);
-
- if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
- cancel_delayed_work_sync(&bond->arp_work);
-
- if (bond->params.mode == BOND_MODE_ALB &&
- delayed_work_pending(&bond->alb_work))
- cancel_delayed_work_sync(&bond->alb_work);
-
- if (bond->params.mode == BOND_MODE_8023AD &&
- delayed_work_pending(&bond->ad_work))
- cancel_delayed_work_sync(&bond->ad_work);
-
- if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work_sync(&bond->mcast_work);
-}
-
/*
* Destroy a bonding device.
* Must be under rtnl_lock when this function is called.
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 97c33c2..1e2ad41 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -518,6 +518,8 @@ static ssize_t bonding_store_arp_interval(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (sscanf(buf, "%d", &new_value) != 1) {
pr_err("%s: no arp_interval value specified.\n",
bond->dev->name);
@@ -544,10 +546,6 @@ static ssize_t bonding_store_arp_interval(struct device *d,
pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
bond->dev->name, bond->dev->name);
bond->params.miimon = 0;
- if (delayed_work_pending(&bond->mii_work)) {
- cancel_delayed_work(&bond->mii_work);
- flush_workqueue(bond->wq);
- }
}
if (!bond->params.arp_targets[0]) {
pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
@@ -559,19 +557,12 @@ static ssize_t bonding_store_arp_interval(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (!delayed_work_pending(&bond->arp_work)) {
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_activebackup_arp_mon);
- else
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_loadbalance_arp_mon);
-
- queue_delayed_work(bond->wq, &bond->arp_work, 0);
- }
+ cancel_delayed_work_sync(&bond->mii_work);
+ queue_delayed_work(bond->wq, &bond->arp_work, 0);
}
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
@@ -967,6 +958,8 @@ static ssize_t bonding_store_miimon(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (sscanf(buf, "%d", &new_value) != 1) {
pr_err("%s: no miimon value specified.\n",
bond->dev->name);
@@ -998,10 +991,6 @@ static ssize_t bonding_store_miimon(struct device *d,
bond->params.arp_validate =
BOND_ARP_VALIDATE_NONE;
}
- if (delayed_work_pending(&bond->arp_work)) {
- cancel_delayed_work(&bond->arp_work);
- flush_workqueue(bond->wq);
- }
}
if (bond->dev->flags & IFF_UP) {
@@ -1010,15 +999,12 @@ static ssize_t bonding_store_miimon(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (!delayed_work_pending(&bond->mii_work)) {
- INIT_DELAYED_WORK(&bond->mii_work,
- bond_mii_monitor);
- queue_delayed_work(bond->wq,
- &bond->mii_work, 0);
- }
+ cancel_delayed_work_sync(&bond->arp_work);
+ queue_delayed_work(bond->wq, &bond->mii_work, 0);
}
}
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Mugunthan V N <[email protected]>
commit 7e51cde276ca820d526c6c21cf8147df595a36bf upstream.
To restart tx queue use netif_wake_queue() intead of netif_start_queue()
so that net schedule will restart transmission immediately which will
increase network performance while doing huge data transfers.
Reported-by: Dan Franke <[email protected]>
Suggested-by: Sriramakrishnan A G <[email protected]>
Signed-off-by: Mugunthan V N <[email protected]>
Acked-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/ti/davinci_emac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 4da93a5..762464e 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1053,7 +1053,7 @@ static void emac_tx_handler(void *token, int len, int status)
atomic_dec(&priv->cur_tx);
if (unlikely(netif_queue_stopped(ndev)))
- netif_start_queue(ndev);
+ netif_wake_queue(ndev);
ndev->stats.tx_packets++;
ndev->stats.tx_bytes += len;
dev_kfree_skb_any(skb);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Mugunthan V N <[email protected]>
commit b56d6b3fca6d1214dbc9c5655f26e5d4ec04afc8 upstream.
To restart tx queue use netif_wake_queue() intead of netif_start_queue()
so that net schedule will restart transmission immediately which will
increase network performance while doing huge data transfers.
Reported-by: Dan Franke <[email protected]>
Suggested-by: Sriramakrishnan A G <[email protected]>
Signed-off-by: Mugunthan V N <[email protected]>
Acked-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/ti/cpsw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 6685bbb..310e353 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -249,7 +249,7 @@ void cpsw_tx_handler(void *token, int len, int status)
struct cpsw_priv *priv = netdev_priv(ndev);
if (unlikely(netif_queue_stopped(ndev)))
- netif_start_queue(ndev);
+ netif_wake_queue(ndev);
priv->stats.tx_packets++;
priv->stats.tx_bytes += len;
dev_kfree_skb_any(skb);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Moore <[email protected]>
commit ded34e0fe8fe8c2d595bfa30626654e4b87621e0 upstream.
As reported by Jan, and others over the past few years, there is a
race condition caused by unix_release setting the sock->sk pointer
to NULL before properly marking the socket as dead/orphaned. This
can cause a problem with the LSM hook security_unix_may_send() if
there is another socket attempting to write to this partially
released socket in between when sock->sk is set to NULL and it is
marked as dead/orphaned. This patch fixes this by only setting
sock->sk to NULL after the socket has been marked as dead; I also
take the opportunity to make unix_release_sock() a void function
as it only ever returned 0/success.
Dave, I think this one should go on the -stable pile.
Special thanks to Jan for coming up with a reproducer for this
problem.
Reported-by: Jan Stancek <[email protected]>
Signed-off-by: Paul Moore <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/unix/af_unix.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 9aa708c..023db69 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -375,7 +375,7 @@ static void unix_sock_destructor(struct sock *sk)
#endif
}
-static int unix_release_sock(struct sock *sk, int embrion)
+static void unix_release_sock(struct sock *sk, int embrion)
{
struct unix_sock *u = unix_sk(sk);
struct path path;
@@ -444,8 +444,6 @@ static int unix_release_sock(struct sock *sk, int embrion)
if (unix_tot_inflight)
unix_gc(); /* Garbage collect fds */
-
- return 0;
}
static void init_peercred(struct sock *sk)
@@ -695,9 +693,10 @@ static int unix_release(struct socket *sock)
if (!sk)
return 0;
+ unix_release_sock(sk, 0);
sock->sk = NULL;
- return unix_release_sock(sk, 0);
+ return 0;
}
static int unix_autobind(struct socket *sock)
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: "[email protected]" <[email protected]>
commit 1bc7db16782c2a581fb4d53ca853631050f31611 upstream.
Currently if either arp_interval or miimon is disabled, they both get
disabled, and upon disabling they get executed once more which is not
the proper behaviour. Also when doing a no-op and disabling an already
disabled one, the other again gets disabled.
Also fix the error messages with the proper valid ranges, and a small
typo fix in the up delay error message (outputting "down delay", instead
of "up delay").
Signed-off-by: Nikolay Aleksandrov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/bonding/bond_sysfs.c | 92 +++++++++++++++++++++-------------------
1 file changed, 48 insertions(+), 44 deletions(-)
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 1e2ad41..ed4f9e5 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -527,7 +527,7 @@ static ssize_t bonding_store_arp_interval(struct device *d,
goto out;
}
if (new_value < 0) {
- pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+ pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n",
bond->dev->name, new_value, INT_MAX);
ret = -EINVAL;
goto out;
@@ -542,14 +542,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
pr_info("%s: Setting ARP monitoring interval to %d.\n",
bond->dev->name, new_value);
bond->params.arp_interval = new_value;
- if (bond->params.miimon) {
- pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
- bond->dev->name, bond->dev->name);
- bond->params.miimon = 0;
- }
- if (!bond->params.arp_targets[0]) {
- pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
- bond->dev->name);
+ if (new_value) {
+ if (bond->params.miimon) {
+ pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+ bond->dev->name, bond->dev->name);
+ bond->params.miimon = 0;
+ }
+ if (!bond->params.arp_targets[0])
+ pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+ bond->dev->name);
}
if (bond->dev->flags & IFF_UP) {
/* If the interface is up, we may need to fire off
@@ -557,10 +558,13 @@ static ssize_t bonding_store_arp_interval(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- cancel_delayed_work_sync(&bond->mii_work);
- queue_delayed_work(bond->wq, &bond->arp_work, 0);
+ if (!new_value) {
+ cancel_delayed_work_sync(&bond->arp_work);
+ } else {
+ cancel_delayed_work_sync(&bond->mii_work);
+ queue_delayed_work(bond->wq, &bond->arp_work, 0);
+ }
}
-
out:
rtnl_unlock();
return ret;
@@ -702,7 +706,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
}
if (new_value < 0) {
pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
- bond->dev->name, new_value, 1, INT_MAX);
+ bond->dev->name, new_value, 0, INT_MAX);
ret = -EINVAL;
goto out;
} else {
@@ -757,8 +761,8 @@ static ssize_t bonding_store_updelay(struct device *d,
goto out;
}
if (new_value < 0) {
- pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
- bond->dev->name, new_value, 1, INT_MAX);
+ pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 0, INT_MAX);
ret = -EINVAL;
goto out;
} else {
@@ -968,37 +972,37 @@ static ssize_t bonding_store_miimon(struct device *d,
}
if (new_value < 0) {
pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
- bond->dev->name, new_value, 1, INT_MAX);
+ bond->dev->name, new_value, 0, INT_MAX);
ret = -EINVAL;
goto out;
- } else {
- pr_info("%s: Setting MII monitoring interval to %d.\n",
- bond->dev->name, new_value);
- bond->params.miimon = new_value;
- if (bond->params.updelay)
- pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
- bond->dev->name,
- bond->params.updelay * bond->params.miimon);
- if (bond->params.downdelay)
- pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
- bond->dev->name,
- bond->params.downdelay * bond->params.miimon);
- if (bond->params.arp_interval) {
- pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
- bond->dev->name);
- bond->params.arp_interval = 0;
- if (bond->params.arp_validate) {
- bond->params.arp_validate =
- BOND_ARP_VALIDATE_NONE;
- }
- }
-
- if (bond->dev->flags & IFF_UP) {
- /* If the interface is up, we may need to fire off
- * the MII timer. If the interface is down, the
- * timer will get fired off when the open function
- * is called.
- */
+ }
+ pr_info("%s: Setting MII monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.miimon = new_value;
+ if (bond->params.updelay)
+ pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.updelay * bond->params.miimon);
+ if (bond->params.downdelay)
+ pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.downdelay * bond->params.miimon);
+ if (new_value && bond->params.arp_interval) {
+ pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+ bond->dev->name);
+ bond->params.arp_interval = 0;
+ if (bond->params.arp_validate)
+ bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
+ }
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the MII timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (!new_value) {
+ cancel_delayed_work_sync(&bond->mii_work);
+ } else {
cancel_delayed_work_sync(&bond->arp_work);
queue_delayed_work(bond->wq, &bond->mii_work, 0);
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Masatake YAMATO <[email protected]>
commit f1e79e208076ffe7bad97158275f1c572c04f5c7 upstream.
Trigger BUG_ON if a group name is longer than GENL_NAMSIZ.
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/netlink/genetlink.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 2cc7c1e..4be473d 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -142,6 +142,7 @@ int genl_register_mc_group(struct genl_family *family,
int err = 0;
BUG_ON(grp->name[0] == '\0');
+ BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL);
genl_lock();
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang <[email protected]>
commit 4a7df340ed1bac190c124c1601bfc10cde9fb4fb upstream.
vlan_vid_del() could possibly free ->vlan_info after a RCU grace
period, however, we may still refer to the freed memory area
by 'grp' pointer. Found by code inspection.
This patch moves vlan_vid_del() as behind as possible.
Cc: Patrick McHardy <[email protected]>
Cc: "David S. Miller" <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Acked-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/8021q/vlan.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 9096bcb..8bdc56d 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -86,13 +86,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
grp = &vlan_info->grp;
- /* Take it out of our own structures, but be sure to interlock with
- * HW accelerating devices or SW vlan input packet processing if
- * VLAN is not 0 (leave it there for 802.1p).
- */
- if (vlan_id)
- vlan_vid_del(real_dev, vlan_id);
-
grp->nr_vlan_devs--;
if (vlan->flags & VLAN_FLAG_GVRP)
@@ -108,6 +101,13 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
if (grp->nr_vlan_devs == 0)
vlan_gvrp_uninit_applicant(real_dev);
+ /* Take it out of our own structures, but be sure to interlock with
+ * HW accelerating devices or SW vlan input packet processing if
+ * VLAN is not 0 (leave it there for 802.1p).
+ */
+ if (vlan_id)
+ vlan_vid_del(real_dev, vlan_id);
+
/* Get rid of the vlan's reference to real_dev */
dev_put(real_dev);
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Masatake YAMATO <[email protected]>
commit 73214f5d9f33b79918b1f7babddd5c8af28dd23d upstream.
The original name is too long.
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
include/linux/thermal.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 796f1ff..1662047 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -108,7 +108,7 @@ struct thermal_zone_device {
/* Adding event notification support elements */
#define THERMAL_GENL_FAMILY_NAME "thermal_event"
#define THERMAL_GENL_VERSION 0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group"
+#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp"
enum events {
THERMAL_AUX0,
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 9979a55a833883242e3a29f3596676edd7199c46 upstream.
The WARN_ON(in_interrupt()) in net_enable_timestamp() can get false
positive, in socket clone path, run from softirq context :
[ 3641.624425] WARNING: at net/core/dev.c:1532 net_enable_timestamp+0x7b/0x80()
[ 3641.668811] Call Trace:
[ 3641.671254] <IRQ> [<ffffffff80286817>] warn_slowpath_common+0x87/0xc0
[ 3641.677871] [<ffffffff8028686a>] warn_slowpath_null+0x1a/0x20
[ 3641.683683] [<ffffffff80742f8b>] net_enable_timestamp+0x7b/0x80
[ 3641.689668] [<ffffffff80732ce5>] sk_clone_lock+0x425/0x450
[ 3641.695222] [<ffffffff8078db36>] inet_csk_clone_lock+0x16/0x170
[ 3641.701213] [<ffffffff807ae449>] tcp_create_openreq_child+0x29/0x820
[ 3641.707663] [<ffffffff807d62e2>] ? ipt_do_table+0x222/0x670
[ 3641.713354] [<ffffffff807aaf5b>] tcp_v4_syn_recv_sock+0xab/0x3d0
[ 3641.719425] [<ffffffff807af63a>] tcp_check_req+0x3da/0x530
[ 3641.724979] [<ffffffff8078b400>] ? inet_hashinfo_init+0x60/0x80
[ 3641.730964] [<ffffffff807ade6f>] ? tcp_v4_rcv+0x79f/0xbe0
[ 3641.736430] [<ffffffff807ab9bd>] tcp_v4_do_rcv+0x38d/0x4f0
[ 3641.741985] [<ffffffff807ae14a>] tcp_v4_rcv+0xa7a/0xbe0
Its safe at this point because the parent socket owns a reference
on the netstamp_needed, so we cant have a 0 -> 1 transition, which
requires to lock a mutex.
Instead of refining the check, lets remove it, as all known callers
are safe. If it ever changes in the future, static_key_slow_inc()
will complain anyway.
Reported-by: Laurent Chavey <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/core/dev.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 097dd07..39aa9e6 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1481,7 +1481,6 @@ void net_enable_timestamp(void)
return;
}
#endif
- WARN_ON(in_interrupt());
static_key_slow_inc(&netstamp_needed);
}
EXPORT_SYMBOL(net_enable_timestamp);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuchung Cheng <[email protected]>
commit 7ebe183c6d444ef5587d803b64a1f4734b18c564 upstream.
On SACK reneging the sender immediately retransmits and forces a
timeout but disables Eifel (undo). If the (buggy) receiver does not
drop any packet this can trigger a false slow-start retransmit storm
driven by the ACKs of the original packets. This can be detected with
undo and TCP timestamps.
Signed-off-by: Yuchung Cheng <[email protected]>
Acked-by: Neal Cardwell <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/ipv4/tcp_input.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 410b7c4..e75e4fb 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2267,11 +2267,8 @@ void tcp_enter_loss(struct sock *sk, int how)
if (tcp_is_reno(tp))
tcp_reset_reno_sack(tp);
- if (!how) {
- /* Push undo marker, if it was plain RTO and nothing
- * was retransmitted. */
- tp->undo_marker = tp->snd_una;
- } else {
+ tp->undo_marker = tp->snd_una;
+ if (how) {
tp->sacked_out = 0;
tp->fackets_out = 0;
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Mirko Lindner <[email protected]>
commit 74f9f42c1c1650e74fb464f76644c9041f996851 upstream.
The sky2 driver sets the Rx Upper Threshold for Pause Packet generation to a
wrong value which leads to only 2kB of RAM remaining space. This can lead to
Rx overflow errors even with activated flow-control.
Fix: We should increase the value to 8192/8
Signed-off-by: Mirko Lindner <[email protected]>
Acked-by: Stephen Hemminger <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/marvell/sky2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 05c2cac..af158e8 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -1066,7 +1066,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space)
sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
- tp = space - 2048/8;
+ tp = space - 8192/8;
sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
} else {
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Mirko Lindner <[email protected]>
commit 9cfe8b156c21cf340b3a10ecb3022fbbc1c39185 upstream.
The sky2 driver doesn't count the Receive Overflows because the MAC
interrupt for this event is not set in the MAC's interrupt mask.
The MAC's interrupt mask is set only for Transmit FIFO Underruns.
Fix: The correct setting should be (GM_IS_TX_FF_UR | GM_IS_RX_FF_OR)
Otherwise the Receive Overflow event will not generate any interrupt.
The Receive Overflow interrupt is handled correctly
Signed-off-by: Mirko Lindner <[email protected]>
Acked-by: Stephen Hemminger <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/ethernet/marvell/sky2.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h
index 3c896ce..a0f229e 100644
--- a/drivers/net/ethernet/marvell/sky2.h
+++ b/drivers/net/ethernet/marvell/sky2.h
@@ -2069,7 +2069,7 @@ enum {
GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
-#define GMAC_DEF_MSK GM_IS_TX_FF_UR
+#define GMAC_DEF_MSK (GM_IS_TX_FF_UR | GM_IS_RX_FF_OR)
};
/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit 991f76f837bf22c5bb07261cfd86525a0a96650c upstream.
While readdir() is running, lseek() may set filp->f_pos as zero,
then may leave filp->private_data pointing to one sysfs_dirent
object without holding its reference counter, so the sysfs_dirent
object may be used after free in next readdir().
This patch holds inode->i_mutex to avoid the problem since
the lock is always held in readdir path.
Reported-by: Dave Jones <[email protected]>
Tested-by: Sasha Levin <[email protected]>
Cc: <[email protected]>
Signed-off-by: Ming Lei <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backported to 3.5: removed usage of file_inode() ]
Signed-off-by: Luis Henriques <[email protected]>
---
fs/sysfs/dir.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 2ee0864..8777436 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -1063,10 +1063,21 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
return 0;
}
+static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ loff_t ret;
+
+ mutex_lock(&inode->i_mutex);
+ ret = generic_file_llseek(file, offset, whence);
+ mutex_unlock(&inode->i_mutex);
+
+ return ret;
+}
const struct file_operations sysfs_dir_operations = {
.read = generic_read_dir,
.readdir = sysfs_readdir,
.release = sysfs_dir_release,
- .llseek = generic_file_llseek,
+ .llseek = sysfs_dir_llseek,
};
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Bing Zhao <[email protected]>
commit 084c7189acb3f969c855536166042e27f5dd703f upstream.
curr_cmd points to the command that is in processing or waiting
for its command response from firmware. If the function shutdown
happens to occur at this time we should cancel the cmd timer and
put the command back to free queue.
Tested-by: Marco Cesarano <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/mwifiex/init.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index c1cb004..0346cc2 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -591,6 +591,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
return ret;
}
+ /* cancel current command */
+ if (adapter->curr_cmd) {
+ dev_warn(adapter->dev, "curr_cmd is still in processing\n");
+ del_timer(&adapter->cmd_timer);
+ mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
+ adapter->curr_cmd = NULL;
+ }
+
/* shut down mwifiex */
dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Kosina <[email protected]>
commit 570637dc8eeb2faba06228d497ff40bb019bcc93 upstream.
Fix build problem caused by typo introduced by 620ae90ed8
("HID: usbhid: quirk for MSI GX680R led panel").
Reported-by: [email protected]
Signed-off-by: Jiri Kosina <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/hid/usbhid/hid-quirks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index e11d186..0401e3f 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -73,7 +73,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
- { USB_VENDIR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 8edfdab37157d2683e51b8be5d3d5697f66a9f7b upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backported to 3.5; adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/oti6858.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 5976b65..d9c40b1 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -191,7 +191,6 @@ struct oti6858_private {
u8 setup_done;
struct delayed_work delayed_setup_work;
- wait_queue_head_t intr_wait;
struct usb_serial_port *port; /* USB port with which associated */
};
@@ -345,7 +344,6 @@ static int oti6858_startup(struct usb_serial *serial)
break;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->intr_wait);
/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
priv->port = port;
@@ -672,11 +670,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- wait_event_interruptible(priv->intr_wait,
+ wait_event_interruptible(port->delta_msr_wait,
+ port->serial->disconnected ||
priv->status.pin_state != prev);
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->status.pin_state & PIN_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -783,7 +785,7 @@ static void oti6858_read_int_callback(struct urb *urb)
if (!priv->transient) {
if (xs->pin_state != priv->status.pin_state)
- wake_up_interruptible(&priv->intr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Vinicius Costa Gomes <[email protected]>
commit eb20ff9c91ddcb2d55c1849a87d3db85af5e88a9 upstream.
With deferred setup for SCO, it is possible that userspace closes the
socket when it is in the BT_CONNECT2 state, after the Connect Request is
received but before the Accept Synchonous Connection is sent.
If this happens the following crash was observed, when the connection is
terminated:
[ +0.000003] hci_sync_conn_complete_evt: hci0 status 0x10
[ +0.000005] sco_connect_cfm: hcon ffff88003d1bd800 bdaddr 40:98:4e:32:d7:39 status 16
[ +0.000003] sco_conn_del: hcon ffff88003d1bd800 conn ffff88003cc8e300, err 110
[ +0.000015] BUG: unable to handle kernel NULL pointer dereference at 0000000000000199
[ +0.000906] IP: [<ffffffff810620dd>] __lock_acquire+0xed/0xe82
[ +0.000000] PGD 3d21f067 PUD 3d291067 PMD 0
[ +0.000000] Oops: 0002 [#1] SMP
[ +0.000000] Modules linked in: rfcomm bnep btusb bluetooth
[ +0.000000] CPU 0
[ +0.000000] Pid: 1481, comm: kworker/u:2H Not tainted 3.9.0-rc1-25019-gad82cdd #1 Bochs Bochs
[ +0.000000] RIP: 0010:[<ffffffff810620dd>] [<ffffffff810620dd>] __lock_acquire+0xed/0xe82
[ +0.000000] RSP: 0018:ffff88003c3c19d8 EFLAGS: 00010002
[ +0.000000] RAX: 0000000000000001 RBX: 0000000000000246 RCX: 0000000000000000
[ +0.000000] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88003d1be868
[ +0.000000] RBP: ffff88003c3c1a98 R08: 0000000000000002 R09: 0000000000000000
[ +0.000000] R10: ffff88003d1be868 R11: ffff88003e20b000 R12: 0000000000000002
[ +0.000000] R13: ffff88003aaa8000 R14: 000000000000006e R15: ffff88003d1be850
[ +0.000000] FS: 0000000000000000(0000) GS:ffff88003e200000(0000) knlGS:0000000000000000
[ +0.000000] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ +0.000000] CR2: 0000000000000199 CR3: 000000003c1cb000 CR4: 00000000000006b0
[ +0.000000] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ +0.000000] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ +0.000000] Process kworker/u:2H (pid: 1481, threadinfo ffff88003c3c0000, task ffff88003aaa8000)
[ +0.000000] Stack:
[ +0.000000] ffffffff81b16342 0000000000000000 0000000000000000 ffff88003d1be868
[ +0.000000] ffffffff00000000 00018c0c7863e367 000000003c3c1a28 ffffffff8101efbd
[ +0.000000] 0000000000000000 ffff88003e3d2400 ffff88003c3c1a38 ffffffff81007c7a
[ +0.000000] Call Trace:
[ +0.000000] [<ffffffff8101efbd>] ? kvm_clock_read+0x34/0x3b
[ +0.000000] [<ffffffff81007c7a>] ? paravirt_sched_clock+0x9/0xd
[ +0.000000] [<ffffffff81007fd4>] ? sched_clock+0x9/0xb
[ +0.000000] [<ffffffff8104fd7a>] ? sched_clock_local+0x12/0x75
[ +0.000000] [<ffffffff810632d1>] lock_acquire+0x93/0xb1
[ +0.000000] [<ffffffffa0022339>] ? spin_lock+0x9/0xb [bluetooth]
[ +0.000000] [<ffffffff8105f3d8>] ? lock_release_holdtime.part.22+0x4e/0x55
[ +0.000000] [<ffffffff814f6038>] _raw_spin_lock+0x40/0x74
[ +0.000000] [<ffffffffa0022339>] ? spin_lock+0x9/0xb [bluetooth]
[ +0.000000] [<ffffffff814f6936>] ? _raw_spin_unlock+0x23/0x36
[ +0.000000] [<ffffffffa0022339>] spin_lock+0x9/0xb [bluetooth]
[ +0.000000] [<ffffffffa00230cc>] sco_conn_del+0x76/0xbb [bluetooth]
[ +0.000000] [<ffffffffa002391d>] sco_connect_cfm+0x2da/0x2e9 [bluetooth]
[ +0.000000] [<ffffffffa000862a>] hci_proto_connect_cfm+0x38/0x65 [bluetooth]
[ +0.000000] [<ffffffffa0008d30>] hci_sync_conn_complete_evt.isra.79+0x11a/0x13e [bluetooth]
[ +0.000000] [<ffffffffa000cd96>] hci_event_packet+0x153b/0x239d [bluetooth]
[ +0.000000] [<ffffffff814f68ff>] ? _raw_spin_unlock_irqrestore+0x48/0x5c
[ +0.000000] [<ffffffffa00025f6>] hci_rx_work+0xf3/0x2e3 [bluetooth]
[ +0.000000] [<ffffffff8103efed>] process_one_work+0x1dc/0x30b
[ +0.000000] [<ffffffff8103ef83>] ? process_one_work+0x172/0x30b
[ +0.000000] [<ffffffff8103e07f>] ? spin_lock_irq+0x9/0xb
[ +0.000000] [<ffffffff8103fc8d>] worker_thread+0x123/0x1d2
[ +0.000000] [<ffffffff8103fb6a>] ? manage_workers+0x240/0x240
[ +0.000000] [<ffffffff81044211>] kthread+0x9d/0xa5
[ +0.000000] [<ffffffff81044174>] ? __kthread_parkme+0x60/0x60
[ +0.000000] [<ffffffff814f75bc>] ret_from_fork+0x7c/0xb0
[ +0.000000] [<ffffffff81044174>] ? __kthread_parkme+0x60/0x60
[ +0.000000] Code: d7 44 89 8d 50 ff ff ff 4c 89 95 58 ff ff ff e8 44 fc ff ff 44 8b 8d 50 ff ff ff 48 85 c0 4c 8b 95 58 ff ff ff 0f 84 7a 04 00 00 <f0> ff 80 98 01 00 00 83 3d 25 41 a7 00 00 45 8b b5 e8 05 00 00
[ +0.000000] RIP [<ffffffff810620dd>] __lock_acquire+0xed/0xe82
[ +0.000000] RSP <ffff88003c3c19d8>
[ +0.000000] CR2: 0000000000000199
[ +0.000000] ---[ end trace e73cd3b52352dd34 ]---
Signed-off-by: Vinicius Costa Gomes <[email protected]>
Tested-by: Frederic Dalleau <[email protected]>
Signed-off-by: Gustavo Padovan <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/bluetooth/sco.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index cbdd313..87b8ee9 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -378,6 +378,7 @@ static void __sco_sock_close(struct sock *sk)
sco_chan_del(sk, ECONNRESET);
break;
+ case BT_CONNECT2:
case BT_CONNECT:
case BT_DISCONN:
sco_chan_del(sk, ECONNRESET);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit fc98ab873aa3dbe783ce56a2ffdbbe7c7609521a upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backported to 3.5; adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/ti_usb_3410_5052.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index a4404f5..d9f43247 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -75,7 +75,6 @@ struct ti_port {
int tp_flags;
int tp_closing_wait;/* in .01 secs */
struct async_icount tp_icount;
- wait_queue_head_t tp_msr_wait; /* wait for msr change */
wait_queue_head_t tp_write_wait;
struct ti_device *tp_tdev;
struct usb_serial_port *tp_port;
@@ -421,7 +420,6 @@ static int ti_startup(struct usb_serial *serial)
tport->tp_uart_base_addr = (i == 0 ?
TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
tport->tp_closing_wait = closing_wait;
- init_waitqueue_head(&tport->tp_msr_wait);
init_waitqueue_head(&tport->tp_write_wait);
if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
GFP_KERNEL)) {
@@ -800,9 +798,13 @@ static int ti_ioctl(struct tty_struct *tty,
dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
cprev = tport->tp_icount;
while (1) {
- interruptible_sleep_on(&tport->tp_msr_wait);
+ interruptible_sleep_on(&port->delta_msr_wait);
if (signal_pending(current))
return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
cnow = tport->tp_icount;
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -1414,7 +1416,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
icount->dcd++;
if (msr & TI_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&tport->tp_msr_wait);
+ wake_up_interruptible(&tport->tp_port->delta_msr_wait);
spin_unlock_irqrestore(&tport->tp_lock, flags);
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit 9bf7a4890518186238d2579be16ecc5190a707c0 upstream.
We need to inc the nlink of deleted entries when running replay so we can do the
unlink on the fs_root and get everything cleaned up and then have the orphan
cleanup do the right thing. The problem is inc_nlink complains about this, even
thought it still does the right thing. So use set_nlink() if our i_nlink is 0
to keep users from seeing the warnings during log replay. Thanks,
Signed-off-by: Josef Bacik <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
fs/btrfs/tree-log.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 8abeae4..aad8644 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1132,7 +1132,10 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans,
btrfs_release_path(path);
if (ret == 0) {
- btrfs_inc_nlink(inode);
+ if (!inode->i_nlink)
+ set_nlink(inode, 1);
+ else
+ btrfs_inc_nlink(inode);
btrfs_update_inode(trans, root, inode);
} else if (ret == -EEXIST) {
ret = 0;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 43a66b4c417ad15f6d2f632ce67ad195bdf999e8 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backported to 3.5; adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/ssu100.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index c4409b1..3ad10b5 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -65,7 +65,6 @@ struct ssu100_port_private {
spinlock_t status_lock;
u8 shadowLSR;
u8 shadowMSR;
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
struct async_icount icount;
};
@@ -366,8 +365,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->status_lock, flags);
while (1) {
- wait_event_interruptible(priv->delta_msr_wait,
- ((priv->icount.rng != prev.rng) ||
+ wait_event_interruptible(port->delta_msr_wait,
+ (port->serial->disconnected ||
+ (priv->icount.rng != prev.rng) ||
(priv->icount.dsr != prev.dsr) ||
(priv->icount.dcd != prev.dcd) ||
(priv->icount.cts != prev.cts)));
@@ -375,6 +375,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->status_lock, flags);
cur = priv->icount;
spin_unlock_irqrestore(&priv->status_lock, flags);
@@ -455,7 +458,6 @@ static int ssu100_attach(struct usb_serial *serial)
}
spin_lock_init(&priv->status_lock);
- init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(port, priv);
return ssu100_initdevice(serial->dev);
@@ -536,7 +538,7 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
priv->icount.dcd++;
if (msr & UART_MSR_TERI)
priv->icount.rng++;
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
}
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 40509ca982c00c4b70fc00be887509feca0bff15 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backported to 3.5; adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/pl2303.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 13b8dd6..6fe8d0e 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -137,7 +137,6 @@ enum pl2303_type {
struct pl2303_private {
spinlock_t lock;
- wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
enum pl2303_type type;
@@ -193,7 +192,6 @@ static int pl2303_startup(struct usb_serial *serial)
if (!priv)
goto cleanup;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
priv->type = type;
usb_set_serial_port_data(serial->port[i], priv);
}
@@ -582,11 +580,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -705,7 +706,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->line_status & UART_BREAK_ERROR)
usb_serial_handle_break(port);
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
tty = tty_port_tty_get(&port->port);
if (!tty)
@@ -770,7 +771,7 @@ static void pl2303_process_read_urb(struct urb *urb)
line_status = priv->line_status;
priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
if (!urb->actual_length)
return;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit dbcea7615d8d7d58f6ff49d2c5568113f70effe9 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backported to 3.5; adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/spcp8x5.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index cad6089..66a4871 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -154,7 +154,6 @@ enum spcp8x5_type {
struct spcp8x5_private {
spinlock_t lock;
enum spcp8x5_type type;
- wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
};
@@ -188,7 +187,6 @@ static int spcp8x5_startup(struct usb_serial *serial)
goto cleanup;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
priv->type = type;
usb_set_serial_port_data(serial->port[i] , priv);
}
@@ -491,7 +489,7 @@ static void spcp8x5_process_read_urb(struct urb *urb)
priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
/* wake up the wait for termios */
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
if (!urb->actual_length)
return;
@@ -541,12 +539,15 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
while (1) {
/* wake up in bulk read */
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit a14430db686b8e459e1cf070a6ecf391515c9ab9 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/mos7840.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index be5f09b..2727955 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -224,7 +224,6 @@ struct moschip_port {
char open;
char open_ports;
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
int delta_msr_cond;
struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
@@ -444,7 +443,7 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
}
mos7840_port->delta_msr_cond = 1;
- wake_up_interruptible(&mos7840_port->delta_msr_wait);
+ wake_up_interruptible(&port->port->delta_msr_wait);
}
}
@@ -1166,7 +1165,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
/* initialize our wait queues */
init_waitqueue_head(&mos7840_port->wait_chase);
- init_waitqueue_head(&mos7840_port->delta_msr_wait);
/* initialize our icount structure */
memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
@@ -2307,13 +2305,18 @@ static int mos7840_ioctl(struct tty_struct *tty,
while (1) {
/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
mos7840_port->delta_msr_cond = 0;
- wait_event_interruptible(mos7840_port->delta_msr_wait,
- (mos7840_port->
+ wait_event_interruptible(port->delta_msr_wait,
+ (port->serial->disconnected ||
+ mos7840_port->
delta_msr_cond == 1));
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
cnow = mos7840_port->icount;
smp_rmb();
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 508f940f1407656076a2e7d8f7fa059b567ecac2 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: backport to 3.5; adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/f81232.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 499b15f..ea88b47 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -49,7 +49,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
struct f81232_private {
spinlock_t lock;
- wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
};
@@ -114,7 +113,7 @@ static void f81232_process_read_urb(struct urb *urb)
line_status = priv->line_status;
priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
if (!urb->actual_length)
return;
@@ -262,11 +261,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (1) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -329,7 +331,6 @@ static int f81232_startup(struct usb_serial *serial)
if (!priv)
goto cleanup;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
usb_set_serial_port_data(serial->port[i], priv);
}
return 0;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit cf1d24443677a0758cfa88ca40f24858b89261c0 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/mct_u232.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 66b91d5..5f005cc 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -118,8 +118,6 @@ struct mct_u232_private {
unsigned char last_msr; /* Modem Status Register */
unsigned int rx_flags; /* Throttling flags */
struct async_icount icount;
- wait_queue_head_t msr_wait; /* for handling sleeping while waiting
- for msr change to happen */
};
#define THROTTLED 0x01
@@ -399,7 +397,6 @@ static int mct_u232_startup(struct usb_serial *serial)
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->msr_wait);
usb_set_serial_port_data(serial->port[0], priv);
init_waitqueue_head(&serial->port[0]->write_wait);
@@ -416,7 +413,6 @@ static int mct_u232_startup(struct usb_serial *serial)
return 0;
} /* mct_u232_startup */
-
static void mct_u232_release(struct usb_serial *serial)
{
struct mct_u232_private *priv;
@@ -616,7 +612,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
tty_kref_put(tty);
}
#endif
- wake_up_interruptible(&priv->msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
spin_unlock_irqrestore(&priv->lock, flags);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -827,13 +823,17 @@ static int mct_u232_ioctl(struct tty_struct *tty,
cprev = mct_u232_port->icount;
spin_unlock_irqrestore(&mct_u232_port->lock, flags);
for ( ; ; ) {
- prepare_to_wait(&mct_u232_port->msr_wait,
+ prepare_to_wait(&port->delta_msr_wait,
&wait, TASK_INTERRUPTIBLE);
schedule();
- finish_wait(&mct_u232_port->msr_wait, &wait);
+ finish_wait(&port->delta_msr_wait, &wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&mct_u232_port->lock, flags);
cnow = mct_u232_port->icount;
spin_unlock_irqrestore(&mct_u232_port->lock, flags);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 7b2459690584f239650a365f3411ba2ec1c6d1e0 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/io_ti.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index d81630d..b08bb9c 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -91,9 +91,6 @@ struct edgeport_port {
int close_pending;
int lsr_event;
struct async_icount icount;
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while
- waiting for msr change to
- happen */
struct edgeport_serial *edge_serial;
struct usb_serial_port *port;
__u8 bUartMode; /* Port type, 0: RS232, etc. */
@@ -1542,7 +1539,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
icount->dcd++;
if (msr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&edge_port->delta_msr_wait);
+ wake_up_interruptible(&edge_port->port->delta_msr_wait);
}
/* Save the new modem status */
@@ -1860,7 +1857,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
dev = port->serial->dev;
memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
- init_waitqueue_head(&edge_port->delta_msr_wait);
/* turn off loopback */
status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
@@ -2552,10 +2548,14 @@ static int edge_ioctl(struct tty_struct *tty,
dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
cprev = edge_port->icount;
while (1) {
- interruptible_sleep_on(&edge_port->delta_msr_wait);
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
cnow = edge_port->icount;
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 356050d8b1e526db093e9d2c78daf49d6bf418e3 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Also remove bogus test for private data pointer being NULL as it is
never assigned in the loop.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/cypress_m8.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index b78c34e..dec5b2f 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -116,7 +116,6 @@ struct cypress_private {
int baud_rate; /* stores current baud rate in
integer form */
int isthrottled; /* if throttled, discard reads */
- wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
char prev_status, diff_status; /* used for TIOCMIWAIT */
/* we pass a pointer to this as the argument sent to
cypress_set_termios old_termios */
@@ -452,7 +451,6 @@ static int generic_startup(struct usb_serial *serial)
kfree(priv);
return -ENOMEM;
}
- init_waitqueue_head(&priv->delta_msr_wait);
usb_reset_configuration(serial->dev);
@@ -872,12 +870,16 @@ static int cypress_ioctl(struct tty_struct *tty,
switch (cmd) {
/* This code comes from drivers/char/serial.c and ftdi_sio.c */
case TIOCMIWAIT:
- while (priv != NULL) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ for (;;) {
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
- else {
+
+ if (port->serial->disconnected)
+ return -EIO;
+
+ {
char diff = priv->diff_status;
if (diff == 0)
return -EIO; /* no change => error */
@@ -1193,7 +1195,7 @@ static void cypress_read_int_callback(struct urb *urb)
if (priv->current_status != priv->prev_status) {
priv->diff_status |= priv->current_status ^
priv->prev_status;
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
priv->prev_status = priv->current_status;
}
spin_unlock_irqrestore(&priv->lock, flags);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 333576255d4cfc53efd056aad438568184b36af6 upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/io_edgeport.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index e1f5ccd..457743a 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -114,7 +114,6 @@ struct edgeport_port {
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */
wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */
- wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
struct async_icount icount;
struct usb_serial_port *port; /* loop back to the owner of this object */
@@ -884,7 +883,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
/* initialize our wait queues */
init_waitqueue_head(&edge_port->wait_open);
init_waitqueue_head(&edge_port->wait_chase);
- init_waitqueue_head(&edge_port->delta_msr_wait);
init_waitqueue_head(&edge_port->wait_command);
/* initialize our icount structure */
@@ -1701,13 +1699,17 @@ static int edge_ioctl(struct tty_struct *tty,
dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
cprev = edge_port->icount;
while (1) {
- prepare_to_wait(&edge_port->delta_msr_wait,
+ prepare_to_wait(&port->delta_msr_wait,
&wait, TASK_INTERRUPTIBLE);
schedule();
- finish_wait(&edge_port->delta_msr_wait, &wait);
+ finish_wait(&port->delta_msr_wait, &wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
cnow = edge_port->icount;
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -2088,7 +2090,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
icount->dcd++;
if (newMsr & EDGEPORT_MSR_DELTA_RI)
icount->rng++;
- wake_up_interruptible(&edge_port->delta_msr_wait);
+ wake_up_interruptible(&edge_port->port->delta_msr_wait);
}
/* Save the new modem status */
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 71ccb9b01981fabae27d3c98260ea4613207618e upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
When switching to tty ports, some lifetime assumptions were changed.
Specifically, close can now be called before the final tty reference is
dropped as part of hangup at device disconnect. Even with the ftdi
private-data refcounting this means that the port private data can be
freed while a process is sleeping on modem-status changes and thus
cannot be relied on to detect disconnects when woken up.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/ftdi_sio.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index cddca7f..a93f958 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -74,9 +74,7 @@ struct ftdi_private {
int flags; /* some ASYNC_xxxx flags are supported */
unsigned long last_dtr_rts; /* saved modem control outputs */
struct async_icount icount;
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
char prev_status; /* Used for TIOCMIWAIT */
- bool dev_gone; /* Used to abort TIOCMIWAIT */
char transmit_empty; /* If transmitter is empty or not */
struct usb_serial_port *port;
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
@@ -1695,10 +1693,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
kref_init(&priv->kref);
mutex_init(&priv->cfg_lock);
memset(&priv->icount, 0x00, sizeof(priv->icount));
- init_waitqueue_head(&priv->delta_msr_wait);
priv->flags = ASYNC_LOW_LATENCY;
- priv->dev_gone = false;
if (quirk && quirk->port_probe)
quirk->port_probe(priv);
@@ -1845,8 +1841,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
- priv->dev_gone = true;
- wake_up_interruptible_all(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
remove_sysfs_attrs(port);
@@ -1995,7 +1990,7 @@ static int ftdi_process_packet(struct tty_struct *tty,
if (diff_status & FTDI_RS0_RLSD)
priv->icount.dcd++;
- wake_up_interruptible_all(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
priv->prev_status = status;
}
@@ -2394,11 +2389,15 @@ static int ftdi_ioctl(struct tty_struct *tty,
*/
case TIOCMIWAIT:
cprev = priv->icount;
- while (!priv->dev_gone) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ for (;;) {
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+
+ if (port->serial->disconnected)
+ return -EIO;
+
cnow = priv->icount;
if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
@@ -2408,8 +2407,6 @@ static int ftdi_ioctl(struct tty_struct *tty,
}
cprev = cnow;
}
- return -EIO;
- break;
case TIOCSERGETLSR:
return get_lsr_info(port, (struct serial_struct __user *)arg);
break;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit fa1e11d5231c001c80a479160b5832933c5d35fb upstream.
Use the port wait queue and make sure to check the serial disconnected
flag before accessing private port data after waking up.
This is is needed as the private port data (including the wait queue
itself) can be gone when waking up after a disconnect.
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/ch341.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index cabd1b1..93c835e 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -82,7 +82,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
struct ch341_private {
spinlock_t lock; /* access lock */
- wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
unsigned baud_rate; /* set baud rate */
u8 line_control; /* set line control value RTS/DTR */
u8 line_status; /* active status of modem control inputs */
@@ -253,7 +252,6 @@ static int ch341_attach(struct usb_serial *serial)
return -ENOMEM;
spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
@@ -289,7 +287,7 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_handshake(port->serial->dev, priv->line_control);
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
}
static void ch341_close(struct usb_serial_port *port)
@@ -482,7 +480,7 @@ static void ch341_read_int_callback(struct urb *urb)
tty_kref_put(tty);
}
- wake_up_interruptible(&priv->delta_msr_wait);
+ wake_up_interruptible(&port->delta_msr_wait);
}
exit:
@@ -508,11 +506,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
spin_unlock_irqrestore(&priv->lock, flags);
while (!multi_change) {
- interruptible_sleep_on(&priv->delta_msr_wait);
+ interruptible_sleep_on(&port->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
+ if (port->serial->disconnected)
+ return -EIO;
+
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
multi_change = priv->multi_status_change;
--
1.8.1.2
On Mon, Apr 08, 2013 at 12:01:57PM +0200, Johan Hovold wrote:
> On Mon, Apr 08, 2013 at 10:49:50AM +0100, Luis Henriques wrote:
> > 3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
> >
> > ------------------
> >
> > From: Johan Hovold <[email protected]>
> >
> > commit e5b33dc9d16053c2ae4c2c669cf008829530364b upstream.
> >
> > Add modem-status-change wait queue to struct usb_serial_port that
> > subdrivers can use to implement TIOCMIWAIT.
> >
> > Currently subdrivers use a private wait queue which may have been
> > released when waking up after device disconnected.
> >
> > Note that we're adding a new wait queue rather than reusing the tty-port
> > one as we do not want to get woken up at hangup (yet).
>
> This one should be followed by eba0e3c3a0ba7b96f0 (USB: serial: fix hang
> when opening port) which adds the missing queue initialisation. It
> appears the next patch in your series starts using the wait queue
> directly.
Right, I see what you mean. Not sure how this happen, but obviously the
ordering doesn't make sense. I'll fix this. Thanks for your (really
quick!) feedback.
Cheers,
--
Luis
>
> Thanks, Johan
>
> > Signed-off-by: Johan Hovold <[email protected]>
> > Signed-off-by: Greg Kroah-Hartman <[email protected]>
> > Signed-off-by: Luis Henriques <[email protected]>
> > ---
> > include/linux/usb/serial.h | 2 ++
> > 1 file changed, 2 insertions(+)
> >
> > diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
> > index 86c0b45..0b61f01 100644
> > --- a/include/linux/usb/serial.h
> > +++ b/include/linux/usb/serial.h
> > @@ -66,6 +66,7 @@
> > * port.
> > * @flags: usb serial port flags
> > * @write_wait: a wait_queue_head_t used by the port.
> > + * @delta_msr_wait: modem-status-change wait queue
> > * @work: work queue entry for the line discipline waking up.
> > * @throttled: nonzero if the read urb is inactive to throttle the device
> > * @throttle_req: nonzero if the tty wants to throttle us
> > @@ -112,6 +113,7 @@ struct usb_serial_port {
> >
> > unsigned long flags;
> > wait_queue_head_t write_wait;
> > + wait_queue_head_t delta_msr_wait;
> > struct work_struct work;
> > char throttled;
> > char throttle_req;
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit e5b33dc9d16053c2ae4c2c669cf008829530364b upstream.
Add modem-status-change wait queue to struct usb_serial_port that
subdrivers can use to implement TIOCMIWAIT.
Currently subdrivers use a private wait queue which may have been
released when waking up after device disconnected.
Note that we're adding a new wait queue rather than reusing the tty-port
one as we do not want to get woken up at hangup (yet).
Signed-off-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
include/linux/usb/serial.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 86c0b45..0b61f01 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -66,6 +66,7 @@
* port.
* @flags: usb serial port flags
* @write_wait: a wait_queue_head_t used by the port.
+ * @delta_msr_wait: modem-status-change wait queue
* @work: work queue entry for the line discipline waking up.
* @throttled: nonzero if the read urb is inactive to throttle the device
* @throttle_req: nonzero if the tty wants to throttle us
@@ -112,6 +113,7 @@ struct usb_serial_port {
unsigned long flags;
wait_queue_head_t write_wait;
+ wait_queue_head_t delta_msr_wait;
struct work_struct work;
char throttled;
char throttle_req;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit eba0e3c3a0ba7b96f01cbe997680f6a4401a0bfc upstream.
Johan's 'fix use-after-free in TIOCMIWAIT' patchset[1] introduces
one bug which can cause kernel hang when opening port.
This patch initialized the 'port->delta_msr_wait' waitqueue head
to fix the bug which is introduced in 3.9-rc4.
[1], http://marc.info/?l=linux-usb&m=136368139627876&w=2
Signed-off-by: Ming Lei <[email protected]>
Acked-by: Johan Hovold <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/usb-serial.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 2418551..fb09885 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -899,6 +899,7 @@ static int usb_serial_probe(struct usb_interface *interface,
port->port.ops = &serial_port_ops;
port->serial = serial;
spin_lock_init(&port->lock);
+ init_waitqueue_head(&port->delta_msr_wait);
/* Keep this for private driver use for the moment but
should probably go away */
INIT_WORK(&port->work, usb_serial_port_work);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Holoborodko <[email protected]>
commit 482b0b5d82bd916cc0c55a2abf65bdc69023b843 upstream.
It enhances the driver for FTDI-based USB serial adapters
to recognize Mitsubishi Electric Corp. USB/RS422 Converters
as FT232BM chips and support them.
https://search.meau.com/?q=FX-USB-AW
Signed-off-by: Konstantin Holoborodko <[email protected]>
Tested-by: Konstantin Holoborodko <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/serial/ftdi_sio.c | 1 +
drivers/usb/serial/ftdi_sio_ids.h | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 1f939cb..cddca7f 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -648,6 +648,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
+ { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 9d359e18..e79861e 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -584,6 +584,13 @@
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/*
+ * Mitsubishi Electric Corp. (http://www.meau.com)
+ * Submitted by Konstantin Holoborodko
+ */
+#define MITSUBISHI_VID 0x06D3
+#define MITSUBISHI_FXUSB_PID 0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */
+
+/*
* Definitions for B&B Electronics products.
*/
#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Vivek Gautam <[email protected]>
commit 1c11a172cb30492f5f6a82c6e118fdcd9946c34f upstream.
Use proper macro while extracting TRB transfer length from
Transfer event TRBs. Adding a macro EVENT_TRB_LEN (bits 0:23)
for the same, and use it instead of TRB_LEN (bits 0:16) in
case of event TRBs.
This patch should be backported to kernels as old as 2.6.31, that
contain the commit b10de142119a676552df3f0d2e3a9d647036c26a "USB: xhci:
Bulk transfer support". This patch will have issues applying to older
kernels.
Signed-off-by: Vivek gautam <[email protected]>
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/usb/host/xhci-ring.c | 24 ++++++++++++------------
drivers/usb/host/xhci.h | 4 ++++
2 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 6f3043f..848d0bc 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2027,8 +2027,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
if (event_trb != ep_ring->dequeue &&
event_trb != td->last_trb)
td->urb->actual_length =
- td->urb->transfer_buffer_length
- - TRB_LEN(le32_to_cpu(event->transfer_len));
+ td->urb->transfer_buffer_length -
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
else
td->urb->actual_length = 0;
@@ -2060,7 +2060,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* Maybe the event was for the data stage? */
td->urb->actual_length =
td->urb->transfer_buffer_length -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
xhci_dbg(xhci, "Waiting for status "
"stage event\n");
return 0;
@@ -2096,7 +2096,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* handle completion code */
switch (trb_comp_code) {
case COMP_SUCCESS:
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
frame->status = 0;
break;
}
@@ -2141,7 +2141,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
}
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
if (trb_comp_code != COMP_STOP_INVAL) {
frame->actual_length = len;
@@ -2199,7 +2199,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
case COMP_SUCCESS:
/* Double check that the HW transferred everything. */
if (event_trb != td->last_trb ||
- TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
xhci_warn(xhci, "WARN Successful completion "
"on short TX\n");
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
@@ -2227,18 +2227,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
"%d bytes untransferred\n",
td->urb->ep->desc.bEndpointAddress,
td->urb->transfer_buffer_length,
- TRB_LEN(le32_to_cpu(event->transfer_len)));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
/* Fast path - was this the last TRB in the TD for this URB? */
if (event_trb == td->last_trb) {
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length =
td->urb->transfer_buffer_length -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
if (td->urb->transfer_buffer_length <
td->urb->actual_length) {
xhci_warn(xhci, "HC gave bad length "
"of %d bytes left\n",
- TRB_LEN(le32_to_cpu(event->transfer_len)));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
td->urb->actual_length = 0;
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
*status = -EREMOTEIO;
@@ -2280,7 +2280,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
if (trb_comp_code != COMP_STOP_INVAL)
td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
- TRB_LEN(le32_to_cpu(event->transfer_len));
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
}
return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2366,7 +2366,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* transfer type
*/
case COMP_SUCCESS:
- if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
break;
if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
trb_comp_code = COMP_SHORT_TX;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b35bbbe..3e8bf2d 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -972,6 +972,10 @@ struct xhci_transfer_event {
__le32 flags;
};
+/* Transfer event TRB length bit mask */
+/* bits 0:23 */
+#define EVENT_TRB_LEN(p) ((p) & 0xffffff)
+
/** Transfer Event bit fields **/
#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f)
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit fdf30d1c1b386e1b73116cc7e0fb14e962b763b0 upstream.
A user reported a problem where he was getting early ENOSPC with hundreds of
gigs of free data space and 6 gigs of free metadata space. This is because the
global block reserve was taking up the entire free metadata space. This is
ridiculous, we have infrastructure in place to throttle if we start using too
much of the global reserve, so instead of letting it get this huge just limit it
to 512mb so that users can still get work done. This allowed the user to
complete his rsync without issues. Thanks
Reported-and-tested-by: Stefan Priebe <[email protected]>
Signed-off-by: Josef Bacik <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/btrfs/extent-tree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index fe6cec5..9e99ea0 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4218,7 +4218,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
spin_lock(&sinfo->lock);
spin_lock(&block_rsv->lock);
- block_rsv->size = num_bytes;
+ block_rsv->size = min_t(u64, num_bytes, 512 * 1024 * 1024);
num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
sinfo->bytes_reserved + sinfo->bytes_readonly +
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Abbott <[email protected]>
commit e4317ce877a31dbb9d96375391c1c4ad2210d637 upstream.
For the s626 driver, there is a bug in the handling of asynchronous
commands on the AI subdevice when the stop source is `TRIG_NONE`. The
command should run continuously until cancelled, but the interrupt
handler stops the command running after the first scan.
The command set-up function `s626_ai_cmd()` contains this code:
switch (cmd->stop_src) {
case TRIG_COUNT:
/* data arrives as one packet */
devpriv->ai_sample_count = cmd->stop_arg;
devpriv->ai_continous = 0;
break;
case TRIG_NONE:
/* continous acquisition */
devpriv->ai_continous = 1;
devpriv->ai_sample_count = 0;
break;
}
The interrupt handler `s626_irq_handler()` contains this code:
if (!(devpriv->ai_continous))
devpriv->ai_sample_count--;
if (devpriv->ai_sample_count <= 0) {
devpriv->ai_cmd_running = 0;
/* ... */
}
So `devpriv->ai_sample_count` is only decremented for the `TRIG_COUNT`
case, but `devpriv->ai_cmd_running` is set to 0 (and the command
stopped) regardless.
Fix this in `s626_ai_cmd()` by setting `devpriv->ai_sample_count = 1`
for the `TRIG_NONE` case. The interrupt handler will not decrement it
so it will remain greater than 0 and the check for stopping the
acquisition will fail.
Signed-off-by: Ian Abbott <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/staging/comedi/drivers/s626.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index e68e474..9c6b758 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -1823,7 +1823,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
case TRIG_NONE:
/* continous acquisition */
devpriv->ai_continous = 1;
- devpriv->ai_sample_count = 0;
+ devpriv->ai_sample_count = 1;
break;
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Josef Bacik <[email protected]>
commit f4881bc7a83eff263789dd524b7c269d138d4af5 upstream.
Dave reported a warning when running xfstest 275. We have been leaking delalloc
metadata space when our reservations fail. This is because we were improperly
calculating how much space to free for our checksum reservations. The problem
is we would sometimes free up space that had already been freed in another
thread and we would end up with negative usage for the delalloc space. This
patch fixes the problem by calculating how much space the other threads would
have already freed, and then calculate how much space we need to free had we not
done the reservation at all, and then freeing any excess space. This makes
xfstests 275 no longer have leaked space. Thanks
Reported-by: David Sterba <[email protected]>
Signed-off-by: Josef Bacik <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
fs/btrfs/extent-tree.c | 47 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 6 deletions(-)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 6e1d367..fe6cec5 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4487,14 +4487,49 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
* If the inodes csum_bytes is the same as the original
* csum_bytes then we know we haven't raced with any free()ers
* so we can just reduce our inodes csum bytes and carry on.
- * Otherwise we have to do the normal free thing to account for
- * the case that the free side didn't free up its reserve
- * because of this outstanding reservation.
*/
- if (BTRFS_I(inode)->csum_bytes == csum_bytes)
+ if (BTRFS_I(inode)->csum_bytes == csum_bytes) {
calc_csum_metadata_size(inode, num_bytes, 0);
- else
- to_free = calc_csum_metadata_size(inode, num_bytes, 0);
+ } else {
+ u64 orig_csum_bytes = BTRFS_I(inode)->csum_bytes;
+ u64 bytes;
+
+ /*
+ * This is tricky, but first we need to figure out how much we
+ * free'd from any free-ers that occured during this
+ * reservation, so we reset ->csum_bytes to the csum_bytes
+ * before we dropped our lock, and then call the free for the
+ * number of bytes that were freed while we were trying our
+ * reservation.
+ */
+ bytes = csum_bytes - BTRFS_I(inode)->csum_bytes;
+ BTRFS_I(inode)->csum_bytes = csum_bytes;
+ to_free = calc_csum_metadata_size(inode, bytes, 0);
+
+
+ /*
+ * Now we need to see how much we would have freed had we not
+ * been making this reservation and our ->csum_bytes were not
+ * artificially inflated.
+ */
+ BTRFS_I(inode)->csum_bytes = csum_bytes - num_bytes;
+ bytes = csum_bytes - orig_csum_bytes;
+ bytes = calc_csum_metadata_size(inode, bytes, 0);
+
+ /*
+ * Now reset ->csum_bytes to what it should be. If bytes is
+ * more than to_free then we would have free'd more space had we
+ * not had an artificially high ->csum_bytes, so we need to free
+ * the remainder. If bytes is the same or less then we don't
+ * need to do anything, the other free-ers did the correct
+ * thing.
+ */
+ BTRFS_I(inode)->csum_bytes = orig_csum_bytes - num_bytes;
+ if (bytes > to_free)
+ to_free = bytes - to_free;
+ else
+ to_free = 0;
+ }
spin_unlock(&BTRFS_I(inode)->lock);
if (dropped)
to_free += btrfs_calc_trans_metadata_size(root, dropped);
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
commit 4adaa611020fa6ac65b0ac8db78276af4ec04e63 upstream.
Btrfs uses page_mkwrite to ensure stable pages during
crc calculations and mmap workloads. We call clear_page_dirty_for_io
before we do any crcs, and this forces any application with the file
mapped to wait for the crc to finish before it is allowed to change
the file.
With compression on, the clear_page_dirty_for_io step is happening after
we've compressed the pages. This means the applications might be
changing the pages while we are compressing them, and some of those
modifications might not hit the disk.
This commit adds the clear_page_dirty_for_io before compression starts
and makes sure to redirty the page if we have to fallback to
uncompressed IO as well.
Signed-off-by: Chris Mason <[email protected]>
Reported-by: Alexandre Oliva <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/btrfs/extent_io.c | 33 +++++++++++++++++++++++++++++++++
fs/btrfs/extent_io.h | 2 ++
fs/btrfs/inode.c | 14 ++++++++++++++
3 files changed, 49 insertions(+)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index b89ba9f..9d1970b 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1229,6 +1229,39 @@ int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end)
GFP_NOFS);
}
+int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+ unsigned long index = start >> PAGE_CACHE_SHIFT;
+ unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+ struct page *page;
+
+ while (index <= end_index) {
+ page = find_get_page(inode->i_mapping, index);
+ BUG_ON(!page); /* Pages should be in the extent_io_tree */
+ clear_page_dirty_for_io(page);
+ page_cache_release(page);
+ index++;
+ }
+ return 0;
+}
+
+int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+ unsigned long index = start >> PAGE_CACHE_SHIFT;
+ unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+ struct page *page;
+
+ while (index <= end_index) {
+ page = find_get_page(inode->i_mapping, index);
+ BUG_ON(!page); /* Pages should be in the extent_io_tree */
+ account_page_redirty(page);
+ __set_page_dirty_nobuffers(page);
+ page_cache_release(page);
+ index++;
+ }
+ return 0;
+}
+
/*
* helper function to set both pages and extents in the tree writeback
*/
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 25900af..c5003db 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -314,6 +314,8 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
unsigned long *map_len);
int extent_range_uptodate(struct extent_io_tree *tree,
u64 start, u64 end);
+int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
+int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
int extent_clear_unlock_delalloc(struct inode *inode,
struct extent_io_tree *tree,
u64 start, u64 end, struct page *locked_page,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fadf1c3..4f71dc6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -349,6 +349,7 @@ static noinline int compress_file_range(struct inode *inode,
int i;
int will_compress;
int compress_type = root->fs_info->compress_type;
+ int redirty = 0;
/* if this is a small write inside eof, kick off a defrag */
if ((end - start + 1) < 16 * 1024 &&
@@ -411,6 +412,17 @@ again:
if (BTRFS_I(inode)->force_compress)
compress_type = BTRFS_I(inode)->force_compress;
+ /*
+ * we need to call clear_page_dirty_for_io on each
+ * page in the range. Otherwise applications with the file
+ * mmap'd can wander in and change the page contents while
+ * we are compressing them.
+ *
+ * If the compression fails for any reason, we set the pages
+ * dirty again later on.
+ */
+ extent_range_clear_dirty_for_io(inode, start, end);
+ redirty = 1;
ret = btrfs_compress_pages(compress_type,
inode->i_mapping, start,
total_compressed, pages,
@@ -552,6 +564,8 @@ cleanup_and_bail_uncompressed:
__set_page_dirty_nobuffers(locked_page);
/* unlocked later on in the async handlers */
}
+ if (redirty)
+ extent_range_redirty_for_io(inode, start, end);
add_async_extent(async_cow, start, end - start + 1,
0, NULL, 0, BTRFS_COMPRESS_NONE);
*num_added += 1;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Boyer <[email protected]>
commit 620ae90ed8ca8b6e40cb9e10279b4f5ef9f0ab81 upstream.
This keyboard backlight device causes a 10 second delay to boot. Add it
to the quirk list with HID_QUIRK_NO_INIT_REPORTS.
This fixes Red Hat bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=907221
Signed-off-by: Josh Boyer <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/hid/hid-ids.h | 3 +++
drivers/hid/usbhid/hid-quirks.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b57671c..7561d73 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -565,6 +565,9 @@
#define USB_VENDOR_ID_MONTEREY 0x0566
#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
+#define USB_VENDOR_ID_MSI 0x1770
+#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL 0xff00
+
#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
#define USB_DEVICE_ID_N_S_HARMONY 0xc359
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index a73bb7a..e11d186 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -73,6 +73,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
+ { USB_VENDIR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Boyer <[email protected]>
commit 3d464d9b71ef2f2b40a4bc9dcf06794fd1be9d12 upstream.
This device needs to be added to the quirks list with HID_QUIRK_NO_INIT_REPORTS,
otherwise it causes 10 seconds timeout during report initialization.
This fixes Red Hat bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=806587
Signed-off-by: Josh Boyer <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/hid/hid-ids.h | 3 +++
drivers/hid/usbhid/hid-quirks.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c04eec3..b57671c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -656,6 +656,9 @@
#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008
#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001
+#define USB_VENDOR_ID_REALTEK 0x0bda
+#define USB_DEVICE_ID_REALTEK_READER 0x0152
+
#define USB_VENDOR_ID_ROCCAT 0x1e7d
#define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4
#define USB_DEVICE_ID_ROCCAT_ISKU 0x319c
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 1a4bc41..a73bb7a 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -79,6 +79,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Beulich <[email protected]>
commit 0e5e098ac22dae38f957e951b70d3cf73beff0f7 upstream.
Commit 7708992 ("xen/blkback: Seperate the bio allocation and the bio
submission") consolidated the pendcnt updates to just a single write,
neglecting the fact that the error path relied on it getting set to 1
up front (such that the decrement in __end_block_io_op() would actually
drop the count to zero, triggering the necessary cleanup actions).
Also remove a misleading and a stale (after said commit) comment.
Signed-off-by: Jan Beulich <[email protected]>
Signed-off-by: Konrad Rzeszutek Wilk <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/block/xen-blkback/blkback.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index c85d91a..4fd1dea 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -743,13 +743,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
bio->bi_end_io = end_block_io_op;
}
- /*
- * We set it one so that the last submit_bio does not have to call
- * atomic_inc.
- */
atomic_set(&pending_req->pendcnt, nbio);
-
- /* Get a reference count for the disk queue and start sending I/O */
blk_start_plug(&plug);
for (i = 0; i < nbio; i++)
@@ -777,6 +771,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
fail_put_bio:
for (i = 0; i < nbio; i++)
bio_put(biolist[i]);
+ atomic_set(&pending_req->pendcnt, 1);
__end_block_io_op(pending_req, -EINVAL);
msleep(1); /* back off a bit */
return -EIO;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Frederic Weisbecker <[email protected]>
commit e5ab012c3271990e8457055c25cafddc1ae8aa6b upstream.
As it stands, irq_exit() may or may not be called with
irqs disabled, depending on __ARCH_IRQ_EXIT_IRQS_DISABLED
that the arch can define.
It makes tick_nohz_irq_exit() unsafe. For example two
interrupts can race in tick_nohz_stop_sched_tick(): the inner
most one computes the expiring time on top of the timer list,
then it's interrupted right before reprogramming the
clock. The new interrupt enqueues a new timer list timer,
it reprogram the clock to take it into account and it exits.
The CPUs resumes the inner most interrupt and performs the clock
reprogramming without considering the new timer list timer.
This regression has been introduced by:
280f06774afedf849f0b34248ed6aff57d0f6908
("nohz: Separate out irq exit and idle loop dyntick logic")
Let's fix it right now with the appropriate protections.
A saner long term solution will be to remove
__ARCH_IRQ_EXIT_IRQS_DISABLED and mandate that irq_exit() is called
with interrupts disabled.
Signed-off-by: Frederic Weisbecker <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: <[email protected]> #v3.2+
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
[ luis: backported to 3.5 ]
Signed-off-by: Luis Henriques <[email protected]>
---
kernel/time/tick-sched.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 4a08472..cc1825f 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -500,12 +500,17 @@ void tick_nohz_idle_enter(void)
*/
void tick_nohz_irq_exit(void)
{
+ unsigned long flags;
struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
if (!ts->inidle)
return;
+ local_irq_save(flags);
+
tick_nohz_stop_sched_tick(ts);
+
+ local_irq_restore(flags);
}
/**
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: David Vrabel <[email protected]>
commit 0e367ae46503cfe7791460c8ba8434a5d60b2bd5 upstream.
If the frontend is using a non-native protocol (e.g., a 64-bit
frontend with a 32-bit backend) and it sent an unrecognized request,
the request was not translated and the response would have the
incorrect ID. This may cause the frontend driver to behave
incorrectly or crash.
Since the ID field in the request is always in the same place,
regardless of the request type we can get the correct ID and make a
valid response (which will report BLKIF_RSP_EOPNOTSUPP).
This bug affected 64-bit SLES 11 guests when using a 32-bit backend.
This guest does a BLKIF_OP_RESERVED_1 (BLKIF_OP_PACKET in the SLES
source) and would crash in blkif_int() as the ID in the response would
be invalid.
Signed-off-by: David Vrabel <[email protected]>
Signed-off-by: Konrad Rzeszutek Wilk <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/block/xen-blkback/blkback.c | 31 +++++++++++++++++++++++++++----
drivers/block/xen-blkback/common.h | 25 +++++++++++++++++++++++++
include/xen/interface/io/blkif.h | 10 ++++++++++
3 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index c6decb9..c85d91a 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -422,6 +422,16 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
return err;
}
+static int dispatch_other_io(struct xen_blkif *blkif,
+ struct blkif_request *req,
+ struct pending_req *pending_req)
+{
+ free_req(pending_req);
+ make_response(blkif, req->u.other.id, req->operation,
+ BLKIF_RSP_EOPNOTSUPP);
+ return -EIO;
+}
+
static void xen_blk_drain_io(struct xen_blkif *blkif)
{
atomic_set(&blkif->drain, 1);
@@ -543,17 +553,30 @@ __do_block_io_op(struct xen_blkif *blkif)
/* Apply all sanity checks to /private copy/ of request. */
barrier();
- if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
+
+ switch (req.operation) {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ case BLKIF_OP_WRITE_BARRIER:
+ case BLKIF_OP_FLUSH_DISKCACHE:
+ if (dispatch_rw_block_io(blkif, &req, pending_req))
+ goto done;
+ break;
+ case BLKIF_OP_DISCARD:
free_req(pending_req);
if (dispatch_discard_io(blkif, &req))
- break;
- } else if (dispatch_rw_block_io(blkif, &req, pending_req))
+ goto done;
+ break;
+ default:
+ if (dispatch_other_io(blkif, &req, pending_req))
+ goto done;
break;
+ }
/* Yield point for this unbounded loop. */
cond_resched();
}
-
+done:
return more_to_do;
}
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 9ad3b5e..fc2a486 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -76,11 +76,18 @@ struct blkif_x86_32_request_discard {
uint64_t nr_sectors;
} __attribute__((__packed__));
+struct blkif_x86_32_request_other {
+ uint8_t _pad1;
+ blkif_vdev_t _pad2;
+ uint64_t id; /* private guest value, echoed in resp */
+} __attribute__((__packed__));
+
struct blkif_x86_32_request {
uint8_t operation; /* BLKIF_OP_??? */
union {
struct blkif_x86_32_request_rw rw;
struct blkif_x86_32_request_discard discard;
+ struct blkif_x86_32_request_other other;
} u;
} __attribute__((__packed__));
@@ -112,11 +119,19 @@ struct blkif_x86_64_request_discard {
uint64_t nr_sectors;
} __attribute__((__packed__));
+struct blkif_x86_64_request_other {
+ uint8_t _pad1;
+ blkif_vdev_t _pad2;
+ uint32_t _pad3; /* offsetof(blkif_..,u.discard.id)==8 */
+ uint64_t id; /* private guest value, echoed in resp */
+} __attribute__((__packed__));
+
struct blkif_x86_64_request {
uint8_t operation; /* BLKIF_OP_??? */
union {
struct blkif_x86_64_request_rw rw;
struct blkif_x86_64_request_discard discard;
+ struct blkif_x86_64_request_other other;
} u;
} __attribute__((__packed__));
@@ -262,6 +277,11 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst,
dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
break;
default:
+ /*
+ * Don't know how to translate this op. Only get the
+ * ID so failure can be reported to the frontend.
+ */
+ dst->u.other.id = src->u.other.id;
break;
}
}
@@ -293,6 +313,11 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst,
dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
break;
default:
+ /*
+ * Don't know how to translate this op. Only get the
+ * ID so failure can be reported to the frontend.
+ */
+ dst->u.other.id = src->u.other.id;
break;
}
}
diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h
index ee338bf..2af8fdb 100644
--- a/include/xen/interface/io/blkif.h
+++ b/include/xen/interface/io/blkif.h
@@ -138,11 +138,21 @@ struct blkif_request_discard {
uint8_t _pad3;
} __attribute__((__packed__));
+struct blkif_request_other {
+ uint8_t _pad1;
+ blkif_vdev_t _pad2; /* only for read/write requests */
+#ifdef CONFIG_X86_64
+ uint32_t _pad3; /* offsetof(blkif_req..,u.other.id)==8*/
+#endif
+ uint64_t id; /* private guest value, echoed in resp */
+} __attribute__((__packed__));
+
struct blkif_request {
uint8_t operation; /* BLKIF_OP_??? */
union {
struct blkif_request_rw rw;
struct blkif_request_discard discard;
+ struct blkif_request_other other;
} u;
} __attribute__((__packed__));
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit 7ea600b5314529f9d1b9d6d3c41cb26fce6a7a4a upstream.
... lest we get livelocks between path_is_under() and d_path() and friends.
The thing is, wrt fairness lglocks are more similar to rwsems than to rwlocks;
it is possible to have thread B spin on attempt to take lock shared while thread
A is already holding it shared, if B is on lower-numbered CPU than A and there's
a thread C spinning on attempt to take the same lock exclusive.
As the result, we need consistent ordering between vfsmount_lock (lglock) and
rename_lock (seq_lock), even though everything that takes both is going to take
vfsmount_lock only shared.
Spotted-by: Brad Spengler <[email protected]>
Signed-off-by: Al Viro <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
fs/dcache.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c
index 1845c46..458ec45 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2579,7 +2579,6 @@ static int prepend_path(const struct path *path,
bool slash = false;
int error = 0;
- br_read_lock(&vfsmount_lock);
while (dentry != root->dentry || vfsmnt != root->mnt) {
struct dentry * parent;
@@ -2609,8 +2608,6 @@ static int prepend_path(const struct path *path,
if (!error && !slash)
error = prepend(buffer, buflen, "/", 1);
-out:
- br_read_unlock(&vfsmount_lock);
return error;
global_root:
@@ -2627,7 +2624,7 @@ global_root:
error = prepend(buffer, buflen, "/", 1);
if (!error)
error = real_mount(vfsmnt)->mnt_ns ? 1 : 2;
- goto out;
+ return error;
}
/**
@@ -2654,9 +2651,11 @@ char *__d_path(const struct path *path,
int error;
prepend(&res, &buflen, "\0", 1);
+ br_read_lock(&vfsmount_lock);
write_seqlock(&rename_lock);
error = prepend_path(path, root, &res, &buflen);
write_sequnlock(&rename_lock);
+ br_read_unlock(&vfsmount_lock);
if (error < 0)
return ERR_PTR(error);
@@ -2673,9 +2672,11 @@ char *d_absolute_path(const struct path *path,
int error;
prepend(&res, &buflen, "\0", 1);
+ br_read_lock(&vfsmount_lock);
write_seqlock(&rename_lock);
error = prepend_path(path, &root, &res, &buflen);
write_sequnlock(&rename_lock);
+ br_read_unlock(&vfsmount_lock);
if (error > 1)
error = -EINVAL;
@@ -2739,11 +2740,13 @@ char *d_path(const struct path *path, char *buf, int buflen)
return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
get_fs_root(current->fs, &root);
+ br_read_lock(&vfsmount_lock);
write_seqlock(&rename_lock);
error = path_with_deleted(path, &root, &res, &buflen);
+ write_sequnlock(&rename_lock);
+ br_read_unlock(&vfsmount_lock);
if (error < 0)
res = ERR_PTR(error);
- write_sequnlock(&rename_lock);
path_put(&root);
return res;
}
@@ -2898,6 +2901,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
get_fs_root_and_pwd(current->fs, &root, &pwd);
error = -ENOENT;
+ br_read_lock(&vfsmount_lock);
write_seqlock(&rename_lock);
if (!d_unlinked(pwd.dentry)) {
unsigned long len;
@@ -2907,6 +2911,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
prepend(&cwd, &buflen, "\0", 1);
error = prepend_path(&pwd, &root, &cwd, &buflen);
write_sequnlock(&rename_lock);
+ br_read_unlock(&vfsmount_lock);
if (error < 0)
goto out;
@@ -2927,6 +2932,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
}
} else {
write_sequnlock(&rename_lock);
+ br_read_unlock(&vfsmount_lock);
}
out:
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 89b1f39eb4189de745fae554b0d614d87c8d5c63 upstream.
For large UDF filesystems with 512-byte blocks the number of necessary
bitmap blocks is larger than 2^16 so s_nr_groups in udf_bitmap overflows
(the number will overflow for filesystems larger than 128 GB with
512-byte blocks). That results in ENOSPC errors despite the filesystem
has plenty of free space.
Fix the problem by changing s_nr_groups' type to 'int'. That is enough
even for filesystems 2^32 blocks (UDF maximum) and 512-byte blocksize.
Reported-and-tested-by: [email protected]
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/udf/udf_sb.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 42ad69a..9e8e08e 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -82,7 +82,7 @@ struct udf_virtual_data {
struct udf_bitmap {
__u32 s_extLength;
__u32 s_extPosition;
- __u16 s_nr_groups;
+ int s_nr_groups;
struct buffer_head **s_block_bitmap;
};
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Lingzhu Xiang <[email protected]>
commit 613f04a0f51e6e68ac6fe571ab79da3c0a5eb4da upstream.
Backported for 3.4-stable. Re-added current_trace NULL checks;
removed allocated_snapshot field; adapted to
tracing_trace_options_write without trace_set_options.
From: "Steven Rostedt (Red Hat)" <[email protected]>
The latency tracers require the buffers to be in overwrite mode,
otherwise they get screwed up. Force the buffers to stay in overwrite
mode when latency tracers are enabled.
Added a flag_changed() method to the tracer structure to allow
the tracers to see what flags are being changed, and also be able
to prevent the change from happing.
Cc: [email protected]
Signed-off-by: Steven Rostedt <[email protected]>
Signed-off-by: Lingzhu Xiang <[email protected]>
Reviewed-by: CAI Qian <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques<[email protected]>
---
kernel/trace/trace.c | 35 +++++++++++++++++++++++++++++------
kernel/trace/trace.h | 7 +++++++
kernel/trace/trace_irqsoff.c | 19 ++++++++++++++-----
kernel/trace/trace_sched_wakeup.c | 18 +++++++++++++-----
4 files changed, 63 insertions(+), 16 deletions(-)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index b354405..34c61b2 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2762,11 +2762,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
return -EINVAL;
}
-static void set_tracer_flags(unsigned int mask, int enabled)
+/* Some tracers require overwrite to stay enabled */
+int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
+{
+ if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set)
+ return -1;
+
+ return 0;
+}
+
+int set_tracer_flag(unsigned int mask, int enabled)
{
/* do nothing if flag is already set */
if (!!(trace_flags & mask) == !!enabled)
- return;
+ return 0;
+
+ /* Give the tracer a chance to approve the change */
+ if (current_trace->flag_changed)
+ if (current_trace->flag_changed(current_trace, mask, !!enabled))
+ return -EINVAL;
if (enabled)
trace_flags |= mask;
@@ -2782,6 +2796,8 @@ static void set_tracer_flags(unsigned int mask, int enabled)
ring_buffer_change_overwrite(max_tr.buffer, enabled);
#endif
}
+
+ return 0;
}
static ssize_t
@@ -2791,7 +2807,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
char buf[64];
char *cmp;
int neg = 0;
- int ret = 0;
+ int ret = -ENODEV;
int i;
if (cnt >= sizeof(buf))
@@ -2812,7 +2828,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
for (i = 0; trace_options[i]; i++) {
if (strcmp(cmp, trace_options[i]) == 0) {
- set_tracer_flags(1 << i, !neg);
+ ret = set_tracer_flag(1 << i, !neg);
break;
}
}
@@ -2823,7 +2839,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
mutex_unlock(&trace_types_lock);
- if (ret)
+ if (ret < 0)
return ret;
*ppos += cnt;
@@ -3166,6 +3182,9 @@ static int tracing_set_tracer(const char *buf)
goto out;
trace_branch_disable();
+
+ current_trace->enabled = false;
+
if (current_trace && current_trace->reset)
current_trace->reset(tr);
if (current_trace && current_trace->use_max_tr) {
@@ -3202,6 +3221,7 @@ static int tracing_set_tracer(const char *buf)
goto out;
}
+ current_trace->enabled = true;
trace_branch_enable(tr);
out:
mutex_unlock(&trace_types_lock);
@@ -4605,9 +4625,12 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
return -EINVAL;
mutex_lock(&trace_types_lock);
- set_tracer_flags(1 << index, val);
+ ret = set_tracer_flag(1 << index, val);
mutex_unlock(&trace_types_lock);
+ if (ret < 0)
+ return ret;
+
*ppos += cnt;
return cnt;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 5aec220..29812da 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -283,10 +283,14 @@ struct tracer {
enum print_line_t (*print_line)(struct trace_iterator *iter);
/* If you handled the flag setting, return 0 */
int (*set_flag)(u32 old_flags, u32 bit, int set);
+ /* Return 0 if OK with change, else return non-zero */
+ int (*flag_changed)(struct tracer *tracer,
+ u32 mask, int set);
struct tracer *next;
struct tracer_flags *flags;
int print_max;
int use_max_tr;
+ bool enabled;
};
@@ -833,6 +837,9 @@ extern const char *__stop___trace_bprintk_fmt[];
void trace_printk_init_buffers(void);
+int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set);
+int set_tracer_flag(unsigned int mask, int enabled);
+
#undef FTRACE_ENTRY
#define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter) \
extern struct ftrace_event_call \
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 99d20e9..8dd139a 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -32,7 +32,7 @@ enum {
static int trace_type __read_mostly;
-static int save_lat_flag;
+static int save_flags;
static void stop_irqsoff_tracer(struct trace_array *tr, int graph);
static int start_irqsoff_tracer(struct trace_array *tr, int graph);
@@ -557,8 +557,11 @@ static void stop_irqsoff_tracer(struct trace_array *tr, int graph)
static void __irqsoff_tracer_init(struct trace_array *tr)
{
- save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT;
- trace_flags |= TRACE_ITER_LATENCY_FMT;
+ save_flags = trace_flags;
+
+ /* non overwrite screws up the latency tracers */
+ set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
+ set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
tracing_max_latency = 0;
irqsoff_trace = tr;
@@ -572,10 +575,13 @@ static void __irqsoff_tracer_init(struct trace_array *tr)
static void irqsoff_tracer_reset(struct trace_array *tr)
{
+ int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
+ int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
+
stop_irqsoff_tracer(tr, is_graph());
- if (!save_lat_flag)
- trace_flags &= ~TRACE_ITER_LATENCY_FMT;
+ set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
+ set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
}
static void irqsoff_tracer_start(struct trace_array *tr)
@@ -608,6 +614,7 @@ static struct tracer irqsoff_tracer __read_mostly =
.print_line = irqsoff_print_line,
.flags = &tracer_flags,
.set_flag = irqsoff_set_flag,
+ .flag_changed = trace_keep_overwrite,
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_irqsoff,
#endif
@@ -641,6 +648,7 @@ static struct tracer preemptoff_tracer __read_mostly =
.print_line = irqsoff_print_line,
.flags = &tracer_flags,
.set_flag = irqsoff_set_flag,
+ .flag_changed = trace_keep_overwrite,
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_preemptoff,
#endif
@@ -676,6 +684,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly =
.print_line = irqsoff_print_line,
.flags = &tracer_flags,
.set_flag = irqsoff_set_flag,
+ .flag_changed = trace_keep_overwrite,
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_preemptirqsoff,
#endif
diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c
index ff791ea..9eadedc 100644
--- a/kernel/trace/trace_sched_wakeup.c
+++ b/kernel/trace/trace_sched_wakeup.c
@@ -36,7 +36,7 @@ static void __wakeup_reset(struct trace_array *tr);
static int wakeup_graph_entry(struct ftrace_graph_ent *trace);
static void wakeup_graph_return(struct ftrace_graph_ret *trace);
-static int save_lat_flag;
+static int save_flags;
#define TRACE_DISPLAY_GRAPH 1
@@ -539,8 +539,11 @@ static void stop_wakeup_tracer(struct trace_array *tr)
static int __wakeup_tracer_init(struct trace_array *tr)
{
- save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT;
- trace_flags |= TRACE_ITER_LATENCY_FMT;
+ save_flags = trace_flags;
+
+ /* non overwrite screws up the latency tracers */
+ set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
+ set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
tracing_max_latency = 0;
wakeup_trace = tr;
@@ -562,12 +565,15 @@ static int wakeup_rt_tracer_init(struct trace_array *tr)
static void wakeup_tracer_reset(struct trace_array *tr)
{
+ int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
+ int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
+
stop_wakeup_tracer(tr);
/* make sure we put back any tasks we are tracing */
wakeup_reset(tr);
- if (!save_lat_flag)
- trace_flags &= ~TRACE_ITER_LATENCY_FMT;
+ set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
+ set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
}
static void wakeup_tracer_start(struct trace_array *tr)
@@ -593,6 +599,7 @@ static struct tracer wakeup_tracer __read_mostly =
.print_line = wakeup_print_line,
.flags = &tracer_flags,
.set_flag = wakeup_set_flag,
+ .flag_changed = trace_keep_overwrite,
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_wakeup,
#endif
@@ -614,6 +621,7 @@ static struct tracer wakeup_rt_tracer __read_mostly =
.print_line = wakeup_print_line,
.flags = &tracer_flags,
.set_flag = wakeup_set_flag,
+ .flag_changed = trace_keep_overwrite,
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_wakeup,
#endif
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Jussi Kivilinna <[email protected]>
commit 36ef0b473fbf43d5db23eea4616cc1d18cec245f upstream.
Signed-off-by: Jussi Kivilinna <[email protected]>
Acked-by: Larry Finger <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/rtlwifi/usb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index d4850b4..bec780a 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -853,6 +853,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
if (unlikely(!_urb)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Can't allocate urb. Drop skb!\n");
+ kfree_skb(skb);
return;
}
urb_list = &rtlusb->tx_pending[ep_num];
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Lingzhu Xiang <[email protected]>
commit 69d34da2984c95b33ea21518227e1f9470f11d95 upstream.
Backported for 3.4, 3.0-stable. Moved return to after unlock.
From: "Steven Rostedt (Red Hat)" <[email protected]>
Seems that the tracer flags have never been protected from
synchronous writes. Luckily, admins don't usually modify the
tracing flags via two different tasks. But if scripts were to
be used to modify them, then they could get corrupted.
Move the trace_types_lock that protects against tracers changing
to also protect the flags being set.
Cc: [email protected]
Signed-off-by: Steven Rostedt <[email protected]>
Signed-off-by: Lingzhu Xiang <[email protected]>
Reviewed-by: CAI Qian <[email protected]>
Signed-off-by: Luis Henriques<[email protected]>
---
kernel/trace/trace.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 199f77b..b354405 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2791,7 +2791,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
char buf[64];
char *cmp;
int neg = 0;
- int ret;
+ int ret = 0;
int i;
if (cnt >= sizeof(buf))
@@ -2808,6 +2808,8 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
cmp += 2;
}
+ mutex_lock(&trace_types_lock);
+
for (i = 0; trace_options[i]; i++) {
if (strcmp(cmp, trace_options[i]) == 0) {
set_tracer_flags(1 << i, !neg);
@@ -2816,13 +2818,13 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
}
/* If no option could be set, test the specific tracer options */
- if (!trace_options[i]) {
- mutex_lock(&trace_types_lock);
+ if (!trace_options[i])
ret = set_tracer_option(current_trace, cmp, neg);
- mutex_unlock(&trace_types_lock);
- if (ret)
- return ret;
- }
+
+ mutex_unlock(&trace_types_lock);
+
+ if (ret)
+ return ret;
*ppos += cnt;
@@ -4601,7 +4603,10 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
if (val != 0 && val != 1)
return -EINVAL;
+
+ mutex_lock(&trace_types_lock);
set_tracer_flags(1 << index, val);
+ mutex_unlock(&trace_types_lock);
*ppos += cnt;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
commit cf4ab538f1516606d3ae730dce15d6f33d96b7e1 upstream.
Functions like nfs_map_uid_to_name() and nfs_map_gid_to_group() are
expected to return a string without any terminating NUL character.
Regression introduced by commit 57e62324e469e092ecc6c94a7a86fe4bd6ac5172
(NFS: Store the legacy idmapper result in the keyring).
Reported-by: Dave Chiluk <[email protected]>
Signed-off-by: Trond Myklebust <[email protected]>
Cc: Bryan Schumaker <[email protected]>
[ luis: backported to 3.5: adjusted context ]
Signed-off-by: Luis Henriques <[email protected]>
---
fs/nfs/idmap.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index a0972e9..e4476dc 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -710,9 +710,9 @@ out1:
return ret;
}
-static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data)
+static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
{
- return key_instantiate_and_link(key, data, strlen(data) + 1,
+ return key_instantiate_and_link(key, data, datalen,
id_resolver_cache->thread_keyring,
authkey);
}
@@ -720,15 +720,18 @@ static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *dat
static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey)
{
char id_str[NFS_UINT_MAXLEN];
+ size_t len;
int ret = -EINVAL;
switch (im->im_conv) {
case IDMAP_CONV_NAMETOID:
- sprintf(id_str, "%d", im->im_id);
- ret = nfs_idmap_instantiate(key, authkey, id_str);
+ /* Note: here we store the NUL terminator too */
+ len = sprintf(id_str, "%d", im->im_id) + 1;
+ ret = nfs_idmap_instantiate(key, authkey, id_str, len);
break;
case IDMAP_CONV_IDTONAME:
- ret = nfs_idmap_instantiate(key, authkey, im->im_name);
+ len = strlen(im->im_name);
+ ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
break;
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Lekensteyn <[email protected]>
commit d627b62ff8d4d36761adbcd90ff143d79c94ab22 upstream.
This is rather a hack to fix brightness hotkeys on a Clevo laptop. CADL is not
used anywhere in the driver code at the moment, but it could be used in BIOS as
is the case with the Clevo laptop.
The Clevo B7130 requires the CADL field to contain at least the ID of
the LCD device. If this field is empty, the ACPI methods that are called
on pressing brightness / display switching hotkeys will not trigger a
notification. As a result, it appears as no hotkey has been pressed.
Reference: https://bugs.freedesktop.org/show_bug.cgi?id=45452
Tested-by: Peter Wu <[email protected]>
Signed-off-by: Peter Wu <[email protected]>
Acked-by: Jesse Barnes <[email protected]>
Signed-off-by: Daniel Vetter <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/gpu/drm/i915/intel_opregion.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 18bd0af..e27c170 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -427,6 +427,25 @@ blind_set:
goto end;
}
+static void intel_setup_cadls(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_opregion *opregion = &dev_priv->opregion;
+ int i = 0;
+ u32 disp_id;
+
+ /* Initialize the CADL field by duplicating the DIDL values.
+ * Technically, this is not always correct as display outputs may exist,
+ * but not active. This initialization is necessary for some Clevo
+ * laptops that check this field before processing the brightness and
+ * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if
+ * there are less than eight devices. */
+ do {
+ disp_id = ioread32(&opregion->acpi->didl[i]);
+ iowrite32(disp_id, &opregion->acpi->cadl[i]);
+ } while (++i < 8 && disp_id != 0);
+}
+
void intel_opregion_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -436,8 +455,10 @@ void intel_opregion_init(struct drm_device *dev)
return;
if (opregion->acpi) {
- if (drm_core_check_feature(dev, DRIVER_MODESET))
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_didl_outputs(dev);
+ intel_setup_cadls(dev);
+ }
/* Notify BIOS we are ready to handle ACPI video ext notifs.
* Right now, all the events are handled by the ACPI video module.
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Joerg Roedel <[email protected]>
commit c2a2876e863356b092967ea62bebdb4dd663af80 upstream.
There is a bug introduced with commit 27c2127 that causes
devices which are hot unplugged and then hot-replugged to
not have per-device dma_ops set. This causes these devices
to not function correctly. Fixed with this patch.
Reported-by: Andreas Degert <[email protected]>
Signed-off-by: Joerg Roedel <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/iommu/amd_iommu.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 3f365ab..33fee0a 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2270,18 +2270,16 @@ static int device_change_notifier(struct notifier_block *nb,
/* allocate a protection domain if a device is added */
dma_domain = find_protection_domain(devid);
- if (dma_domain)
- goto out;
- dma_domain = dma_ops_domain_alloc();
- if (!dma_domain)
- goto out;
- dma_domain->target_dev = devid;
-
- spin_lock_irqsave(&iommu_pd_list_lock, flags);
- list_add_tail(&dma_domain->list, &iommu_pd_list);
- spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
-
- dev_data = get_dev_data(dev);
+ if (!dma_domain) {
+ dma_domain = dma_ops_domain_alloc();
+ if (!dma_domain)
+ goto out;
+ dma_domain->target_dev = devid;
+
+ spin_lock_irqsave(&iommu_pd_list_lock, flags);
+ list_add_tail(&dma_domain->list, &iommu_pd_list);
+ spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+ }
dev->archdata.dma_ops = &amd_iommu_dma_ops;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
commit 896ee0eee6261e30c3623be931c3f621428947df upstream.
This makes sure that release_sock is called for all error conditions in
irda_getsockopt.
Signed-off-by: Kees Cook <[email protected]>
Reported-by: Brad Spengler <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/irda/af_irda.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index bb14c34..d6c291c 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2584,8 +2584,10 @@ bed:
NULL, NULL, NULL);
/* Check if the we got some results */
- if (!self->cachedaddr)
- return -EAGAIN; /* Didn't find any devices */
+ if (!self->cachedaddr) {
+ err = -EAGAIN; /* Didn't find any devices */
+ goto out;
+ }
daddr = self->cachedaddr;
/* Cleanup */
self->cachedaddr = 0;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit e8cd81693bbbb15db57d3c9aa7dd90eda4842874 upstream.
vcs_poll_data_free() calls unregister_vt_notifier(), which calls
atomic_notifier_chain_unregister(), which calls synchronize_rcu().
Do it *after* we'd dropped ->f_lock.
Signed-off-by: Al Viro <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/tty/vt/vc_screen.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index fa7268a..6abb92c 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -93,7 +93,7 @@ vcs_poll_data_free(struct vcs_poll_data *poll)
static struct vcs_poll_data *
vcs_poll_data_get(struct file *file)
{
- struct vcs_poll_data *poll = file->private_data;
+ struct vcs_poll_data *poll = file->private_data, *kill = NULL;
if (poll)
return poll;
@@ -122,10 +122,12 @@ vcs_poll_data_get(struct file *file)
file->private_data = poll;
} else {
/* someone else raced ahead of us */
- vcs_poll_data_free(poll);
+ kill = poll;
poll = file->private_data;
}
spin_unlock(&file->f_lock);
+ if (kill)
+ vcs_poll_data_free(kill);
return poll;
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: fanchaoting <[email protected]>
commit 4376c94618c26225e69e17b7c91169c45a90b292 upstream.
when pnfs block using device mapper,if umounting later,it maybe
cause oops. we apply "1 + sizeof(bl_umount_request)" memory for
msg->data, the memory maybe overflow when we do "memcpy(&dataptr
[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request))",
because the size of bl_msg is more than 1 byte.
Signed-off-by: fanchaoting<[email protected]>
Signed-off-by: Trond Myklebust <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
fs/nfs/blocklayout/blocklayoutdm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/blocklayout/blocklayoutdm.c b/fs/nfs/blocklayout/blocklayoutdm.c
index 737d839..6fc7b5c 100644
--- a/fs/nfs/blocklayout/blocklayoutdm.c
+++ b/fs/nfs/blocklayout/blocklayoutdm.c
@@ -55,7 +55,8 @@ static void dev_remove(struct net *net, dev_t dev)
bl_pipe_msg.bl_wq = &nn->bl_wq;
memset(msg, 0, sizeof(*msg));
- msg->data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS);
+ msg->len = sizeof(bl_msg) + bl_msg.totallen;
+ msg->data = kzalloc(msg->len, GFP_NOFS);
if (!msg->data)
goto out;
@@ -66,7 +67,6 @@ static void dev_remove(struct net *net, dev_t dev)
memcpy(msg->data, &bl_msg, sizeof(bl_msg));
dataptr = (uint8_t *) msg->data;
memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request));
- msg->len = sizeof(bl_msg) + bl_msg.totallen;
add_wait_queue(&nn->bl_wq, &wq);
if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) {
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
commit 1166fde6a923c30f4351515b6a9a1efc513e7d00 upstream.
We need to be careful when testing task->tk_waitqueue in
rpc_wake_up_task_queue_locked, because it can be changed while we
are holding the queue->lock.
By adding appropriate memory barriers, we can ensure that it is safe to
test task->tk_waitqueue for equality if the RPC_TASK_QUEUED bit is set.
Signed-off-by: Trond Myklebust <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
net/sunrpc/sched.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 85b9235..72d89e1 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -143,6 +143,8 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
task->tk_waitqueue = queue;
queue->qlen++;
+ /* barrier matches the read in rpc_wake_up_task_queue_locked() */
+ smp_wmb();
rpc_set_queued(task);
dprintk("RPC: %5u added to queue %p \"%s\"\n",
@@ -399,8 +401,11 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task
*/
static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
{
- if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue)
- __rpc_do_wake_up_task(queue, task);
+ if (RPC_IS_QUEUED(task)) {
+ smp_rmb();
+ if (task->tk_waitqueue == queue)
+ __rpc_do_wake_up_task(queue, task);
+ }
}
/*
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Marciniszyn <[email protected]>
commit 1ee9e2aa7b31427303466776f455d43e5e3c9275 upstream.
Commit f0dc117abdfa ("IPoIB: Fix TX queue lockup with mixed UD/CM
traffic") attempts to solve an issue where unprocessed UD send
completions can deadlock the netdev.
The patch doesn't fully resolve the issue because if more than half
the tx_outstanding's were UD and all of the destinations are RC
reachable, arming the CQ doesn't solve the issue.
This patch uses the IB_CQ_REPORT_MISSED_EVENTS on the
ib_req_notify_cq(). If the rc is above 0, the UD send cq completion
callback is called directly to re-arm the send completion timer.
This issue is seen in very large parallel filesystem deployments
and the patch has been shown to correct the issue.
Reviewed-by: Dean Luick <[email protected]>
Signed-off-by: Mike Marciniszyn <[email protected]>
Signed-off-by: Roland Dreier <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/infiniband/ulp/ipoib/ipoib_cm.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 014504d..3767853 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -755,9 +755,13 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
if (++priv->tx_outstanding == ipoib_sendq_size) {
ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
tx->qp->qp_num);
- if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP))
- ipoib_warn(priv, "request notify on send CQ failed\n");
netif_stop_queue(dev);
+ rc = ib_req_notify_cq(priv->send_cq,
+ IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS);
+ if (rc < 0)
+ ipoib_warn(priv, "request notify on send CQ failed\n");
+ else if (rc)
+ ipoib_send_comp_handler(priv->send_cq, dev);
}
}
}
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
commit a073dbff359f4741013ae4b8395f5364c5e00b48 upstream.
We need to clear the NFS_LSEG_LAYOUTCOMMIT bits atomically with the
NFS_INO_LAYOUTCOMMIT bit, otherwise we may end up with situations
where the two are out of sync.
The first half of the problem is to ensure that pnfs_layoutcommit_inode
clears the NFS_LSEG_LAYOUTCOMMIT bit through pnfs_list_write_lseg.
We still need to keep the reference to those segments until the RPC call
is finished, so in order to make it clear _where_ those references come
from, we add a helper pnfs_list_write_lseg_done() that cleans up after
pnfs_list_write_lseg.
Signed-off-by: Trond Myklebust <[email protected]>
Acked-by: Benny Halevy <[email protected]>
[ luis: backported to 3.5:
- adjust context
- function rename pnfs_put_lseg -> put_lseg ]
Signed-off-by: Luis Henriques <[email protected]>
---
fs/nfs/nfs4proc.c | 14 --------------
fs/nfs/pnfs.c | 19 ++++++++++++++++++-
2 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 81d51aa..b96aa12 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6501,22 +6501,8 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
static void nfs4_layoutcommit_release(void *calldata)
{
struct nfs4_layoutcommit_data *data = calldata;
- struct pnfs_layout_segment *lseg, *tmp;
- unsigned long *bitlock = &NFS_I(data->args.inode)->flags;
pnfs_cleanup_layoutcommit(data);
- /* Matched by references in pnfs_set_layoutcommit */
- list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) {
- list_del_init(&lseg->pls_lc_list);
- if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
- &lseg->pls_flags))
- put_lseg(lseg);
- }
-
- clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
- smp_mb__after_clear_bit();
- wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
-
put_rpccred(data->cred);
kfree(data);
}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 8229a0e..958d512 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1546,11 +1546,27 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
if (lseg->pls_range.iomode == IOMODE_RW &&
- test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+ test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
list_add(&lseg->pls_lc_list, listp);
}
}
+static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp)
+{
+ struct pnfs_layout_segment *lseg, *tmp;
+ unsigned long *bitlock = &NFS_I(inode)->flags;
+
+ /* Matched by references in pnfs_set_layoutcommit */
+ list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) {
+ list_del_init(&lseg->pls_lc_list);
+ put_lseg(lseg);
+ }
+
+ clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
+ smp_mb__after_clear_bit();
+ wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
+}
+
void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
{
if (lseg->pls_range.iomode == IOMODE_RW) {
@@ -1601,6 +1617,7 @@ void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data)
if (nfss->pnfs_curr_ld->cleanup_layoutcommit)
nfss->pnfs_curr_ld->cleanup_layoutcommit(data);
+ pnfs_list_write_lseg_done(data->args.inode, &data->lseg_list);
}
/*
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Rutland <[email protected]>
commit a7dc19b8652c862d5b7c4d2339bd3c428bd29c4a upstream.
Currently tick_check_broadcast_device doesn't reject clock_event_devices
with CLOCK_EVT_FEAT_DUMMY, and may select them in preference to real
hardware if they have a higher rating value. In this situation, the
dummy timer is responsible for broadcasting to itself, and the core
clockevents code may attempt to call non-existent callbacks for
programming the dummy, eventually leading to a panic.
This patch makes tick_check_broadcast_device always reject dummy timers,
preventing this problem.
Signed-off-by: Mark Rutland <[email protected]>
Cc: [email protected]
Cc: Jon Medhurst (Tixy) <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Luis Henriques <[email protected]>
---
kernel/time/tick-broadcast.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index f113755..a13987a 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -66,7 +66,8 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc)
*/
int tick_check_broadcast_device(struct clock_event_device *dev)
{
- if ((tick_broadcast_device.evtdev &&
+ if ((dev->features & CLOCK_EVT_FEAT_DUMMY) ||
+ (tick_broadcast_device.evtdev &&
tick_broadcast_device.evtdev->rating >= dev->rating) ||
(dev->features & CLOCK_EVT_FEAT_C3STOP))
return 0;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
commit 01d4ab96d2e7fceaad204e5a8710ce34e229b8c5 upstream.
The beacon and multicast-buffer queues are managed by the beacon
tasklet, and the generic tx path hang check does not help in any way
here. Running it on those queues anyway can introduce some race
conditions leading to unnecessary chip resets.
Signed-off-by: Felix Fietkau <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
[ luis: backported to 3.5:
- file rename link.c -> xmit.c
- adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/ath/ath9k/xmit.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 12a42f2..894ed0e 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2258,21 +2258,21 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
sc->tx_complete_poll_work_seen++;
#endif
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i)) {
- txq = &sc->tx.txq[i];
- ath_txq_lock(sc, txq);
- if (txq->axq_depth) {
- if (txq->axq_tx_inprogress) {
- needreset = true;
- ath_txq_unlock(sc, txq);
- break;
- } else {
- txq->axq_tx_inprogress = true;
- }
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ txq = sc->tx.txq_map[i];
+
+ ath_txq_lock(sc, txq);
+ if (txq->axq_depth) {
+ if (txq->axq_tx_inprogress) {
+ needreset = true;
+ ath_txq_unlock(sc, txq);
+ break;
+ } else {
+ txq->axq_tx_inprogress = true;
}
- ath_txq_unlock_complete(sc, txq);
}
+ ath_txq_unlock_complete(sc, txq);
+ }
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
commit 74632d11a133b5baf6b9d622dd19d2f944d93d94 upstream.
The commit 'ath9k_hw: fix calibration issues on chainmask that don't
include chain 0' changed the hardware chainmask to the chip chainmask
for the duration of the calibration, but the revert to user
configuration in the reset path runs too early.
That causes some issues with limiting the number of antennas (including
spurious failure in hardware-generated packets).
Fix this by reverting the chainmask after the essential parts of the
calibration that need the workaround, and before NF calibration is run.
Signed-off-by: Felix Fietkau <[email protected]>
Reported-by: Wojciech Dubowik <[email protected]>
Tested-by: Wojciech Dubowik <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_calib.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 53aeca7..601213d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -910,6 +910,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
AR_PHY_CL_TAB_1,
AR_PHY_CL_TAB_2 };
+ /* Use chip chainmask only for calibration */
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
if (rtt) {
@@ -1057,6 +1058,9 @@ skip_tx_iqcal:
ar9003_hw_rtt_disable(ah);
}
+ /* Revert chainmask to runtime parameters */
+ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+
/* Initialize list pointers */
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
ah->supp_cals = IQ_MISMATCH_CAL;
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit ebaf5795ef57a70a042ea259448a465024e2821d upstream.
Add support for the AR9462 chip
T: Bus=03 Lev=01 Prnt=01 Port=08 Cnt=01 Dev#= 5 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0cf3 ProdID=817a Rev= 0.02
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
Cc: Gustavo Padovan <[email protected]>
Signed-off-by: Ming Lei <[email protected]>
Signed-off-by: Gustavo Padovan <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/bluetooth/ath3k.c | 2 ++
drivers/bluetooth/btusb.c | 1 +
2 files changed, 3 insertions(+)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 0f069ec..8369de1 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -76,6 +76,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0CF3, 0x0036) },
{ USB_DEVICE(0x0CF3, 0x3004) },
{ USB_DEVICE(0x0CF3, 0x311D) },
+ { USB_DEVICE(0x0CF3, 0x817a) },
{ USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x04CA, 0x3005) },
{ USB_DEVICE(0x13d3, 0x3362) },
@@ -104,6 +105,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 984cf1e..8b2046c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -142,6 +142,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
--
1.8.1.2
3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit d66629c1325399cf080ba8b2fb086c10e5439cdd upstream.
Add support for the AR9462 chip
T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 3 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0cf3 ProdID=0036 Rev= 0.02
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=01
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
Cc: Gustavo Padovan <[email protected]>
Signed-off-by: Ming Lei <[email protected]>
Signed-off-by: Gustavo Padovan <[email protected]>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <[email protected]>
---
drivers/bluetooth/ath3k.c | 2 ++
drivers/bluetooth/btusb.c | 1 +
2 files changed, 3 insertions(+)
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index b00000e..0f069ec 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -73,6 +73,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x03F0, 0x311D) },
/* Atheros AR3012 with sflash firmware*/
+ { USB_DEVICE(0x0CF3, 0x0036) },
{ USB_DEVICE(0x0CF3, 0x3004) },
{ USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x13d3, 0x3375) },
@@ -100,6 +101,7 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
static struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR3012 with sflash firmware*/
+ { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 37f5ba6..984cf1e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -139,6 +139,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
/* Atheros 3012 with sflash firmware */
+ { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
--
1.8.1.2
Hi Luis,
> 3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
>
> ------------------
>
> From: Bing Zhao <[email protected]>
>
> commit 084c7189acb3f969c855536166042e27f5dd703f upstream.
>
> curr_cmd points to the command that is in processing or waiting
> for its command response from firmware. If the function shutdown
> happens to occur at this time we should cancel the cmd timer and
> put the command back to free queue.
>
> Tested-by: Marco Cesarano <[email protected]>
> Signed-off-by: Bing Zhao <[email protected]>
> Signed-off-by: John W. Linville <[email protected]>
> Signed-off-by: Luis Henriques <[email protected]>
This patch is intended for kernel 3.8+.
Please drop it from linux-3.5.7.10 stable.
Thanks,
Bing
Hi Bing,
On Mon, Apr 08, 2013 at 11:03:32AM -0700, Bing Zhao wrote:
> Hi Luis,
>
> > 3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
> >
> > ------------------
> >
> > From: Bing Zhao <[email protected]>
> >
> > commit 084c7189acb3f969c855536166042e27f5dd703f upstream.
> >
> > curr_cmd points to the command that is in processing or waiting
> > for its command response from firmware. If the function shutdown
> > happens to occur at this time we should cancel the cmd timer and
> > put the command back to free queue.
> >
> > Tested-by: Marco Cesarano <[email protected]>
> > Signed-off-by: Bing Zhao <[email protected]>
> > Signed-off-by: John W. Linville <[email protected]>
> > Signed-off-by: Luis Henriques <[email protected]>
>
> This patch is intended for kernel 3.8+.
> Please drop it from linux-3.5.7.10 stable.
Sorry, I didn't noticed that. I'll drop it from 3.5. Thanks.
Cheers,
--
Luis
On Mon, 2013-04-08 at 10:50 +0100, Luis Henriques wrote:
> 3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
>
> ------------------
>
> From: Matt Fleming <[email protected]>
>
> commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
>
> It's not wise to assume VariableNameSize represents the length of
> VariableName, as not all firmware updates VariableNameSize in the same
> way (some don't update it at all if EFI_SUCCESS is returned). There
> are even implementations out there that update VariableNameSize with
> values that are both larger than the string returned in VariableName
> and smaller than the buffer passed to GetNextVariableName(), which
> resulted in the following bug report from Michael Schroeder,
>
> > On HP z220 system (firmware version 1.54), some EFI variables are
> > incorrectly named :
> >
> > ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
> > /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d-00e098032b8c
>
> The issue here is that because we blindly use VariableNameSize without
> verifying its value, we can potentially read garbage values from the
> buffer containing VariableName if VariableNameSize is larger than the
> length of VariableName.
>
> Since VariableName is a string, we can calculate its size by searching
> for the terminating NULL character.
>
> Reported-by: Frederic Crozat <[email protected]>
> Cc: Matthew Garrett <[email protected]>
> Cc: Josh Boyer <[email protected]>
> Cc: Michael Schroeder <[email protected]>
> Cc: Lee, Chun-Yi <[email protected]>
> Cc: Lingzhu Xiang <[email protected]>
> Cc: Seiji Aguchi <[email protected]>
> Signed-off-by: Matt Fleming <[email protected]>
> [ Backported for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
[...]
I thought the workqueue addition was a worthwhile fix in its own right,
so for 3.2.y I cherry-picked that as well.
Ben.
--
Ben Hutchings
Life would be so much easier if we could look at the source code.
On Tue, Apr 09, 2013 at 11:45:06PM +0100, Ben Hutchings wrote:
> On Mon, 2013-04-08 at 10:50 +0100, Luis Henriques wrote:
> > 3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
> >
> > ------------------
> >
> > From: Matt Fleming <[email protected]>
> >
> > commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
> >
> > It's not wise to assume VariableNameSize represents the length of
> > VariableName, as not all firmware updates VariableNameSize in the same
> > way (some don't update it at all if EFI_SUCCESS is returned). There
> > are even implementations out there that update VariableNameSize with
> > values that are both larger than the string returned in VariableName
> > and smaller than the buffer passed to GetNextVariableName(), which
> > resulted in the following bug report from Michael Schroeder,
> >
> > > On HP z220 system (firmware version 1.54), some EFI variables are
> > > incorrectly named :
> > >
> > > ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
> > > /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d-00e098032b8c
> >
> > The issue here is that because we blindly use VariableNameSize without
> > verifying its value, we can potentially read garbage values from the
> > buffer containing VariableName if VariableNameSize is larger than the
> > length of VariableName.
> >
> > Since VariableName is a string, we can calculate its size by searching
> > for the terminating NULL character.
> >
> > Reported-by: Frederic Crozat <[email protected]>
> > Cc: Matthew Garrett <[email protected]>
> > Cc: Josh Boyer <[email protected]>
> > Cc: Michael Schroeder <[email protected]>
> > Cc: Lee, Chun-Yi <[email protected]>
> > Cc: Lingzhu Xiang <[email protected]>
> > Cc: Seiji Aguchi <[email protected]>
> > Signed-off-by: Matt Fleming <[email protected]>
> > [ Backported for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
> [...]
>
> I thought the workqueue addition was a worthwhile fix in its own right,
> so for 3.2.y I cherry-picked that as well.
Ok, makes sense to me too. So here's what I'll do: for this release
I'll just drop this commit and e971318bbed610e28bb3fde9d548e6aaf0a6b02e
('efivars: Handle duplicate names from get_next_variable()').
I'll queue them again for next release along with commit
a93bc0c6e07ed9bac44700280e65e2945d864fd4 ('efi_pstore: Introducing
workqueue updating sysfs').
Thanks for your review Ben.
Cheers,
--
Luis
On 04/10/2013 06:45 AM, Ben Hutchings wrote:
> On Mon, 2013-04-08 at 10:50 +0100, Luis Henriques wrote:
>> 3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
>>
>> ------------------
>>
>> From: Matt Fleming <[email protected]>
>>
>> commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
>>
>> It's not wise to assume VariableNameSize represents the length of
>> VariableName, as not all firmware updates VariableNameSize in the same
>> way (some don't update it at all if EFI_SUCCESS is returned). There
>> are even implementations out there that update VariableNameSize with
>> values that are both larger than the string returned in VariableName
>> and smaller than the buffer passed to GetNextVariableName(), which
>> resulted in the following bug report from Michael Schroeder,
>>
>> > On HP z220 system (firmware version 1.54), some EFI variables are
>> > incorrectly named :
>> >
>> > ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
>> > /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
>> > /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
>> > /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
>> > /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d-00e098032b8c
>>
>> The issue here is that because we blindly use VariableNameSize without
>> verifying its value, we can potentially read garbage values from the
>> buffer containing VariableName if VariableNameSize is larger than the
>> length of VariableName.
>>
>> Since VariableName is a string, we can calculate its size by searching
>> for the terminating NULL character.
>>
>> Reported-by: Frederic Crozat <[email protected]>
>> Cc: Matthew Garrett <[email protected]>
>> Cc: Josh Boyer <[email protected]>
>> Cc: Michael Schroeder <[email protected]>
>> Cc: Lee, Chun-Yi <[email protected]>
>> Cc: Lingzhu Xiang <[email protected]>
>> Cc: Seiji Aguchi <[email protected]>
>> Signed-off-by: Matt Fleming <[email protected]>
>> [ Backported for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
> [...]
>
> I thought the workqueue addition was a worthwhile fix in its own right,
> so for 3.2.y I cherry-picked that as well.
FWIW, the workqueue patch is 1/2 of this patchset[1] fixing closely
related problems. The other one is 81fa4e58.
[1]: http://article.gmane.org/gmane.linux.kernel/1439570
I tried to avoid pulling too much for stable because the patchset is
quite large and I suspect the problem it fixes is only theoretical. I
reported the original bug but was unable to break anything except
getting call traces with various CONFIG_DEBUG_*.
What's your opinion, Seiji?
Lingzhu Xiang
On Wed, Apr 10, 2013 at 06:27:13PM +0800, Lingzhu Xiang wrote:
> On 04/10/2013 06:45 AM, Ben Hutchings wrote:
> >On Mon, 2013-04-08 at 10:50 +0100, Luis Henriques wrote:
> >>3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
> >>
> >>------------------
> >>
> >>From: Matt Fleming <[email protected]>
> >>
> >>commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
> >>
> >>It's not wise to assume VariableNameSize represents the length of
> >>VariableName, as not all firmware updates VariableNameSize in the same
> >>way (some don't update it at all if EFI_SUCCESS is returned). There
> >>are even implementations out there that update VariableNameSize with
> >>values that are both larger than the string returned in VariableName
> >>and smaller than the buffer passed to GetNextVariableName(), which
> >>resulted in the following bug report from Michael Schroeder,
> >>
> >> > On HP z220 system (firmware version 1.54), some EFI variables are
> >> > incorrectly named :
> >> >
> >> > ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
> >> > /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> >> > /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> >> > /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> >> > /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d-00e098032b8c
> >>
> >>The issue here is that because we blindly use VariableNameSize without
> >>verifying its value, we can potentially read garbage values from the
> >>buffer containing VariableName if VariableNameSize is larger than the
> >>length of VariableName.
> >>
> >>Since VariableName is a string, we can calculate its size by searching
> >>for the terminating NULL character.
> >>
> >>Reported-by: Frederic Crozat <[email protected]>
> >>Cc: Matthew Garrett <[email protected]>
> >>Cc: Josh Boyer <[email protected]>
> >>Cc: Michael Schroeder <[email protected]>
> >>Cc: Lee, Chun-Yi <[email protected]>
> >>Cc: Lingzhu Xiang <[email protected]>
> >>Cc: Seiji Aguchi <[email protected]>
> >>Signed-off-by: Matt Fleming <[email protected]>
> >>[ Backported for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
> >[...]
> >
> >I thought the workqueue addition was a worthwhile fix in its own right,
> >so for 3.2.y I cherry-picked that as well.
>
> FWIW, the workqueue patch is 1/2 of this patchset[1] fixing closely
> related problems. The other one is 81fa4e58.
>
> [1]: http://article.gmane.org/gmane.linux.kernel/1439570
>
> I tried to avoid pulling too much for stable because the patchset is
> quite large and I suspect the problem it fixes is only theoretical.
> I reported the original bug but was unable to break anything except
> getting call traces with various CONFIG_DEBUG_*.
>
> What's your opinion, Seiji?
Ok, so just to clarify: you're suggesting me to pick the following commits:
81fa4e581d9283f7992a0d8c534bb141eb840a14 efivars: Disable external interrupt while holding efivars->lock
a93bc0c6e07ed9bac44700280e65e2945d864fd4 efi_pstore: Introducing workqueue updating sysfs
ec50bd32f1672d38ddce10fb1841cbfda89cfe9a efivars: explicitly calculate length of VariableName
e971318bbed610e28bb3fde9d548e6aaf0a6b02e efivars: Handle duplicate names from get_next_variable()
Is this correct?
Cheers,
--
Luis
> -----Original Message-----
> From: Luis Henriques [mailto:[email protected]]
> Sent: Wednesday, April 10, 2013 8:18 AM
> To: Lingzhu Xiang
> Cc: Ben Hutchings; Seiji Aguchi; [email protected]; [email protected]; [email protected]; Matthew
> Garrett; Josh Boyer; Michael Schroeder; Lee, Chun-Yi; Matt Fleming
> Subject: Re: [PATCH 097/102] efivars: explicitly calculate length of VariableName
>
> On Wed, Apr 10, 2013 at 06:27:13PM +0800, Lingzhu Xiang wrote:
> > On 04/10/2013 06:45 AM, Ben Hutchings wrote:
> > >On Mon, 2013-04-08 at 10:50 +0100, Luis Henriques wrote:
> > >>3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
> > >>
> > >>------------------
> > >>
> > >>From: Matt Fleming <[email protected]>
> > >>
> > >>commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
> > >>
> > >>It's not wise to assume VariableNameSize represents the length of
> > >>VariableName, as not all firmware updates VariableNameSize in the
> > >>same way (some don't update it at all if EFI_SUCCESS is returned).
> > >>There are even implementations out there that update
> > >>VariableNameSize with values that are both larger than the string
> > >>returned in VariableName and smaller than the buffer passed to
> > >>GetNextVariableName(), which resulted in the following bug report
> > >>from Michael Schroeder,
> > >>
> > >> > On HP z220 system (firmware version 1.54), some EFI variables are
> > >> > incorrectly named :
> > >> >
> > >> > ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
> > >> > /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > >> > /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > >> > /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > >> >
> > >> /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d
> > >> -00e098032b8c
> > >>
> > >>The issue here is that because we blindly use VariableNameSize
> > >>without verifying its value, we can potentially read garbage values
> > >>from the buffer containing VariableName if VariableNameSize is
> > >>larger than the length of VariableName.
> > >>
> > >>Since VariableName is a string, we can calculate its size by
> > >>searching for the terminating NULL character.
> > >>
> > >>Reported-by: Frederic Crozat <[email protected]>
> > >>Cc: Matthew Garrett <[email protected]>
> > >>Cc: Josh Boyer <[email protected]>
> > >>Cc: Michael Schroeder <[email protected]>
> > >>Cc: Lee, Chun-Yi <[email protected]>
> > >>Cc: Lingzhu Xiang <[email protected]>
> > >>Cc: Seiji Aguchi <[email protected]>
> > >>Signed-off-by: Matt Fleming <[email protected]> [ Backported
> > >>for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
> > >[...]
> > >
> > >I thought the workqueue addition was a worthwhile fix in its own
> > >right, so for 3.2.y I cherry-picked that as well.
> >
> > FWIW, the workqueue patch is 1/2 of this patchset[1] fixing closely
> > related problems. The other one is 81fa4e58.
> >
> > [1]: http://article.gmane.org/gmane.linux.kernel/1439570
> >
> > I tried to avoid pulling too much for stable because the patchset is
> > quite large and I suspect the problem it fixes is only theoretical.
> > I reported the original bug but was unable to break anything except
> > getting call traces with various CONFIG_DEBUG_*.
> >
> > What's your opinion, Seiji?
>
> Ok, so just to clarify: you're suggesting me to pick the following commits:
>
> 81fa4e581d9283f7992a0d8c534bb141eb840a14 efivars: Disable external interrupt while holding efivars->lock
> a93bc0c6e07ed9bac44700280e65e2945d864fd4 efi_pstore: Introducing workqueue updating sysfs
> ec50bd32f1672d38ddce10fb1841cbfda89cfe9a efivars: explicitly calculate length of VariableName
> e971318bbed610e28bb3fde9d548e6aaf0a6b02e efivars: Handle duplicate names from get_next_variable()
I agree to add these commits to a stable tree.
Seiji
>
> Is this correct?
>
> Cheers,
> --
> Luis
On Wed, Apr 10, 2013 at 03:57:12PM +0000, Seiji Aguchi wrote:
>
>
> > -----Original Message-----
> > From: Luis Henriques [mailto:[email protected]]
> > Sent: Wednesday, April 10, 2013 8:18 AM
> > To: Lingzhu Xiang
> > Cc: Ben Hutchings; Seiji Aguchi; [email protected]; [email protected]; [email protected]; Matthew
> > Garrett; Josh Boyer; Michael Schroeder; Lee, Chun-Yi; Matt Fleming
> > Subject: Re: [PATCH 097/102] efivars: explicitly calculate length of VariableName
> >
> > On Wed, Apr 10, 2013 at 06:27:13PM +0800, Lingzhu Xiang wrote:
> > > On 04/10/2013 06:45 AM, Ben Hutchings wrote:
> > > >On Mon, 2013-04-08 at 10:50 +0100, Luis Henriques wrote:
> > > >>3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
> > > >>
> > > >>------------------
> > > >>
> > > >>From: Matt Fleming <[email protected]>
> > > >>
> > > >>commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
> > > >>
> > > >>It's not wise to assume VariableNameSize represents the length of
> > > >>VariableName, as not all firmware updates VariableNameSize in the
> > > >>same way (some don't update it at all if EFI_SUCCESS is returned).
> > > >>There are even implementations out there that update
> > > >>VariableNameSize with values that are both larger than the string
> > > >>returned in VariableName and smaller than the buffer passed to
> > > >>GetNextVariableName(), which resulted in the following bug report
> > > >>from Michael Schroeder,
> > > >>
> > > >> > On HP z220 system (firmware version 1.54), some EFI variables are
> > > >> > incorrectly named :
> > > >> >
> > > >> > ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
> > > >> > /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > >> > /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > >> > /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > >> >
> > > >> /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d
> > > >> -00e098032b8c
> > > >>
> > > >>The issue here is that because we blindly use VariableNameSize
> > > >>without verifying its value, we can potentially read garbage values
> > > >>from the buffer containing VariableName if VariableNameSize is
> > > >>larger than the length of VariableName.
> > > >>
> > > >>Since VariableName is a string, we can calculate its size by
> > > >>searching for the terminating NULL character.
> > > >>
> > > >>Reported-by: Frederic Crozat <[email protected]>
> > > >>Cc: Matthew Garrett <[email protected]>
> > > >>Cc: Josh Boyer <[email protected]>
> > > >>Cc: Michael Schroeder <[email protected]>
> > > >>Cc: Lee, Chun-Yi <[email protected]>
> > > >>Cc: Lingzhu Xiang <[email protected]>
> > > >>Cc: Seiji Aguchi <[email protected]>
> > > >>Signed-off-by: Matt Fleming <[email protected]> [ Backported
> > > >>for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
> > > >[...]
> > > >
> > > >I thought the workqueue addition was a worthwhile fix in its own
> > > >right, so for 3.2.y I cherry-picked that as well.
> > >
> > > FWIW, the workqueue patch is 1/2 of this patchset[1] fixing closely
> > > related problems. The other one is 81fa4e58.
> > >
> > > [1]: http://article.gmane.org/gmane.linux.kernel/1439570
> > >
> > > I tried to avoid pulling too much for stable because the patchset is
> > > quite large and I suspect the problem it fixes is only theoretical.
> > > I reported the original bug but was unable to break anything except
> > > getting call traces with various CONFIG_DEBUG_*.
> > >
> > > What's your opinion, Seiji?
> >
> > Ok, so just to clarify: you're suggesting me to pick the following commits:
> >
> > 81fa4e581d9283f7992a0d8c534bb141eb840a14 efivars: Disable external interrupt while holding efivars->lock
> > a93bc0c6e07ed9bac44700280e65e2945d864fd4 efi_pstore: Introducing workqueue updating sysfs
> > ec50bd32f1672d38ddce10fb1841cbfda89cfe9a efivars: explicitly calculate length of VariableName
> > e971318bbed610e28bb3fde9d548e6aaf0a6b02e efivars: Handle duplicate names from get_next_variable()
>
> I agree to add these commits to a stable tree.
>
Thank you Seiji. I'll queue these for the next 3.5 kernel.
Cheers,
--
Luis
(Adding Ben back to the CC list; not sure how his email was dropped)
On Thu, Apr 11, 2013 at 10:12:56AM +0100, Luis Henriques wrote:
> On Wed, Apr 10, 2013 at 03:57:12PM +0000, Seiji Aguchi wrote:
> >
> >
> > > -----Original Message-----
> > > From: Luis Henriques [mailto:[email protected]]
> > > Sent: Wednesday, April 10, 2013 8:18 AM
> > > To: Lingzhu Xiang
> > > Cc: Ben Hutchings; Seiji Aguchi; [email protected]; [email protected]; [email protected]; Matthew
> > > Garrett; Josh Boyer; Michael Schroeder; Lee, Chun-Yi; Matt Fleming
> > > Subject: Re: [PATCH 097/102] efivars: explicitly calculate length of VariableName
> > >
> > > On Wed, Apr 10, 2013 at 06:27:13PM +0800, Lingzhu Xiang wrote:
> > > > On 04/10/2013 06:45 AM, Ben Hutchings wrote:
> > > > >On Mon, 2013-04-08 at 10:50 +0100, Luis Henriques wrote:
> > > > >>3.5.7.10 -stable review patch. If anyone has any objections, please let me know.
> > > > >>
> > > > >>------------------
> > > > >>
> > > > >>From: Matt Fleming <[email protected]>
> > > > >>
> > > > >>commit ec50bd32f1672d38ddce10fb1841cbfda89cfe9a upstream.
> > > > >>
> > > > >>It's not wise to assume VariableNameSize represents the length of
> > > > >>VariableName, as not all firmware updates VariableNameSize in the
> > > > >>same way (some don't update it at all if EFI_SUCCESS is returned).
> > > > >>There are even implementations out there that update
> > > > >>VariableNameSize with values that are both larger than the string
> > > > >>returned in VariableName and smaller than the buffer passed to
> > > > >>GetNextVariableName(), which resulted in the following bug report
> > > > >>from Michael Schroeder,
> > > > >>
> > > > >> > On HP z220 system (firmware version 1.54), some EFI variables are
> > > > >> > incorrectly named :
> > > > >> >
> > > > >> > ls -d /sys/firmware/efi/vars/*8be4d* | grep -v -- -8be returns
> > > > >> > /sys/firmware/efi/vars/dbxDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > > >> > /sys/firmware/efi/vars/KEKDefault-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > > >> > /sys/firmware/efi/vars/SecureBoot-pport8be4df61-93ca-11d2-aa0d-00e098032b8c
> > > > >> >
> > > > >> /sys/firmware/efi/vars/SetupMode-Information8be4df61-93ca-11d2-aa0d
> > > > >> -00e098032b8c
> > > > >>
> > > > >>The issue here is that because we blindly use VariableNameSize
> > > > >>without verifying its value, we can potentially read garbage values
> > > > >>from the buffer containing VariableName if VariableNameSize is
> > > > >>larger than the length of VariableName.
> > > > >>
> > > > >>Since VariableName is a string, we can calculate its size by
> > > > >>searching for the terminating NULL character.
> > > > >>
> > > > >>Reported-by: Frederic Crozat <[email protected]>
> > > > >>Cc: Matthew Garrett <[email protected]>
> > > > >>Cc: Josh Boyer <[email protected]>
> > > > >>Cc: Michael Schroeder <[email protected]>
> > > > >>Cc: Lee, Chun-Yi <[email protected]>
> > > > >>Cc: Lingzhu Xiang <[email protected]>
> > > > >>Cc: Seiji Aguchi <[email protected]>
> > > > >>Signed-off-by: Matt Fleming <[email protected]> [ Backported
> > > > >>for 3.4-stable. Removed workqueue code added in a93bc0c 3.9-rc1. ]
> > > > >[...]
> > > > >
> > > > >I thought the workqueue addition was a worthwhile fix in its own
> > > > >right, so for 3.2.y I cherry-picked that as well.
> > > >
> > > > FWIW, the workqueue patch is 1/2 of this patchset[1] fixing closely
> > > > related problems. The other one is 81fa4e58.
> > > >
> > > > [1]: http://article.gmane.org/gmane.linux.kernel/1439570
> > > >
> > > > I tried to avoid pulling too much for stable because the patchset is
> > > > quite large and I suspect the problem it fixes is only theoretical.
> > > > I reported the original bug but was unable to break anything except
> > > > getting call traces with various CONFIG_DEBUG_*.
> > > >
> > > > What's your opinion, Seiji?
> > >
> > > Ok, so just to clarify: you're suggesting me to pick the following commits:
> > >
> > > 81fa4e581d9283f7992a0d8c534bb141eb840a14 efivars: Disable external interrupt while holding efivars->lock
> > > a93bc0c6e07ed9bac44700280e65e2945d864fd4 efi_pstore: Introducing workqueue updating sysfs
> > > ec50bd32f1672d38ddce10fb1841cbfda89cfe9a efivars: explicitly calculate length of VariableName
> > > e971318bbed610e28bb3fde9d548e6aaf0a6b02e efivars: Handle duplicate names from get_next_variable()
> >
> > I agree to add these commits to a stable tree.
> >
> Thank you Seiji. I'll queue these for the next 3.5 kernel.
So, after spending some time around this, I ended up picking much
more commits than those listed above. Since this code in 3.5.y wasn't
that different from Ben's 3.2.y, I took the liberty of picking all the
bits I was missing from there. Here's what I ended up with:
d80a361d779a9f19498943d1ca84243209cd5647 efi_pstore: Check remaining space with QueryVariableInfo() before writing data
81fa4e581d9283f7992a0d8c534bb141eb840a14 efivars: Disable external interrupt while holding efivars->lock
68d929862e29a8b52a7f2f2f86a0600423b093cd efi: be more paranoid about available space when creating variables
ed9dc8ce7a1c8115dba9483a9b51df8b63a2e0ef efivars: Allow disabling use as a pstore backend
ec0971ba5372a4dfa753f232449d23a8fd98490e efivars: Add module parameter to disable use as a pstore backend
ca0ba26fbbd2d81c43085df49ce0abfe34535a90 efivars: Fix check for CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE
a93bc0c6e07ed9bac44700280e65e2945d864fd4 efi_pstore: Introducing workqueue updating sysfs
ec50bd32f1672d38ddce10fb1841cbfda89cfe9a efivars: explicitly calculate length of VariableName
e971318bbed610e28bb3fde9d548e6aaf0a6b02e efivars: Handle duplicate names from get_next_variable()
efivars: pstore: Do not check size when erasing variable
(this last commit was picked from 3.2.y directly, its not an upstream
commit)
I'll be sending out 3.5.7.11 for review later this week, and I would
really appreciate any feedback on these commits.
(Ben: Thanks a lot, since most of the backport work was took from your
tree.)
Cheers,
--
Luis
On 04/16/2013 06:33 PM, Luis Henriques wrote:
> 68d929862e29a8b52a7f2f2f86a0600423b093cd efi: be more paranoid about available space when creating variables
This prevents a bricking issue for some Samsung devices but causes
regression on many other machines.
https://bugzilla.kernel.org/show_bug.cgi?id=55471
https://bugzilla.redhat.com/show_bug.cgi?id=947142
http://article.gmane.org/gmane.linux.kernel.efi/1078
http://article.gmane.org/gmane.linux.kernel.stable/47150
This patchset will fix it again:
http://thread.gmane.org/gmane.linux.kernel.efi/1081
On Wed, Apr 17, 2013 at 12:37:43PM +0800, Lingzhu Xiang wrote:
> On 04/16/2013 06:33 PM, Luis Henriques wrote:
> >68d929862e29a8b52a7f2f2f86a0600423b093cd efi: be more paranoid about available space when creating variables
>
> This prevents a bricking issue for some Samsung devices but causes
> regression on many other machines.
>
> https://bugzilla.kernel.org/show_bug.cgi?id=55471
> https://bugzilla.redhat.com/show_bug.cgi?id=947142
> http://article.gmane.org/gmane.linux.kernel.efi/1078
> http://article.gmane.org/gmane.linux.kernel.stable/47150
>
> This patchset will fix it again:
>
> http://thread.gmane.org/gmane.linux.kernel.efi/1081
Thanks for the pointer. I note that in that thread you yourself imply
there are still issues after applying them? Was that accurate, is there
yet further patches needed?
-apw
On 04/17/2013 07:56 PM, Andy Whitcroft wrote:
> On Wed, Apr 17, 2013 at 12:37:43PM +0800, Lingzhu Xiang wrote:
>> On 04/16/2013 06:33 PM, Luis Henriques wrote:
>>> 68d929862e29a8b52a7f2f2f86a0600423b093cd efi: be more paranoid about available space when creating variables
>>
>> This prevents a bricking issue for some Samsung devices but causes
>> regression on many other machines.
>>
>> https://bugzilla.kernel.org/show_bug.cgi?id=55471
>> https://bugzilla.redhat.com/show_bug.cgi?id=947142
>> http://article.gmane.org/gmane.linux.kernel.efi/1078
>> http://article.gmane.org/gmane.linux.kernel.stable/47150
>>
>> This patchset will fix it again:
>>
>> http://thread.gmane.org/gmane.linux.kernel.efi/1081
>
> Thanks for the pointer. I note that in that thread you yourself imply
> there are still issues after applying them? Was that accurate, is there
> yet further patches needed?
I just find that issue. Didn't see that when writing the above.
Earlier I was testing on a different machine and the result was good. I
guess the patch still needs some more testing.
Lingzhu
On Wed, Apr 17, 2013 at 08:13:57PM +0800, Lingzhu Xiang wrote:
> On 04/17/2013 07:56 PM, Andy Whitcroft wrote:
> >On Wed, Apr 17, 2013 at 12:37:43PM +0800, Lingzhu Xiang wrote:
> >>On 04/16/2013 06:33 PM, Luis Henriques wrote:
> >>>68d929862e29a8b52a7f2f2f86a0600423b093cd efi: be more paranoid about available space when creating variables
> >>
> >>This prevents a bricking issue for some Samsung devices but causes
> >>regression on many other machines.
> >>
> >>https://bugzilla.kernel.org/show_bug.cgi?id=55471
> >>https://bugzilla.redhat.com/show_bug.cgi?id=947142
> >>http://article.gmane.org/gmane.linux.kernel.efi/1078
> >>http://article.gmane.org/gmane.linux.kernel.stable/47150
> >>
> >>This patchset will fix it again:
> >>
> >>http://thread.gmane.org/gmane.linux.kernel.efi/1081
> >
> >Thanks for the pointer. I note that in that thread you yourself imply
> >there are still issues after applying them? Was that accurate, is there
> >yet further patches needed?
>
> I just find that issue. Didn't see that when writing the above.
>
> Earlier I was testing on a different machine and the result was
> good. I guess the patch still needs some more testing.
Thanks Lingzhu.
So, I guess you would recommend me to drop the whole series until we
have this patchset accepted, tested and back-ported for 3.5, correct?
(I tried to isolate the one you pointed out, but I'm afraid there are
too many dependencies between them to drop a single patch.)
Cheers,
--
Luis
On 04/17/2013 09:28 PM, Luis Henriques wrote:
> On Wed, Apr 17, 2013 at 08:13:57PM +0800, Lingzhu Xiang wrote:
>> On 04/17/2013 07:56 PM, Andy Whitcroft wrote:
>>> On Wed, Apr 17, 2013 at 12:37:43PM +0800, Lingzhu Xiang wrote:
>>>> On 04/16/2013 06:33 PM, Luis Henriques wrote:
>>>>> 68d929862e29a8b52a7f2f2f86a0600423b093cd efi: be more paranoid about available space when creating variables
>>>>
>>>> This prevents a bricking issue for some Samsung devices but causes
>>>> regression on many other machines.
>>>>
>>>> https://bugzilla.kernel.org/show_bug.cgi?id=55471
>>>> https://bugzilla.redhat.com/show_bug.cgi?id=947142
>>>> http://article.gmane.org/gmane.linux.kernel.efi/1078
>>>> http://article.gmane.org/gmane.linux.kernel.stable/47150
>>>>
>>>> This patchset will fix it again:
>>>>
>>>> http://thread.gmane.org/gmane.linux.kernel.efi/1081
>>>
>>> Thanks for the pointer. I note that in that thread you yourself imply
>>> there are still issues after applying them? Was that accurate, is there
>>> yet further patches needed?
>>
>> I just find that issue. Didn't see that when writing the above.
>>
>> Earlier I was testing on a different machine and the result was
>> good. I guess the patch still needs some more testing.
>
> Thanks Lingzhu.
>
> So, I guess you would recommend me to drop the whole series until we
> have this patchset accepted, tested and back-ported for 3.5, correct?
>
> (I tried to isolate the one you pointed out, but I'm afraid there are
> too many dependencies between them to drop a single patch.)
Unfortunately yes.
The whole series are mostly solving pstore bugs and pstore trashing
firmware. If you want to prevent more bricking from happening asap,
a temporary choice is to allow disabling efi pstore altogether with these:
ed9dc8ce7a1c8115dba9483a9b51df8b63a2e0ef efivars: Allow disabling use as a pstore backend
ec0971ba5372a4dfa753f232449d23a8fd98490e efivars: Add module parameter to disable use as a pstore backend
ca0ba26fbbd2d81c43085df49ce0abfe34535a90 efivars: Fix check for CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE
On Thu, Apr 18, 2013 at 11:27:48AM +0800, Lingzhu Xiang wrote:
> On 04/17/2013 09:28 PM, Luis Henriques wrote:
> > On Wed, Apr 17, 2013 at 08:13:57PM +0800, Lingzhu Xiang wrote:
> >> On 04/17/2013 07:56 PM, Andy Whitcroft wrote:
> >>> On Wed, Apr 17, 2013 at 12:37:43PM +0800, Lingzhu Xiang wrote:
> >>>> On 04/16/2013 06:33 PM, Luis Henriques wrote:
> >>>>> 68d929862e29a8b52a7f2f2f86a0600423b093cd efi: be more paranoid about available space when creating variables
> >>>>
> >>>> This prevents a bricking issue for some Samsung devices but causes
> >>>> regression on many other machines.
> >>>>
> >>>> https://bugzilla.kernel.org/show_bug.cgi?id=55471
> >>>> https://bugzilla.redhat.com/show_bug.cgi?id=947142
> >>>> http://article.gmane.org/gmane.linux.kernel.efi/1078
> >>>> http://article.gmane.org/gmane.linux.kernel.stable/47150
> >>>>
> >>>> This patchset will fix it again:
> >>>>
> >>>> http://thread.gmane.org/gmane.linux.kernel.efi/1081
> >>>
> >>> Thanks for the pointer. I note that in that thread you yourself imply
> >>> there are still issues after applying them? Was that accurate, is there
> >>> yet further patches needed?
> >>
> >> I just find that issue. Didn't see that when writing the above.
> >>
> >> Earlier I was testing on a different machine and the result was
> >> good. I guess the patch still needs some more testing.
> >
> > Thanks Lingzhu.
> >
> > So, I guess you would recommend me to drop the whole series until we
> > have this patchset accepted, tested and back-ported for 3.5, correct?
> >
> > (I tried to isolate the one you pointed out, but I'm afraid there are
> > too many dependencies between them to drop a single patch.)
>
> Unfortunately yes.
>
> The whole series are mostly solving pstore bugs and pstore trashing
> firmware. If you want to prevent more bricking from happening asap,
> a temporary choice is to allow disabling efi pstore altogether with these:
>
> ed9dc8ce7a1c8115dba9483a9b51df8b63a2e0ef efivars: Allow disabling use as a pstore backend
> ec0971ba5372a4dfa753f232449d23a8fd98490e efivars: Add module parameter to disable use as a pstore backend
> ca0ba26fbbd2d81c43085df49ce0abfe34535a90 efivars: Fix check for CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE
Thanks a lot for your help. I'll just pick these and queue them for
3.5.y.
Cheers,
--
Luis