From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751694AbdFFMqI (ORCPT ); Tue, 6 Jun 2017 08:46:08 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:34436 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751660AbdFFMqB (ORCPT ); Tue, 6 Jun 2017 08:46:01 -0400 Date: Tue, 6 Jun 2017 13:45:36 +0100 From: Ben Hutchings To: linux-kernel@vger.kernel.org, Andrew Morton , torvalds@linux-foundation.org, Jiri Slaby , stable@vger.kernel.org Cc: lwn@lwn.net Message-ID: <20170606124536.GC16923@decadent.org.uk> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="5xSkJheCpeK0RUEJ" Content-Disposition: inline X-Mailer: LinuxStableQueue (scripts by bwh) User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: ben@decadent.org.uk Subject: Linux 3.16.44 X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:24:06 +0000) X-SA-Exim-Scanned: Yes (on shadbolt.decadent.org.uk) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --5xSkJheCpeK0RUEJ Content-Type: multipart/mixed; boundary="Km1U/tdNT/EmXiR1" Content-Disposition: inline --Km1U/tdNT/EmXiR1 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable I'm announcing the release of the 3.16.44 kernel. All users of the 3.16 kernel series should upgrade. The updated 3.16.y git tree can be found at: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable= =2Egit linux-3.16.y and can be browsed at the normal kernel.org git web browser: https://git.kernel.org/?p=3Dlinux/kernel/git/stable/linux-stable.git The diff from 3.16.43 is attached to this message. Ben. ------------ Documentation/i2c/muxes/i2c-mux-gpio | 20 +-- Documentation/kernel-parameters.txt | 4 + Makefile | 2 +- arch/arm/include/asm/kvm_mmu.h | 3 +- arch/arm64/include/asm/kvm_mmu.h | 3 +- arch/mips/Makefile | 4 +- arch/mips/bcm47xx/buttons.c | 10 +- arch/mips/cavium-octeon/octeon-memcpy.S | 20 +-- arch/mips/configs/ip27_defconfig | 1 - arch/mips/include/asm/checksum.h | 2 + arch/mips/kernel/process.c | 153 +++++++++++++-------- arch/mips/netlogic/common/smpboot.S | 4 +- arch/powerpc/kernel/hw_breakpoint.c | 4 +- arch/s390/kvm/kvm-s390.c | 3 + arch/x86/include/uapi/asm/hyperv.h | 2 + arch/x86/kernel/pci-calgary_64.c | 2 +- arch/x86/kvm/vmx.c | 2 +- arch/x86/platform/goldfish/goldfish.c | 14 +- arch/xtensa/kernel/setup.c | 4 +- block/blk-mq-tag.c | 44 +++++-- crypto/ahash.c | 79 +++++++---- drivers/base/power/qos.c | 2 +- drivers/bcma/main.c | 4 + drivers/bluetooth/ath3k.c | 2 + drivers/bluetooth/btusb.c | 1 + drivers/char/virtio_console.c | 12 +- drivers/clk/clk-wm831x.c | 3 +- drivers/clk/hisilicon/clkgate-separated.c | 1 + drivers/clk/samsung/clk-s3c2410.c | 4 +- drivers/clk/samsung/clk-s3c2412.c | 4 +- drivers/clk/samsung/clk-s3c2443.c | 4 +- drivers/clk/samsung/clk-s3c64xx.c | 4 +- drivers/clk/shmobile/clk-mstp.c | 6 + drivers/cpufreq/s3c2416-cpufreq.c | 1 - drivers/gpu/drm/ast/ast_post.c | 38 +++++- drivers/gpu/drm/i915/intel_dsi_pll.c | 6 +- drivers/gpu/drm/radeon/radeon_bios.c | 64 +++++---- drivers/gpu/drm/ttm/ttm_bo.c | 4 +- drivers/gpu/drm/ttm/ttm_bo_vm.c | 12 ++ drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 9 +- drivers/hv/channel.c | 15 ++- drivers/hv/channel_mgmt.c | 7 +- drivers/hv/connection.c | 27 +++- drivers/hv/hv.c | 10 +- drivers/hv/hyperv_vmbus.h | 2 +- drivers/i2c/busses/i2c-riic.c | 30 ++++- drivers/iio/pressure/mpl115.c | 1 + drivers/iio/pressure/mpl3115.c | 4 +- drivers/iio/pressure/st_pressure_core.c | 8 +- drivers/infiniband/core/cma.c | 3 + drivers/infiniband/hw/mlx5/qp.c | 29 ++-- drivers/infiniband/hw/mlx5/srq.c | 11 +- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 14 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 21 +-- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 10 +- drivers/iommu/intel-iommu.c | 2 +- drivers/md/dm-cache-target.c | 6 +- drivers/md/linear.c | 29 +++- drivers/md/linear.h | 1 + drivers/md/md.c | 7 + drivers/media/i2c/adv7604.c | 3 + drivers/media/pci/dm1105/Kconfig | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 9 +- drivers/media/usb/uvc/uvc_queue.c | 2 +- drivers/mmc/host/omap_hsmmc.c | 7 +- drivers/net/can/usb/usb_8dev.c | 9 +- drivers/net/ethernet/broadcom/bgmac.c | 6 +- drivers/net/ethernet/mellanox/mlx4/cmd.c | 22 +++- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 6 +- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 8 +- drivers/net/ethernet/mellanox/mlx4/main.c | 2 - drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 +- drivers/net/ethernet/sfc/efx.c | 10 +- drivers/net/ethernet/sfc/efx.h | 6 + drivers/net/ethernet/sfc/selftest.c | 2 +- drivers/net/vxlan.c | 2 +- drivers/net/wireless/adm8211.c | 3 +- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 3 +- drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 4 +- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/mac.c | 44 +++++-- drivers/net/wireless/ath/ath9k/mac.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 27 ++-- drivers/net/wireless/iwlwifi/mvm/rs.c | 4 +- drivers/net/wireless/mwifiex/debugfs.c | 3 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 2 - drivers/platform/goldfish/pdev_bus.c | 13 +- drivers/platform/x86/acer-wmi.c | 22 +++- drivers/power/bq24190_charger.c | 175 ++++++++++-----------= ---- drivers/s390/cio/ioasm.h | 8 +- drivers/s390/cio/qdio_thinint.c | 8 +- drivers/scsi/aacraid/commsup.c | 36 ++--- drivers/scsi/aacraid/src.c | 21 ++- drivers/scsi/storvsc_drv.c | 37 +++++- drivers/staging/rtl8188eu/core/rtw_recv.c | 4 + drivers/staging/rtl8192ee/rtl8192ee/hw.c | 2 +- drivers/staging/rtl8712/rtl871x_recv.c | 7 +- drivers/staging/rtl8821ae/rtl8821ae/hw.c | 2 +- drivers/staging/wlan-ng/p80211netdev.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 36 +++-- drivers/tty/serial/msm_serial.c | 1 + drivers/usb/dwc3/gadget.c | 6 + drivers/usb/gadget/f_hid.c | 101 ++++++++++---- drivers/usb/gadget/f_midi.c | 6 - drivers/usb/gadget/f_sourcesink.c | 6 - drivers/usb/gadget/g_zero.h | 1 - drivers/usb/gadget/u_f.c | 1 - drivers/usb/gadget/u_f.h | 10 +- drivers/usb/misc/adutux.c | 4 - drivers/usb/misc/iowarrior.c | 13 +- drivers/usb/serial/ark3116.c | 38 ++++-- drivers/usb/serial/ch341.c | 27 ++-- drivers/usb/serial/cp210x.c | 2 + drivers/usb/serial/digi_acceleport.c | 52 +++++--- drivers/usb/serial/ftdi_sio.c | 38 ++++-- drivers/usb/serial/io_edgeport.c | 48 ++++--- drivers/usb/serial/io_ti.c | 2 +- drivers/usb/serial/keyspan_pda.c | 19 ++- drivers/usb/serial/mct_u232.c | 6 +- drivers/usb/serial/mos7840.c | 4 +- drivers/usb/serial/omninet.c | 6 - drivers/usb/serial/opticon.c | 2 +- drivers/usb/serial/quatech2.c | 24 ++-- drivers/usb/serial/sierra.c | 28 +--- drivers/usb/serial/spcp8x5.c | 8 +- drivers/usb/serial/ssu100.c | 31 ++++- drivers/usb/serial/ti_usb_3410_5052.c | 12 +- drivers/w1/masters/ds2490.c | 141 ++++++++++++-------- drivers/w1/w1.c | 1 + fs/ext4/inline.c | 75 +++++------ fs/ext4/inode.c | 69 ++++++++-- fs/ext4/mballoc.c | 7 + fs/ext4/super.c | 11 +- fs/ext4/xattr.c | 35 ++--- fs/ext4/xattr.h | 32 +++++ fs/f2fs/f2fs.h | 3 + fs/f2fs/gc.c | 28 +++- fs/f2fs/segment.c | 13 +- fs/f2fs/segment.h | 9 ++ fs/fuse/file.c | 1 + fs/jbd2/transaction.c | 4 +- fs/nfs/nfs4proc.c | 10 +- fs/nfs/nfs4xdr.c | 4 +- fs/nfsd/nfs3xdr.c | 12 +- fs/nfsd/nfssvc.c | 36 +++++ fs/nfsd/nfsxdr.c | 10 +- fs/nfsd/vfs.c | 63 ++++++--- include/crypto/internal/hash.h | 10 ++ include/linux/jump_label.h | 20 +++ include/linux/lockd/lockd.h | 3 +- include/linux/mlx4/cmd.h | 2 +- include/linux/mlx4/driver.h | 10 ++ include/linux/pagemap.h | 1 - include/linux/ww_mutex.h | 8 +- include/rdma/ib_sa.h | 6 +- kernel/sched/core.c | 6 +- kernel/trace/trace.c | 2 +- mm/filemap.c | 7 +- mm/huge_memory.c | 2 +- mm/mempolicy.c | 20 ++- mm/page_alloc.c | 2 +- mm/vmpressure.c | 10 +- net/batman-adv/fragmentation.c | 16 ++- net/batman-adv/routing.c | 8 +- net/core/dev.c | 35 ++++- net/dccp/ipv4.c | 6 + net/dccp/ipv6.c | 12 ++ net/ipv4/inet_connection_sock.c | 2 + net/ipv4/ping.c | 5 +- net/ipv4/route.c | 1 + net/ipv4/tcp_minisocks.c | 3 +- net/ipv6/ip6_offload.c | 7 +- net/ipv6/ip6_output.c | 20 +-- net/ipv6/output_core.c | 14 +- net/ipv6/route.c | 2 + net/ipv6/tcp_ipv6.c | 2 + net/ipv6/udp_offload.c | 6 +- net/ipx/af_ipx.c | 5 +- net/l2tp/l2tp_core.c | 4 +- net/mac80211/pm.c | 1 + net/packet/af_packet.c | 8 +- net/sched/act_api.c | 5 +- net/sctp/ipv6.c | 3 + net/xfrm/xfrm_user.c | 9 +- samples/seccomp/bpf-helper.h | 125 ++++++++++-------- security/keys/encrypted-keys/encrypted.c | 2 +- security/keys/keyctl.c | 24 ++-- security/keys/process_keys.c | 44 ++++--- sound/core/seq/seq_fifo.c | 3 + sound/core/timer.c | 18 ++- sound/pci/ctxfi/cthw20k1.c | 19 +-- sound/pci/ctxfi/cthw20k2.c | 18 +-- sound/soc/codecs/rt5640.c | 4 +- tools/perf/Documentation/perf-script.txt | 4 +- tools/perf/tests/parse-events.c | 6 +- tools/perf/util/evlist.c | 2 +- tools/testing/ktest/ktest.pl | 2 +- 198 files changed, 1922 insertions(+), 1055 deletions(-) Alex Deucher (1): drm/radeon: handle vfct with multiple vbios images Alexander Stein (1): W1: ds2490: Increase timeout when waiting for status Alexey Kodanev (1): tcp: account for ts offset only if tsecr not zero Amey Telawane (1): tracing: Use strlcpy() instead of strcpy() in __trace_find_cmdline() Andrey Konovalov (3): net/packet: fix overflow in check for priv area size net/packet: fix overflow in check for tp_frame_nr net/packet: fix overflow in check for tp_reserve Andrey Ryabinin (1): net/dccp: fix use after free in tw_timer_handler() Andy Whitcroft (2): xfrm_user: validate XFRM_MSG_NEWAE XFRMA_REPLAY_ESN_VAL replay_window xfrm_user: validate XFRM_MSG_NEWAE incoming ESN size harder Arnaldo Carvalho de Melo (1): perf tests: Avoid possible truncation with dirent->d_name + snprintf Arnd Bergmann (4): staging: rtl: fix possible NULL pointer dereference MIPS: 'make -s' should be silent MIPS: ip27: Disable qlge driver in defconfig dvb-usb-v2: avoid use-after-free Bart Van Assche (1): blk-mq: Make bt_clear_tag() easier to read Ben Hutchings (1): Linux 3.16.44 Brian Norris (1): mwifiex: debugfs: Fix (sometimes) off-by-1 SSID print Chao Peng (1): KVM: VMX: use correct vmcs_read/write for guest segment selector/base Chao Yu (1): f2fs: use for_each_set_bit to simplify the code Chris Brandt (2): i2c: riic: correctly finish transfers clk: renesas: mstp: ensure register writes complete Chris Salls (1): mm/mempolicy.c: fix error handling in set_mempolicy and mbind. Chris Wilson (1): locking/ww_mutex: Fix compilation of __WW_MUTEX_INITIALIZER Christian Lamparter (1): ath9k: use correct OTP register offsets for the AR9340 and AR9550 Christoph Hellwig (3): nfsd: update mtime on truncate nfsd: minor nfsd_setattr cleanup nfsd: special case truncates some more Colin Ian King (1): usb: misc: adutux: remove redundant error check on copy_to_user retur= n code Craig Gallek (1): ipv6: Prevent overrun when parsing v6 header options Dan Carpenter (5): adm80211: return an error if adm8211_alloc_rings() fails cpufreq: s3c2416: double free on driver init error path KEYS: Fix an error code in request_master_key() net/mlx4: && vs & typo ipx: call ipxitf_put() in ioctl error path David Dillow (1): iommu/vt-d: Don't over-free page table directories David Howells (2): KEYS: Reinstate EPERM for a key type name beginning with a '.' KEYS: Disallow keyrings beginning with '.' to be joined as session ke= yrings David S. Miller (1): ipv6: Check ip6_find_1stfragopt() return value properly. Dexuan Cui (1): hv: vmbus_post_msg: retry the hypercall on some transient errors Dmitry Tunin (1): Bluetooth: Add another AR3012 04ca:3018 device Eli Cohen (1): IB/mlx5: Fix retrieval of index to first hi class bfreg Eric Biggers (1): KEYS: fix keyctl_set_reqkey_keyring() to not leak thread keyrings Eric Dumazet (7): mlx4: reduce OOM risk on arches with large pages net/mlx4_en: Use __skb_fill_page_desc() net: net_enable_timestamp() can be called from irq contexts ping: implement proper locking dccp/tcp: do not inherit mc_list from parent sctp: do not inherit ipv6_{mc|ac|fl}_list from parent ipv6: fix out of bound writes in __ip6_append_data() Eugenia Emantayev (1): net/mlx4: Spoofcheck and zero MAC can't coexist Felipe Balbi (1): usb: dwc3: gadget: skip Set/Clear Halt when invalid Felipe F. Tonello (1): usb: gadget: define free_ep_req as universal function Felix Fietkau (2): ath5k: drop bogus warning on drv_set_key with unsupported cipher ath9k: fix race condition in enabling/disabling IRQs Feras Daoud (6): IB/ipoib: Set device connection mode only when needed IB/ipoib: Fix deadlock over vlan_mutex IB/ipoib: Fix deadlock between rmmod and set_mode IB/ipoib: rtnl_unlock can not come after free_netdev IB/ipoib: Replace list_del of the neigh->list with list_del_init IB/ipoib: Change list_del to list_del_init in the tx object Ganapathi Bhat (1): mwifiex: Avoid skipping WEP key deletion for AP Gavin Shan (1): mm/page_alloc: fix nodes for reclaim in fast path Guennadi Liakhovetski (1): uvcvideo: Fix a wrong macro Haiyang Zhang (1): hv_vmbus: Add gradually increased delay for retries in vmbus_post_msg= () Hari Vyas (1): net: ethernet: bgmac: mac address change bug Herbert Xu (1): crypto: ahash - Fix EINPROGRESS notification callback Hou Pengyang (1): f2fs: add ovp valid_blocks check for bg gc victim to fg_gc Ian Abbott (1): serial: 8250_pci: Add MKS Tenta SCOM-0800 and SCOM-0801 cards Igor Pylypiv (1): staging: wlan-ng: add missing byte order conversion J. Bruce Fields (4): NFSv4: fix getacl head length estimation nfsd: check for oversized NFSv2/v3 arguments nfsd4: minor NFSv2/v3 write decoding cleanup nfsd: stricter decoding of write-like NFSv2/v3 ops James Cowgill (1): MIPS: OCTEON: Fix copy_from_user fault handling for large buffers Jan Kara (3): ext4: avoid deadlock when expanding inode size ext4: trim allocation requests to group size ext4: fix data corruption in data=3Djournal mode Jan Kiszka (1): serial: exar: Fix initialization of EXAR registers for ports > 0 Janosch Frank (1): KVM: s390: Disable dirty log retrieval for UCONTROL guests Jason Gunthorpe (1): RDMA/core: Fix incorrect structure packing for booleans Javier Martinez Canillas (1): tty: serial: msm: Fix module autoload Joe Thornber (1): dm cache: fix corruption seen when using cache > 2TB Johan Hovold (23): USB: serial: ch341: fix modem-status handling USB: serial: ark3116: fix register-accessor error handling USB: serial: ark3116: fix open error handling USB: serial: ftdi_sio: fix modem-status error handling USB: serial: ftdi_sio: fix latency-timer error handling USB: serial: io_edgeport: fix epic-descriptor handling USB: serial: io_edgeport: fix descriptor error handling USB: serial: mct_u232: fix modem-status error handling USB: serial: quatech2: fix control-message error handling USB: serial: spcp8x5: fix modem-status handling USB: serial: ssu100: fix control-message error handling USB: serial: ti_usb_3410_5052: fix control-message error handling USB: serial: opticon: fix CTS retrieval at open USB: serial: ftdi_sio: fix extreme low-latency setting USB: serial: digi_acceleport: fix OOB data sanity check USB: serial: digi_acceleport: fix incomplete rx sanity check USB: serial: keyspan_pda: fix receive sanity checks USB: serial: ftdi_sio: fix line-status over-reporting USB: serial: sierra: fix bogus alternate-setting assumption USB: serial: mos7840: fix another NULL-deref at open USB: iowarrior: fix NULL-deref at probe USB: serial: io_ti: fix information leak in completion handler USB: serial: omninet: fix reference leaks at open John Keeping (1): PM / QoS: Fix memory leak on resume_latency.notifiers Julian Anastasov (1): ipv4: mask tos for input route Julian Wiedmann (1): s390/qdio: clear DSCI prior to scanning multiple input queues K. Y. Srinivasan (3): scsi: storvsc: Fix a bug in the handling of SRB status flags Drivers: hv: vmbus: Reduce the delay between retries in vmbus_post_ms= g() drivers: hv: Turn off write permission on the hypercall page Ken Lin (1): USB: serial: cp210x: add new IDs for GE Bx50v3 boards Kirtika Ruchandani (1): iwlwifi: mvm: rs: Remove unused 'mcs' variable Krzysztof Opasiak (3): usb: gadget: f_hid: fix: Free out requests usb: gadget: f_hid: fix: Prevent accessing released memory usb: gadget: f_hid: Use spinlock instead of mutex Lars-Peter Clausen (1): adv7604: Initialize drive strength to default when using DT Lee, Chun-Yi (1): platform/x86: acer-wmi: setup accelerometer when machine has appropri= ate notify event Leo Yan (1): clk: hisilicon: fix lock assignment Leon Romanovsky (2): IB/mlx5: Fix out-of-bound access IB/mlx5: Return error for unsupported signature type Li Qiang (1): drm/vmwgfx: fix integer overflow in vmw_surface_define_ioctl() Liam Breck (6): power: supply: bq24190_charger: Fix irq trigger to IRQF_TRIGGER_FALLI= NG power: supply: bq24190_charger: Call set_mode_host() on pm_resume() power: supply: bq24190_charger: Install irq_handler_thread() at end o= f probe() power: supply: bq24190_charger: Call power_supply_changed() for relev= ant component power: supply: bq24190_charger: Don't read fault register outside irq= _handle_thread() power: supply: bq24190_charger: Handle fault before status on interru= pt Linus L=C3=BCssing (1): batman-adv: Fix transmission of final, 16th fragment Long Li (3): scsi: storvsc: use tagged SRB requests if supported by the device scsi: storvsc: properly handle SRB_ERROR when sense message is present scsi: storvsc: properly set residual data length on errors Maciej S. Szmigiero (2): w1: ds2490: USB transfer buffers need to be DMAable w1: don't leak refcount on slave attach failure in w1_attach_slave_de= vice() Majd Dibbiny (1): net/mlx4_core: Fix VF overwrite of module param which disables DMFS o= n new probed PFs Mantas M (1): net: ipv6: check route protocol when deleting routes Marc Kleine-Budde (1): can: usb_8dev: Fix memory leak of priv->cmd_msg_buffer Marc Zyngier (1): arm/arm64: KVM: Enforce unconditional flush to PoC when mapping to st= age-2 Marcin Niestroj (1): iio: st_pressure: Fix data sign Martin Kaiser (1): clk: samsung: mark s3c...._clk_sleep_init() as __init Mathias Svensson (1): samples/seccomp: fix 64-bit comparison macros Matt Chen (1): mac80211: flush delayed work when entering suspend Matthias Schiffer (1): vxlan: correctly validate VXLAN ID against VXLAN_N_VID Max Filippov (1): xtensa: move parse_tag_fdt out of #ifdef CONFIG_BLK_DEV_INITRD Michael Petlan (1): perf script: Fix man page about --dump-raw-trace option Michal Hocko (1): mm/huge_memory.c: fix up "mm/huge_memory.c: respect FOLL_FORCE/FOLL_C= OW for thp" backport Michel D=C3=A4nzer (1): drm/ttm: Make sure BOs being swapped out are cacheable Miklos Szeredi (1): fuse: add missing FR_FORCE Mimi Zohar (1): KEYS: special dot prefixed keyring name bug fix Minchan Kim (1): mm: do not access page->mapping directly on page_endio Mirko Parthey (1): MIPS: BCM47XX: Fix button inversion for Asus WL-500W Murray McAllister (1): drm/vmwgfx: NULL pointer dereference in vmw_surface_define_ioctl() NeilBrown (1): md: ensure md devices are freed before module is unloaded. Nicholas Mc Guire (3): drm/i915: relax uncritical udelay_range() clk: wm831x: fix usleep_range with bad range ASoC: rt5640: use msleep() for long delays Nicolai H=C3=A4hnle (1): drm/ttm: fix use-after-free races in vm fault handling Nikola Pajkovsky (1): x86/pci-calgary: Fix iommu_free() comparison of unsigned expression >= =3D 0 Omar Sandoval (2): sbitmap: fix wakeup hang after sbq resize virtio-console: avoid DMA from stack Paul Burton (7): MIPS: Clear ISA bit correctly in get_frame_info() MIPS: Prevent unaligned accesses during stack unwinding MIPS: Fix get_frame_info() handling of microMIPS function size MIPS: Fix is_jump_ins() handling of 16b microMIPS instructions MIPS: Calculate microMIPS ra properly when unwinding the stack MIPS: Handle microMIPS jumps in the same way as MIPS32/MIPS64 jumps MIPS: Netlogic: Fix assembler warning from smpboot.S Peter Dunning (1): sfc: do not device_attach if a reset is pending Peter Oberparleiter (1): s390/chsc: Add exception handler for CHSC instruction Peter Rosin (3): i2c: i2c-mux-gpio: rename i2c-gpio-mux to i2c-mux-gpio iio: pressure: mpl3115: do not rely on structure field ordering iio: pressure: mpl115: do not rely on structure field ordering Peter Zijlstra (1): locking/static_keys: Add static_key_{en,dis}able() helpers Ping-Ke Shih (1): rtlwifi: Fix alignment issues Rafa=C5=82 Mi=C5=82ecki (1): bcma: use (get|put)_device when probing/removing device driver Raghava Aditya Renukunta (2): scsi: aacraid: Fix memory leak in fib init path scsi: aacraid: Reorder Adapter status check Ralf Baechle (1): MIPS: Fix special case in 64 bit IP checksumming. Randy Dunlap (2): media: fix dm1105.c build error mm: fix stray kernel-doc notation Ravi Bangoria (1): powerpc/xmon: Fix data-breakpoint Ravikumar Kattekola (1): mmc: host: omap_hsmmc: avoid possible overflow of timeout value Ridge Kennedy (1): l2tp: Avoid schedule while atomic in exit_net Roman Mashak (1): net sched actions: decrement module reference count after table flush. Soramichi Akiyama (1): perf evlist: Fix typo in perf_evlist__start_workload() Steve Wise (1): rdma_cm: fail iwarp accepts w/o connection params Steven Rostedt (VMware) (1): ktest: Fix child exit code processing Sven Eckelmann (1): batman-adv: Fix double free during fragment merge error Takashi Iwai (3): ALSA: timer: Reject user params with too small ticks ALSA: ctxfi: Fallback DMA mask to 32bit ALSA: seq: Fix link corruption by event error handling Theodore Ts'o (7): ext4: fix deadlock between inline_data and ext4_expand_extra_isize_ea= () ext4: use private version of page_zero_new_buffers() for data=3Djourn= al mode ext4: fix inline data error paths jbd2: don't leak modified metadata buffers on an aborted journal ext4: preserve the needs_recovery flag when the journal is aborted ext4: return EROFS if device is r/o and journal replay is needed ext4: fix fencepost in s_first_meta_bg validation Thomas Elste (1): power: bq24190_charger: Change first_time flag reset condition Thomas Gleixner (2): x86/platform/goldfish: Prevent unconditional loading goldfish: Sanitize the broken interrupt handler Trond Myklebust (3): NFSv4: Fix memory and state leak in _nfs4_open_and_get_state nlm: Ensure callback code also checks that the files match NFSv4: Fix the underestimation of delegation XDR space reservation Vinayak Menon (1): mm: vmpressure: fix sending wrong events on underflow Vitaly Kuznetsov (3): Drivers: hv: vmbus: Raise retry/wait limits in vmbus_post_msg() hv: allocate synic pages for all present CPUs hv: init percpu_list in hv_synic_alloc() WANG Cong (1): ipv6/dccp: do not inherit ipv6_mc_list from parent Weston Andros Adamson (1): NFSv4: fix getacl ERANGE for some ACL buffer sizes Y.C. Chen (1): drm/ast: Fix AST2400 POST failure without BMC FW or VBIOS colyli@suse.de (1): md linear: fix a race between linear_add() and linear_congested() --Km1U/tdNT/EmXiR1 Content-Type: text/x-diff; charset=UTF-8; name="linux-3.16.44.patch" Content-Disposition: attachment; filename="linux-3.16.44.patch" Content-Transfer-Encoding: quoted-printable diff --git a/Documentation/i2c/muxes/i2c-mux-gpio b/Documentation/i2c/muxes= /i2c-mux-gpio index d4d91a53fc39..7a8d7d261632 100644 --- a/Documentation/i2c/muxes/i2c-mux-gpio +++ b/Documentation/i2c/muxes/i2c-mux-gpio @@ -1,11 +1,11 @@ -Kernel driver i2c-gpio-mux +Kernel driver i2c-mux-gpio =20 Author: Peter Korsgaard =20 Description ----------- =20 -i2c-gpio-mux is an i2c mux driver providing access to I2C bus segments +i2c-mux-gpio is an i2c mux driver providing access to I2C bus segments from a master I2C bus and a hardware MUX controlled through GPIO pins. =20 E.G.: @@ -26,16 +26,16 @@ according to the settings of the GPIO pins 1..N. Usage ----- =20 -i2c-gpio-mux uses the platform bus, so you need to provide a struct +i2c-mux-gpio uses the platform bus, so you need to provide a struct platform_device with the platform_data pointing to a struct -gpio_i2cmux_platform_data with the I2C adapter number of the master +i2c_mux_gpio_platform_data with the I2C adapter number of the master bus, the number of bus segments to create and the GPIO pins used -to control it. See include/linux/i2c-gpio-mux.h for details. +to control it. See include/linux/i2c-mux-gpio.h for details. =20 E.G. something like this for a MUX providing 4 bus segments controlled through 3 GPIO pins: =20 -#include +#include #include =20 static const unsigned myboard_gpiomux_gpios[] =3D { @@ -46,7 +46,7 @@ static const unsigned myboard_gpiomux_values[] =3D { 0, 1, 2, 3 }; =20 -static struct gpio_i2cmux_platform_data myboard_i2cmux_data =3D { +static struct i2c_mux_gpio_platform_data myboard_i2cmux_data =3D { .parent =3D 1, .base_nr =3D 2, /* optional */ .values =3D myboard_gpiomux_values, @@ -57,7 +57,7 @@ static struct gpio_i2cmux_platform_data myboard_i2cmux_da= ta =3D { }; =20 static struct platform_device myboard_i2cmux =3D { - .name =3D "i2c-gpio-mux", + .name =3D "i2c-mux-gpio", .id =3D 0, .dev =3D { .platform_data =3D &myboard_i2cmux_data, @@ -66,14 +66,14 @@ static struct platform_device myboard_i2cmux =3D { =20 If you don't know the absolute GPIO pin numbers at registration time, you can instead provide a chip name (.chip_name) and relative GPIO pin -numbers, and the i2c-gpio-mux driver will do the work for you, +numbers, and the i2c-mux-gpio driver will do the work for you, including deferred probing if the GPIO chip isn't immediately available. =20 Device Registration ------------------- =20 -When registering your i2c-gpio-mux device, you should pass the number +When registering your i2c-mux-gpio device, you should pass the number of any GPIO pin it uses as the device ID. This guarantees that every instance has a different ID. =20 diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-par= ameters.txt index 590bf00677a5..cb76a3cf0763 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1115,6 +1115,10 @@ bytes respectively. Such letter suffixes can also be= entirely omitted. When zero, profiling data is discarded and associated debugfs files are removed at module unload time. =20 + goldfish [X86] Enable the goldfish android emulator platform. + Don't use this when you are not running on the + android emulator + gpt [EFI] Forces disk with valid GPT signature but invalid Protective MBR to be treated as GPT. If the primary GPT is corrupted, it enables the backup/alternate diff --git a/Makefile b/Makefile index 28b1d5eed2c5..1680e3f85a06 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION =3D 3 PATCHLEVEL =3D 16 -SUBLEVEL =3D 43 +SUBLEVEL =3D 44 EXTRAVERSION =3D NAME =3D Museum of Fishiegoodies =20 diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 8618badbbbbe..f4cef021db1e 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -142,8 +142,7 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vc= pu *vcpu) static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t = hva, unsigned long size) { - if (!vcpu_has_cache_enabled(vcpu)) - kvm_flush_dcache_to_poc((void *)hva, size); + kvm_flush_dcache_to_poc((void *)hva, size); =09 /* * If we are going to insert an instruction page and the icache is diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_= mmu.h index 2067f4b75d13..7758e0f478a3 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h @@ -141,8 +141,7 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vc= pu *vcpu) static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t = hva, unsigned long size) { - if (!vcpu_has_cache_enabled(vcpu)) - kvm_flush_dcache_to_poc((void *)hva, size); + kvm_flush_dcache_to_poc((void *)hva, size); =20 if (!icache_is_aliasing()) { /* PIPT */ flush_icache_range(hva, hva + size); diff --git a/arch/mips/Makefile b/arch/mips/Makefile index d964dcf0762b..9032706c0a32 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -333,11 +333,11 @@ CLEAN_FILES +=3D vmlinux.32 vmlinux.64 =20 archprepare: ifdef CONFIG_MIPS32_N32 - @echo ' Checking missing-syscalls for N32' + @$(kecho) ' Checking missing-syscalls for N32' $(Q)$(MAKE) $(build)=3D. missing-syscalls missing_syscalls_flags=3D"-mabi= =3Dn32" endif ifdef CONFIG_MIPS32_O32 - @echo ' Checking missing-syscalls for O32' + @$(kecho) ' Checking missing-syscalls for O32' $(Q)$(MAKE) $(build)=3D. missing-syscalls missing_syscalls_flags=3D"-mabi= =3D32" endif =20 diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c index 49a1ce06844b..64124e3e54b5 100644 --- a/arch/mips/bcm47xx/buttons.c +++ b/arch/mips/bcm47xx/buttons.c @@ -17,6 +17,12 @@ .active_low =3D 1, \ } =20 +#define BCM47XX_GPIO_KEY_H(_gpio, _code) \ + { \ + .code =3D _code, \ + .gpio =3D _gpio, \ + } + /* Asus */ =20 static const struct gpio_keys_button @@ -74,8 +80,8 @@ bcm47xx_buttons_asus_wl500gpv2[] __initconst =3D { =20 static const struct gpio_keys_button bcm47xx_buttons_asus_wl500w[] __initconst =3D { - BCM47XX_GPIO_KEY(6, KEY_RESTART), - BCM47XX_GPIO_KEY(7, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY_H(6, KEY_RESTART), + BCM47XX_GPIO_KEY_H(7, KEY_WPS_BUTTON), }; =20 static const struct gpio_keys_button diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-oct= eon/octeon-memcpy.S index 64e08df51d65..8b7004132491 100644 --- a/arch/mips/cavium-octeon/octeon-memcpy.S +++ b/arch/mips/cavium-octeon/octeon-memcpy.S @@ -208,18 +208,18 @@ EXC( STORE t2, UNIT(6)(dst), s_exc_p10u) ADD src, src, 16*NBYTES EXC( STORE t3, UNIT(7)(dst), s_exc_p9u) ADD dst, dst, 16*NBYTES -EXC( LOAD t0, UNIT(-8)(src), l_exc_copy) -EXC( LOAD t1, UNIT(-7)(src), l_exc_copy) -EXC( LOAD t2, UNIT(-6)(src), l_exc_copy) -EXC( LOAD t3, UNIT(-5)(src), l_exc_copy) +EXC( LOAD t0, UNIT(-8)(src), l_exc_copy_rewind16) +EXC( LOAD t1, UNIT(-7)(src), l_exc_copy_rewind16) +EXC( LOAD t2, UNIT(-6)(src), l_exc_copy_rewind16) +EXC( LOAD t3, UNIT(-5)(src), l_exc_copy_rewind16) EXC( STORE t0, UNIT(-8)(dst), s_exc_p8u) EXC( STORE t1, UNIT(-7)(dst), s_exc_p7u) EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u) EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u) -EXC( LOAD t0, UNIT(-4)(src), l_exc_copy) -EXC( LOAD t1, UNIT(-3)(src), l_exc_copy) -EXC( LOAD t2, UNIT(-2)(src), l_exc_copy) -EXC( LOAD t3, UNIT(-1)(src), l_exc_copy) +EXC( LOAD t0, UNIT(-4)(src), l_exc_copy_rewind16) +EXC( LOAD t1, UNIT(-3)(src), l_exc_copy_rewind16) +EXC( LOAD t2, UNIT(-2)(src), l_exc_copy_rewind16) +EXC( LOAD t3, UNIT(-1)(src), l_exc_copy_rewind16) EXC( STORE t0, UNIT(-4)(dst), s_exc_p4u) EXC( STORE t1, UNIT(-3)(dst), s_exc_p3u) EXC( STORE t2, UNIT(-2)(dst), s_exc_p2u) @@ -383,6 +383,10 @@ done: nop END(memcpy) =20 +l_exc_copy_rewind16: + /* Rewind src and dst by 16*NBYTES for l_exc_copy */ + SUB src, src, 16*NBYTES + SUB dst, dst, 16*NBYTES l_exc_copy: /* * Copy bytes from src until faulting load address (or until a diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defc= onfig index 0e36abcd39cc..7446284dd7b3 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -206,7 +206,6 @@ CONFIG_MLX4_EN=3Dm # CONFIG_MLX4_DEBUG is not set CONFIG_TEHUTI=3Dm CONFIG_BNX2X=3Dm -CONFIG_QLGE=3Dm CONFIG_SFC=3Dm CONFIG_BE2NET=3Dm CONFIG_LIBERTAS_THINFIRM=3Dm diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/check= sum.h index 3418c51e1151..8e01b0215070 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -185,7 +185,9 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, " daddu %0, %4 \n" " dsll32 $1, %0, 0 \n" " daddu %0, $1 \n" + " sltu $1, %0, $1 \n" " dsra32 %0, %0, 0 \n" + " addu %0, $1 \n" #endif " .set pop" : "=3Dr" (sum) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index f206dd3c1b4f..6e90bf52b95b 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -223,11 +223,9 @@ struct mips_frame_info { #define J_TARGET(pc,target) \ (((unsigned long)(pc) & 0xf0000000) | ((target) << 2)) =20 -static inline int is_ra_save_ins(union mips_instruction *ip) +static inline int is_ra_save_ins(union mips_instruction *ip, int *poff) { #ifdef CONFIG_CPU_MICROMIPS - union mips_instruction mmi; - /* * swsp ra,offset * swm16 reglist,offset(sp) @@ -237,29 +235,71 @@ static inline int is_ra_save_ins(union mips_instructi= on *ip) * * microMIPS is way more fun... */ - if (mm_insn_16bit(ip->halfword[0])) { - mmi.word =3D (ip->halfword[0] << 16); - return ((mmi.mm16_r5_format.opcode =3D=3D mm_swsp16_op && - mmi.mm16_r5_format.rt =3D=3D 31) || - (mmi.mm16_m_format.opcode =3D=3D mm_pool16c_op && - mmi.mm16_m_format.func =3D=3D mm_swm16_op)); + if (mm_insn_16bit(ip->halfword[1])) { + switch (ip->mm16_r5_format.opcode) { + case mm_swsp16_op: + if (ip->mm16_r5_format.rt !=3D 31) + return 0; + + *poff =3D ip->mm16_r5_format.simmediate; + *poff =3D (*poff << 2) / sizeof(ulong); + return 1; + + case mm_pool16c_op: + switch (ip->mm16_m_format.func) { + case mm_swm16_op: + *poff =3D ip->mm16_m_format.imm; + *poff +=3D 1 + ip->mm16_m_format.rlist; + *poff =3D (*poff << 2) / sizeof(ulong); + return 1; + + default: + return 0; + } + + default: + return 0; + } } - else { - mmi.halfword[0] =3D ip->halfword[1]; - mmi.halfword[1] =3D ip->halfword[0]; - return ((mmi.mm_m_format.opcode =3D=3D mm_pool32b_op && - mmi.mm_m_format.rd > 9 && - mmi.mm_m_format.base =3D=3D 29 && - mmi.mm_m_format.func =3D=3D mm_swm32_func) || - (mmi.i_format.opcode =3D=3D mm_sw32_op && - mmi.i_format.rs =3D=3D 29 && - mmi.i_format.rt =3D=3D 31)); + + switch (ip->i_format.opcode) { + case mm_sw32_op: + if (ip->i_format.rs !=3D 29) + return 0; + if (ip->i_format.rt !=3D 31) + return 0; + + *poff =3D ip->i_format.simmediate / sizeof(ulong); + return 1; + + case mm_pool32b_op: + switch (ip->mm_m_format.func) { + case mm_swm32_func: + if (ip->mm_m_format.rd < 0x10) + return 0; + if (ip->mm_m_format.base !=3D 29) + return 0; + + *poff =3D ip->mm_m_format.simmediate; + *poff +=3D (ip->mm_m_format.rd & 0xf) * sizeof(u32); + *poff /=3D sizeof(ulong); + return 1; + default: + return 0; + } + + default: + return 0; } #else /* sw / sd $ra, offset($sp) */ - return (ip->i_format.opcode =3D=3D sw_op || ip->i_format.opcode =3D=3D sd= _op) && - ip->i_format.rs =3D=3D 29 && - ip->i_format.rt =3D=3D 31; + if ((ip->i_format.opcode =3D=3D sw_op || ip->i_format.opcode =3D=3D sd_op= ) && + ip->i_format.rs =3D=3D 29 && ip->i_format.rt =3D=3D 31) { + *poff =3D ip->i_format.simmediate / sizeof(ulong); + return 1; + } + + return 0; #endif } =20 @@ -274,13 +314,16 @@ static inline int is_jump_ins(union mips_instruction = *ip) * * microMIPS is kind of more fun... */ - union mips_instruction mmi; - - mmi.word =3D (ip->halfword[0] << 16); + if (mm_insn_16bit(ip->halfword[1])) { + if ((ip->mm16_r5_format.opcode =3D=3D mm_pool16c_op && + (ip->mm16_r5_format.rt & mm_jr16_op) =3D=3D mm_jr16_op)) + return 1; + return 0; + } =20 - if ((mmi.mm16_r5_format.opcode =3D=3D mm_pool16c_op && - (mmi.mm16_r5_format.rt & mm_jr16_op) =3D=3D mm_jr16_op) || - ip->j_format.opcode =3D=3D mm_jal32_op) + if (ip->j_format.opcode =3D=3D mm_j32_op) + return 1; + if (ip->j_format.opcode =3D=3D mm_jal32_op) return 1; if (ip->r_format.opcode !=3D mm_pool32a_op || ip->r_format.func !=3D mm_pool32axf_op) @@ -308,15 +351,13 @@ static inline int is_sp_move_ins(union mips_instructi= on *ip) * * microMIPS is not more fun... */ - if (mm_insn_16bit(ip->halfword[0])) { - union mips_instruction mmi; - - mmi.word =3D (ip->halfword[0] << 16); - return ((mmi.mm16_r3_format.opcode =3D=3D mm_pool16d_op && - mmi.mm16_r3_format.simmediate && mm_addiusp_func) || - (mmi.mm16_r5_format.opcode =3D=3D mm_pool16d_op && - mmi.mm16_r5_format.rt =3D=3D 29)); + if (mm_insn_16bit(ip->halfword[1])) { + return (ip->mm16_r3_format.opcode =3D=3D mm_pool16d_op && + ip->mm16_r3_format.simmediate && mm_addiusp_func) || + (ip->mm16_r5_format.opcode =3D=3D mm_pool16d_op && + ip->mm16_r5_format.rt =3D=3D 29); } + return (ip->mm_i_format.opcode =3D=3D mm_addiu32_op && ip->mm_i_format.rt =3D=3D 29 && ip->mm_i_format.rs =3D=3D 29); #else @@ -331,30 +372,36 @@ static inline int is_sp_move_ins(union mips_instructi= on *ip) =20 static int get_frame_info(struct mips_frame_info *info) { -#ifdef CONFIG_CPU_MICROMIPS - union mips_instruction *ip =3D (void *) (((char *) info->func) - 1); -#else - union mips_instruction *ip =3D info->func; -#endif - unsigned max_insns =3D info->func_size / sizeof(union mips_instruction); - unsigned i; + bool is_mmips =3D IS_ENABLED(CONFIG_CPU_MICROMIPS); + union mips_instruction insn, *ip, *ip_end; + const unsigned int max_insns =3D 128; + unsigned int i; =20 info->pc_offset =3D -1; info->frame_size =3D 0; =20 + ip =3D (void *)msk_isa16_mode((ulong)info->func); if (!ip) goto err; =20 - if (max_insns =3D=3D 0) - max_insns =3D 128U; /* unknown function size */ - max_insns =3D min(128U, max_insns); - - for (i =3D 0; i < max_insns; i++, ip++) { + ip_end =3D (void *)ip + info->func_size; + + for (i =3D 0; i < max_insns && ip < ip_end; i++, ip++) { + if (is_mmips && mm_insn_16bit(ip->halfword[0])) { + insn.halfword[0] =3D 0; + insn.halfword[1] =3D ip->halfword[0]; + } else if (is_mmips) { + insn.halfword[0] =3D ip->halfword[1]; + insn.halfword[1] =3D ip->halfword[0]; + } else { + insn.word =3D ip->word; + } =20 - if (is_jump_ins(ip)) + if (is_jump_ins(&insn)) break; + if (!info->frame_size) { - if (is_sp_move_ins(ip)) + if (is_sp_move_ins(&insn)) { #ifdef CONFIG_CPU_MICROMIPS if (mm_insn_16bit(ip->halfword[0])) @@ -377,11 +424,9 @@ static int get_frame_info(struct mips_frame_info *info) } continue; } - if (info->pc_offset =3D=3D -1 && is_ra_save_ins(ip)) { - info->pc_offset =3D - ip->i_format.simmediate / sizeof(long); + if (info->pc_offset =3D=3D -1 && + is_ra_save_ins(&insn, &info->pc_offset)) break; - } } if (info->frame_size && info->pc_offset >=3D 0) /* nested */ return 0; diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/commo= n/smpboot.S index 805355b0bd05..deeac1243bc2 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -61,8 +61,8 @@ NESTED(xlp_boot_core0_siblings, PT_SIZE, sp) sync /* find the location to which nlm_boot_siblings was relocated */ li t0, CKSEG1ADDR(RESET_VEC_PHYS) - dla t1, nlm_reset_entry - dla t2, nlm_boot_siblings + PTR_LA t1, nlm_reset_entry + PTR_LA t2, nlm_boot_siblings dsubu t2, t1 daddu t2, t0 /* call it */ diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_b= reakpoint.c index 0bb5918faaaf..839b7cd1edc9 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c @@ -227,8 +227,10 @@ int __kprobes hw_breakpoint_handler(struct die_args *a= rgs) rcu_read_lock(); =20 bp =3D __get_cpu_var(bp_per_reg); - if (!bp) + if (!bp) { + rc =3D NOTIFY_DONE; goto out; + } info =3D counter_arch_bp(bp); =20 /* diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index fd8a8373c275..dcf75dfd4583 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -216,6 +216,9 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot; int is_dirty =3D 0; =20 + if (kvm_is_ucontrol(kvm)) + return -EINVAL; + mutex_lock(&kvm->slots_lock); =20 r =3D -EINVAL; diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm= /hyperv.h index 462efe746d77..7c6634dd42c6 100644 --- a/arch/x86/include/uapi/asm/hyperv.h +++ b/arch/x86/include/uapi/asm/hyperv.h @@ -214,6 +214,8 @@ #define HV_STATUS_INVALID_HYPERCALL_CODE 2 #define HV_STATUS_INVALID_HYPERCALL_INPUT 3 #define HV_STATUS_INVALID_ALIGNMENT 4 +#define HV_STATUS_INSUFFICIENT_MEMORY 11 +#define HV_STATUS_INVALID_CONNECTION_ID 18 #define HV_STATUS_INSUFFICIENT_BUFFERS 19 =20 typedef struct _HV_REFERENCE_TSC_PAGE { diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary= _64.c index 0497f719977d..c055e9a4e547 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -296,7 +296,7 @@ static void iommu_free(struct iommu_table *tbl, dma_add= r_t dma_addr, =20 /* were we called with bad_dma_address? */ badend =3D DMA_ERROR_CODE + (EMERGENCY_PAGES * PAGE_SIZE); - if (unlikely((dma_addr >=3D DMA_ERROR_CODE) && (dma_addr < badend))) { + if (unlikely(dma_addr < badend)) { WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA " "address 0x%Lx\n", dma_addr); return; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index dad945386800..d55d7b518cdc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3231,7 +3231,7 @@ static void fix_rmode_seg(int seg, struct kvm_segment= *save) } =20 vmcs_write16(sf->selector, var.selector); - vmcs_write32(sf->base, var.base); + vmcs_writel(sf->base, var.base); vmcs_write32(sf->limit, var.limit); vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(&var)); } diff --git a/arch/x86/platform/goldfish/goldfish.c b/arch/x86/platform/gold= fish/goldfish.c index 1693107a518e..0d17c0aafeb1 100644 --- a/arch/x86/platform/goldfish/goldfish.c +++ b/arch/x86/platform/goldfish/goldfish.c @@ -42,10 +42,22 @@ static struct resource goldfish_pdev_bus_resources[] = =3D { } }; =20 +static bool goldfish_enable __initdata; + +static int __init goldfish_setup(char *str) +{ + goldfish_enable =3D true; + return 0; +} +__setup("goldfish", goldfish_setup); + static int __init goldfish_init(void) { + if (!goldfish_enable) + return -ENODEV; + platform_device_register_simple("goldfish_pdev_bus", -1, - goldfish_pdev_bus_resources, 2); + goldfish_pdev_bus_resources, 2); return 0; } device_initcall(goldfish_init); diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index ed5b8b9b8d96..08f8da0d6443 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -133,6 +133,8 @@ static int __init parse_tag_initrd(const bp_tag_t* tag) =20 __tagtable(BP_TAG_INITRD, parse_tag_initrd); =20 +#endif /* CONFIG_BLK_DEV_INITRD */ + #ifdef CONFIG_OF =20 static int __init parse_tag_fdt(const bp_tag_t *tag) @@ -145,8 +147,6 @@ __tagtable(BP_TAG_FDT, parse_tag_fdt); =20 #endif /* CONFIG_OF */ =20 -#endif /* CONFIG_BLK_DEV_INITRD */ - static int __init parse_tag_cmdline(const bp_tag_t* tag) { strlcpy(command_line, (char *)(tag->data), COMMAND_LINE_SIZE); diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index b88f4b375c27..b37125e2c7dc 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -340,6 +340,7 @@ static void bt_clear_tag(struct blk_mq_bitmap_tags *bt,= unsigned int tag) { const int index =3D TAG_TO_INDEX(bt, tag); struct bt_wait_state *bs; + unsigned int wake_batch; int wait_cnt; =20 clear_bit(TAG_TO_BIT(bt, tag), &bt->map[index].word); @@ -352,15 +353,24 @@ static void bt_clear_tag(struct blk_mq_bitmap_tags *b= t, unsigned int tag) return; =20 wait_cnt =3D atomic_dec_return(&bs->wait_cnt); - if (wait_cnt =3D=3D 0) { -wake: - atomic_add(bt->wake_cnt, &bs->wait_cnt); + if (wait_cnt <=3D 0) { + wake_batch =3D ACCESS_ONCE(bt->wake_cnt); + /* + * Pairs with the memory barrier in bt_update_count() to + * ensure that we see the batch size update before the wait + * count is reset. + */ + smp_mb__before_atomic(); + /* + * If there are concurrent callers to bt_clear_tag(), the last + * one to decrement the wait count below zero will bump it back + * up. If there is a concurrent resize, the count reset will + * either cause the cmpxchg to fail or overwrite after the + * cmpxchg. + */ + atomic_cmpxchg(&bs->wait_cnt, wait_cnt, wait_cnt + wake_batch); bt_index_atomic_inc(&bt->wake_index); wake_up(&bs->wait); - } else if (wait_cnt < 0) { - wait_cnt =3D atomic_inc_return(&bs->wait_cnt); - if (!wait_cnt) - goto wake; } } =20 @@ -453,20 +463,30 @@ static void bt_update_count(struct blk_mq_bitmap_tags= *bt, { unsigned int tags_per_word =3D 1U << bt->bits_per_word; unsigned int map_depth =3D depth; + unsigned int wake_batch; + int i; =20 if (depth) { - int i; - for (i =3D 0; i < bt->map_nr; i++) { bt->map[i].depth =3D min(map_depth, tags_per_word); map_depth -=3D bt->map[i].depth; } } =20 - bt->wake_cnt =3D BT_WAIT_BATCH; - if (bt->wake_cnt > depth / BT_WAIT_QUEUES) - bt->wake_cnt =3D max(1U, depth / BT_WAIT_QUEUES); + wake_batch =3D BT_WAIT_BATCH; + if (wake_batch > depth / BT_WAIT_QUEUES) + wake_batch =3D max(1U, depth / BT_WAIT_QUEUES); =20 + if (bt->wake_cnt !=3D wake_batch) { + ACCESS_ONCE(bt->wake_cnt) =3D wake_batch; + /* + * Pairs with the memory barrier in bt_clear_tag() to ensure + * that the batch size is updated before the wait counts. + */ + smp_mb__before_atomic(); + for (i =3D 0; i < BT_WAIT_QUEUES; i++) + atomic_set(&bt->bs[i].wait_cnt, 1); + } bt->depth =3D depth; } =20 diff --git a/crypto/ahash.c b/crypto/ahash.c index 8a25fdafa97f..c2982958a2a0 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -31,6 +31,7 @@ struct ahash_request_priv { crypto_completion_t complete; void *data; u8 *result; + u32 flags; void *ubuf[] CRYPTO_MINALIGN_ATTR; }; =20 @@ -263,6 +264,8 @@ static int ahash_save_req(struct ahash_request *req, cr= ypto_completion_t cplt) priv->result =3D req->result; priv->complete =3D req->base.complete; priv->data =3D req->base.data; + priv->flags =3D req->base.flags; + /* * WARNING: We do not backup req->priv here! The req->priv * is for internal use of the Crypto API and the @@ -277,38 +280,44 @@ static int ahash_save_req(struct ahash_request *req, = crypto_completion_t cplt) return 0; } =20 -static void ahash_restore_req(struct ahash_request *req) +static void ahash_restore_req(struct ahash_request *req, int err) { struct ahash_request_priv *priv =3D req->priv; =20 + if (!err) + memcpy(priv->result, req->result, + crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); + /* Restore the original crypto request. */ req->result =3D priv->result; - req->base.complete =3D priv->complete; - req->base.data =3D priv->data; + + ahash_request_set_callback(req, priv->flags, + priv->complete, priv->data); req->priv =3D NULL; =20 /* Free the req->priv.priv from the ADJUSTED request. */ kzfree(priv); } =20 -static void ahash_op_unaligned_finish(struct ahash_request *req, int err) +static void ahash_notify_einprogress(struct ahash_request *req) { struct ahash_request_priv *priv =3D req->priv; + struct crypto_async_request oreq; =20 - if (err =3D=3D -EINPROGRESS) - return; - - if (!err) - memcpy(priv->result, req->result, - crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); + oreq.data =3D priv->data; =20 - ahash_restore_req(req); + priv->complete(&oreq, -EINPROGRESS); } =20 static void ahash_op_unaligned_done(struct crypto_async_request *req, int = err) { struct ahash_request *areq =3D req->data; =20 + if (err =3D=3D -EINPROGRESS) { + ahash_notify_einprogress(areq); + return; + } + /* * Restore the original request, see ahash_op_unaligned() for what * goes where. @@ -319,7 +328,7 @@ static void ahash_op_unaligned_done(struct crypto_async= _request *req, int err) */ =20 /* First copy req->result into req->priv.result */ - ahash_op_unaligned_finish(areq, err); + ahash_restore_req(areq, err); =20 /* Complete the ORIGINAL request. */ areq->base.complete(&areq->base, err); @@ -335,7 +344,12 @@ static int ahash_op_unaligned(struct ahash_request *re= q, return err; =20 err =3D op(req); - ahash_op_unaligned_finish(req, err); + if (err =3D=3D -EINPROGRESS || + (err =3D=3D -EBUSY && (ahash_request_flags(req) & + CRYPTO_TFM_REQ_MAY_BACKLOG))) + return err; + + ahash_restore_req(req, err); =20 return err; } @@ -370,25 +384,14 @@ int crypto_ahash_digest(struct ahash_request *req) } EXPORT_SYMBOL_GPL(crypto_ahash_digest); =20 -static void ahash_def_finup_finish2(struct ahash_request *req, int err) +static void ahash_def_finup_done2(struct crypto_async_request *req, int er= r) { - struct ahash_request_priv *priv =3D req->priv; + struct ahash_request *areq =3D req->data; =20 if (err =3D=3D -EINPROGRESS) return; =20 - if (!err) - memcpy(priv->result, req->result, - crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); - - ahash_restore_req(req); -} - -static void ahash_def_finup_done2(struct crypto_async_request *req, int er= r) -{ - struct ahash_request *areq =3D req->data; - - ahash_def_finup_finish2(areq, err); + ahash_restore_req(areq, err); =20 areq->base.complete(&areq->base, err); } @@ -399,11 +402,15 @@ static int ahash_def_finup_finish1(struct ahash_reque= st *req, int err) goto out; =20 req->base.complete =3D ahash_def_finup_done2; - req->base.flags &=3D ~CRYPTO_TFM_REQ_MAY_SLEEP; + err =3D crypto_ahash_reqtfm(req)->final(req); + if (err =3D=3D -EINPROGRESS || + (err =3D=3D -EBUSY && (ahash_request_flags(req) & + CRYPTO_TFM_REQ_MAY_BACKLOG))) + return err; =20 out: - ahash_def_finup_finish2(req, err); + ahash_restore_req(req, err); return err; } =20 @@ -411,7 +418,16 @@ static void ahash_def_finup_done1(struct crypto_async_= request *req, int err) { struct ahash_request *areq =3D req->data; =20 + if (err =3D=3D -EINPROGRESS) { + ahash_notify_einprogress(areq); + return; + } + + areq->base.flags &=3D ~CRYPTO_TFM_REQ_MAY_SLEEP; + err =3D ahash_def_finup_finish1(areq, err); + if (areq->priv) + return; =20 areq->base.complete(&areq->base, err); } @@ -426,6 +442,11 @@ static int ahash_def_finup(struct ahash_request *req) return err; =20 err =3D tfm->update(req); + if (err =3D=3D -EINPROGRESS || + (err =3D=3D -EBUSY && (ahash_request_flags(req) & + CRYPTO_TFM_REQ_MAY_BACKLOG))) + return err; + return ahash_def_finup_finish1(req, err); } =20 diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 36b9eb4862cb..64458d7e067b 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -277,7 +277,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev) dev->power.qos =3D ERR_PTR(-ENODEV); spin_unlock_irq(&dev->power.lock); =20 - kfree(c->notifiers); + kfree(qos->resume_latency.notifiers); kfree(qos); =20 out: diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 34ea4c588d36..f371019925a2 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -450,8 +450,11 @@ static int bcma_device_probe(struct device *dev) drv); int err =3D 0; =20 + get_device(dev); if (adrv->probe) err =3D adrv->probe(core); + if (err) + put_device(dev); =20 return err; } @@ -464,6 +467,7 @@ static int bcma_device_remove(struct device *dev) =20 if (adrv->remove) adrv->remove(core); + put_device(dev); =20 return 0; } diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 1af9fd3202c1..7b3f02bb8152 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -94,6 +94,7 @@ static const struct usb_device_id ath3k_table[] =3D { { USB_DEVICE(0x04CA, 0x300f) }, { USB_DEVICE(0x04CA, 0x3010) }, { USB_DEVICE(0x04CA, 0x3014) }, + { USB_DEVICE(0x04CA, 0x3018) }, { USB_DEVICE(0x0930, 0x0219) }, { USB_DEVICE(0x0930, 0x021c) }, { USB_DEVICE(0x0930, 0x0220) }, @@ -162,6 +163,7 @@ static const struct usb_device_id ath3k_blist_tbl[] =3D= { { USB_DEVICE(0x04ca, 0x300f), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3010), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3014), .driver_info =3D BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3018), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x021c), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info =3D BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 876654772092..0dc627b3a92a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -188,6 +188,7 @@ static const struct usb_device_id blacklist_table[] =3D= { { USB_DEVICE(0x04ca, 0x300f), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3010), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3014), .driver_info =3D BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3018), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x021c), .driver_info =3D BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0220), .driver_info =3D BTUSB_ATH3012 }, diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 7d58b2918138..f56ea682ad44 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1129,6 +1129,8 @@ static int put_chars(u32 vtermno, const char *buf, in= t count) { struct port *port; struct scatterlist sg[1]; + void *data; + int ret; =20 if (unlikely(early_put_chars)) return early_put_chars(vtermno, buf, count); @@ -1137,8 +1139,14 @@ static int put_chars(u32 vtermno, const char *buf, i= nt count) if (!port) return -EPIPE; =20 - sg_init_one(sg, buf, count); - return __send_to_port(port, sg, 1, count, (void *)buf, false); + data =3D kmemdup(buf, count, GFP_ATOMIC); + if (!data) + return -ENOMEM; + + sg_init_one(sg, data, count); + ret =3D __send_to_port(port, sg, 1, count, data, false); + kfree(data); + return ret; } =20 /* diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index 093dfe159dfb..ef9cd34fb9b5 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -102,7 +102,8 @@ static int wm831x_fll_prepare(struct clk_hw *hw) if (ret !=3D 0) dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret); =20 - usleep_range(2000, 2000); + /* wait 2-3 ms for new frequency taking effect */ + usleep_range(2000, 3000); =20 return ret; } diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisili= con/clkgate-separated.c index b03d5a7246f9..098a80d6302b 100644 --- a/drivers/clk/hisilicon/clkgate-separated.c +++ b/drivers/clk/hisilicon/clkgate-separated.c @@ -122,6 +122,7 @@ struct clk *hisi_register_clkgate_sep(struct device *de= v, const char *name, sclk->bit_idx =3D bit_idx; sclk->flags =3D clk_gate_flags; sclk->hw.init =3D &init; + sclk->lock =3D lock; =20 clk =3D clk_register(dev, &sclk->hw); if (IS_ERR(clk)) diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3= c2410.c index 140f4733c02e..0f761acff7d4 100644 --- a/drivers/clk/samsung/clk-s3c2410.c +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -78,7 +78,7 @@ static struct syscore_ops s3c2410_clk_syscore_ops =3D { .resume =3D s3c2410_clk_resume, }; =20 -static void s3c2410_clk_sleep_init(void) +static void __init s3c2410_clk_sleep_init(void) { s3c2410_save =3D samsung_clk_alloc_reg_dump(s3c2410_clk_regs, ARRAY_SIZE(s3c2410_clk_regs)); @@ -92,7 +92,7 @@ static void s3c2410_clk_sleep_init(void) return; } #else -static void s3c2410_clk_sleep_init(void) {} +static void __init s3c2410_clk_sleep_init(void) {} #endif =20 PNAME(fclk_p) =3D { "mpll", "div_slow" }; diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3= c2412.c index 23e4313f625e..828b9f04b2c3 100644 --- a/drivers/clk/samsung/clk-s3c2412.c +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -69,7 +69,7 @@ static struct syscore_ops s3c2412_clk_syscore_ops =3D { .resume =3D s3c2412_clk_resume, }; =20 -static void s3c2412_clk_sleep_init(void) +static void __init s3c2412_clk_sleep_init(void) { s3c2412_save =3D samsung_clk_alloc_reg_dump(s3c2412_clk_regs, ARRAY_SIZE(s3c2412_clk_regs)); @@ -83,7 +83,7 @@ static void s3c2412_clk_sleep_init(void) return; } #else -static void s3c2412_clk_sleep_init(void) {} +static void __init s3c2412_clk_sleep_init(void) {} #endif =20 static struct clk_div_table divxti_d[] =3D { diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3= c2443.c index c4bbdabebaa4..3066503ded38 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -89,7 +89,7 @@ static struct syscore_ops s3c2443_clk_syscore_ops =3D { .resume =3D s3c2443_clk_resume, }; =20 -static void s3c2443_clk_sleep_init(void) +static void __init s3c2443_clk_sleep_init(void) { s3c2443_save =3D samsung_clk_alloc_reg_dump(s3c2443_clk_regs, ARRAY_SIZE(s3c2443_clk_regs)); @@ -103,7 +103,7 @@ static void s3c2443_clk_sleep_init(void) return; } #else -static void s3c2443_clk_sleep_init(void) {} +static void __init s3c2443_clk_sleep_init(void) {} #endif =20 PNAME(epllref_p) =3D { "mpllref", "mpllref", "xti", "ext" }; diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3= c64xx.c index 8889ff1c10fc..377aa5ffcab4 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -122,7 +122,7 @@ static struct syscore_ops s3c64xx_clk_syscore_ops =3D { .resume =3D s3c64xx_clk_resume, }; =20 -static void s3c64xx_clk_sleep_init(void) +static void __init s3c64xx_clk_sleep_init(void) { s3c64xx_save_common =3D samsung_clk_alloc_reg_dump(s3c64xx_clk_regs, ARRAY_SIZE(s3c64xx_clk_regs)); @@ -146,7 +146,7 @@ err_warn: __func__); } #else -static void s3c64xx_clk_sleep_init(void) {} +static void __init s3c64xx_clk_sleep_init(void) {} #endif =20 /* List of parent clocks common for all S3C64xx SoCs. */ diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mst= p.c index a9e02a38093e..2fa66c1c8a5d 100644 --- a/drivers/clk/shmobile/clk-mstp.c +++ b/drivers/clk/shmobile/clk-mstp.c @@ -85,6 +85,12 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, b= ool enable) value |=3D bitmask; cpg_mstp_write(group, value, group->smstpcr); =20 + if (!group->mstpsr) { + /* dummy read to ensure write has completed */ + cpg_mstp_read(group, group->smstpcr); + barrier(); + } + spin_unlock_irqrestore(&group->lock, flags); =20 if (!enable || !group->mstpsr) diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cp= ufreq.c index d6d425773fa4..5b2db3c6568f 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -400,7 +400,6 @@ static int s3c2416_cpufreq_driver_init(struct cpufreq_p= olicy *policy) rate =3D clk_get_rate(s3c_freq->hclk); if (rate < 133 * 1000 * 1000) { pr_err("cpufreq: HCLK not at 133MHz\n"); - clk_put(s3c_freq->hclk); ret =3D -EINVAL; goto err_armclk; } diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 38d437f3a267..976d2e1450ee 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -1625,12 +1625,44 @@ static void ast_init_dram_2300(struct drm_device *d= ev) temp |=3D 0x73; ast_write32(ast, 0x12008, temp); =20 + param.dram_freq =3D 396; param.dram_type =3D AST_DDR3; + temp =3D ast_mindwm(ast, 0x1e6e2070); if (temp & 0x01000000) param.dram_type =3D AST_DDR2; - param.dram_chipid =3D ast->dram_type; - param.dram_freq =3D ast->mclk; - param.vram_size =3D ast->vram_size; + switch (temp & 0x18000000) { + case 0: + param.dram_chipid =3D AST_DRAM_512Mx16; + break; + default: + case 0x08000000: + param.dram_chipid =3D AST_DRAM_1Gx16; + break; + case 0x10000000: + param.dram_chipid =3D AST_DRAM_2Gx16; + break; + case 0x18000000: + param.dram_chipid =3D AST_DRAM_4Gx16; + break; + } + switch (temp & 0x0c) { + default: + case 0x00: + param.vram_size =3D AST_VIDMEM_SIZE_8M; + break; + + case 0x04: + param.vram_size =3D AST_VIDMEM_SIZE_16M; + break; + + case 0x08: + param.vram_size =3D AST_VIDMEM_SIZE_32M; + break; + + case 0x0c: + param.vram_size =3D AST_VIDMEM_SIZE_64M; + break; + } =20 if (param.dram_type =3D=3D AST_DDR3) { get_ddr3_info(ast, ¶m); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/in= tel_dsi_pll.c index ba79ec19da3b..1441b1bae903 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -265,8 +265,10 @@ void vlv_enable_dsi_pll(struct intel_encoder *encoder) =20 vlv_configure_dsi_pll(encoder); =20 - /* wait at least 0.5 us after ungating before enabling VCO */ - usleep_range(1, 10); + /* wait at least 0.5 us after ungating before enabling VCO, + * allow hrtimer subsystem optimization by relaxing timing + */ + usleep_range(10, 50); =20 tmp =3D vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); tmp |=3D DSI_PLL_VCO_EN; diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/= radeon_bios.c index a1ebf2c629ed..6add06481196 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -597,51 +597,57 @@ static bool radeon_read_disabled_bios(struct radeon_d= evice *rdev) #ifdef CONFIG_ACPI static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) { - bool ret =3D false; struct acpi_table_header *hdr; acpi_size tbl_size; UEFI_ACPI_VFCT *vfct; - GOP_VBIOS_CONTENT *vbios; - VFCT_IMAGE_HEADER *vhdr; + unsigned offset; =20 if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) return false; if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); - goto out_unmap; + return false; } =20 vfct =3D (UEFI_ACPI_VFCT *)hdr; - if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { - DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); - goto out_unmap; - } + offset =3D vfct->VBIOSImageOffset; =20 - vbios =3D (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); - vhdr =3D &vbios->VbiosHeader; - DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n= ", - vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, - vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + while (offset < tbl_size) { + GOP_VBIOS_CONTENT *vbios =3D (GOP_VBIOS_CONTENT *)((char *)hdr + offset); + VFCT_IMAGE_HEADER *vhdr =3D &vbios->VbiosHeader; =20 - if (vhdr->PCIBus !=3D rdev->pdev->bus->number || - vhdr->PCIDevice !=3D PCI_SLOT(rdev->pdev->devfn) || - vhdr->PCIFunction !=3D PCI_FUNC(rdev->pdev->devfn) || - vhdr->VendorID !=3D rdev->pdev->vendor || - vhdr->DeviceID !=3D rdev->pdev->device) { - DRM_INFO("ACPI VFCT table is not for this card\n"); - goto out_unmap; - } + offset +=3D sizeof(VFCT_IMAGE_HEADER); + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image header truncated\n"); + return false; + } =20 - if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLengt= h > tbl_size) { - DRM_ERROR("ACPI VFCT image truncated\n"); - goto out_unmap; - } + offset +=3D vhdr->ImageLength; + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + return false; + } =20 - rdev->bios =3D kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNE= L); - ret =3D !!rdev->bios; + if (vhdr->ImageLength && + vhdr->PCIBus =3D=3D rdev->pdev->bus->number && + vhdr->PCIDevice =3D=3D PCI_SLOT(rdev->pdev->devfn) && + vhdr->PCIFunction =3D=3D PCI_FUNC(rdev->pdev->devfn) && + vhdr->VendorID =3D=3D rdev->pdev->vendor && + vhdr->DeviceID =3D=3D rdev->pdev->device) { + rdev->bios =3D kmemdup(&vbios->VbiosContent, + vhdr->ImageLength, + GFP_KERNEL); + + if (!rdev->bios) { + kfree(rdev->bios); + return false; + } + return true; + } + } =20 -out_unmap: - return ret; + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + return false; } #else static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index f7befc4c0c49..4f99f8084973 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1641,7 +1641,6 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shri= nk) struct ttm_buffer_object *bo; int ret =3D -EBUSY; int put_count; - uint32_t swap_placement =3D (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM); =20 spin_lock(&glob->lru_lock); list_for_each_entry(bo, &glob->swap_lru, swap) { @@ -1679,7 +1678,8 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shri= nk) if (unlikely(ret !=3D 0)) goto out; =20 - if ((bo->mem.placement & swap_placement) !=3D swap_placement) { + if (bo->mem.mem_type !=3D TTM_PL_SYSTEM || + bo->ttm->caching_state !=3D tt_cached) { struct ttm_mem_reg evict_mem; =20 evict_mem =3D bo->mem; diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_v= m.c index 0ce48e5a9cb4..1cfdbf6efc21 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -68,8 +68,11 @@ static int ttm_bo_vm_fault_idle(struct ttm_buffer_object= *bo, if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) goto out_unlock; =20 + ttm_bo_reference(bo); up_read(&vma->vm_mm->mmap_sem); (void) ttm_bo_wait(bo, false, true, false); + ttm_bo_unreserve(bo); + ttm_bo_unref(&bo); goto out_unlock; } =20 @@ -117,8 +120,10 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma,= struct vm_fault *vmf) =20 if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) { if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) { + ttm_bo_reference(bo); up_read(&vma->vm_mm->mmap_sem); (void) ttm_bo_wait_unreserved(bo); + ttm_bo_unref(&bo); } =20 return VM_FAULT_RETRY; @@ -163,6 +168,13 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma,= struct vm_fault *vmf) ret =3D ttm_bo_vm_fault_idle(bo, vma, vmf); if (unlikely(ret !=3D 0)) { retval =3D ret; + + if (retval =3D=3D VM_FAULT_RETRY && + !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) { + /* The BO has already been unreserved. */ + return retval; + } + goto out_unlock; } =20 diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwg= fx/vmwgfx_surface.c index 17a4107639b2..67623797bd55 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -711,11 +711,14 @@ int vmw_surface_define_ioctl(struct drm_device *dev, = void *data, 128; =20 num_sizes =3D 0; - for (i =3D 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) + for (i =3D 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { + if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS) + return -EINVAL; num_sizes +=3D req->mip_levels[i]; + } =20 - if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * - DRM_VMW_MAX_MIP_LEVELS) + if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS || + num_sizes =3D=3D 0) return -EINVAL; =20 size =3D vmw_user_surface_size + 128 + diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 1e951c507c0d..db2e7fecae49 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -163,7 +163,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 se= nd_ringbuffer_size, spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); =20 ret =3D vmbus_post_msg(open_msg, - sizeof(struct vmbus_channel_open_channel)); + sizeof(struct vmbus_channel_open_channel), true); =20 if (ret !=3D 0) { err =3D ret; @@ -391,7 +391,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel= , void *kbuffer, spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); =20 ret =3D vmbus_post_msg(gpadlmsg, msginfo->msgsize - - sizeof(*msginfo)); + sizeof(*msginfo), true); if (ret !=3D 0) goto cleanup; =20 @@ -407,8 +407,8 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel= , void *kbuffer, gpadl_body->gpadl =3D next_gpadl_handle; =20 ret =3D vmbus_post_msg(gpadl_body, - submsginfo->msgsize - - sizeof(*submsginfo)); + submsginfo->msgsize - sizeof(*submsginfo), + true); if (ret !=3D 0) goto cleanup; =20 @@ -456,8 +456,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel,= u32 gpadl_handle) list_add_tail(&info->msglistentry, &vmbus_connection.chn_msg_list); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); - ret =3D vmbus_post_msg(msg, - sizeof(struct vmbus_channel_gpadl_teardown)); + ret =3D vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown), + true); =20 if (ret) goto post_msg_err; @@ -502,7 +502,8 @@ static int vmbus_close_internal(struct vmbus_channel *c= hannel) msg->header.msgtype =3D CHANNELMSG_CLOSECHANNEL; msg->child_relid =3D channel->offermsg.child_relid; =20 - ret =3D vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel)); + ret =3D vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel), + true); =20 if (ret) { pr_err("Close failed: close post msg return is %d\n", ret); diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 10953ece3307..9a129f8486ca 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -229,7 +229,8 @@ static void vmbus_process_rescind_offer(struct work_str= uct *work) memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); msg.child_relid =3D channel->offermsg.child_relid; msg.header.msgtype =3D CHANNELMSG_RELID_RELEASED; - vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released)); + vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released), + true); =20 if (channel->target_cpu !=3D smp_processor_id()) smp_call_function_single(channel->target_cpu, @@ -771,8 +772,8 @@ int vmbus_request_offers(void) msg->msgtype =3D CHANNELMSG_REQUESTOFFERS; =20 =20 - ret =3D vmbus_post_msg(msg, - sizeof(struct vmbus_channel_message_header)); + ret =3D vmbus_post_msg(msg, sizeof(struct vmbus_channel_message_header), + true); if (ret !=3D 0) { pr_err("Unable to request offers - %d\n", ret); =20 diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index e206619b946e..04e5a98fdc44 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -94,7 +94,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_m= sginfo *msginfo, spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); =20 ret =3D vmbus_post_msg(msg, - sizeof(struct vmbus_channel_initiate_contact)); + sizeof(struct vmbus_channel_initiate_contact), + true); if (ret !=3D 0) { spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&msginfo->msglistentry); @@ -413,11 +414,12 @@ void vmbus_on_event(unsigned long data) /* * vmbus_post_msg - Send a msg on the vmbus's message connection */ -int vmbus_post_msg(void *buffer, size_t buflen) +int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep) { union hv_connection_id conn_id; int ret =3D 0; int retries =3D 0; + u32 usec =3D 1; =20 conn_id.asu32 =3D 0; conn_id.u.id =3D VMBUS_MESSAGE_CONNECTION_ID; @@ -427,13 +429,20 @@ int vmbus_post_msg(void *buffer, size_t buflen) * insufficient resources. Retry the operation a couple of * times before giving up. */ - while (retries < 10) { + while (retries < 100) { ret =3D hv_post_message(conn_id, 1, buffer, buflen); =20 switch (ret) { + case HV_STATUS_INVALID_CONNECTION_ID: + /* + * We could get this if we send messages too + * frequently. + */ + ret =3D -EAGAIN; + break; + case HV_STATUS_INSUFFICIENT_MEMORY: case HV_STATUS_INSUFFICIENT_BUFFERS: ret =3D -ENOMEM; - case -ENOMEM: break; case HV_STATUS_SUCCESS: return ret; @@ -443,7 +452,15 @@ int vmbus_post_msg(void *buffer, size_t buflen) } =20 retries++; - msleep(100); + if (can_sleep && usec > 1000) + msleep(usec / 1000); + else if (usec < MAX_UDELAY_MS * 1000) + udelay(usec); + else + mdelay(usec / 1000); + + if (usec < 256000) + usec *=3D 2; } return ret; } diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 3e4235c7a47f..a8b9eea5c4fc 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -156,7 +156,7 @@ int hv_init(void) /* See if the hypercall page is already set */ rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); =20 - virtaddr =3D __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); + virtaddr =3D __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX); =20 if (!virtaddr) goto cleanup; @@ -264,7 +264,7 @@ int hv_synic_alloc(void) size_t size =3D sizeof(struct tasklet_struct); int cpu; =20 - for_each_online_cpu(cpu) { + for_each_present_cpu(cpu) { hv_context.event_dpc[cpu] =3D kmalloc(size, GFP_ATOMIC); if (hv_context.event_dpc[cpu] =3D=3D NULL) { pr_err("Unable to allocate event dpc\n"); @@ -295,6 +295,8 @@ int hv_synic_alloc(void) pr_err("Unable to allocate post msg page\n"); goto err; } + + INIT_LIST_HEAD(&hv_context.percpu_list[cpu]); } =20 return 0; @@ -317,7 +319,7 @@ void hv_synic_free(void) { int cpu; =20 - for_each_online_cpu(cpu) + for_each_present_cpu(cpu) hv_synic_free_cpu(cpu); } =20 @@ -386,8 +388,6 @@ void hv_synic_init(void *arg) */ rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); hv_context.vp_index[cpu] =3D (u32)vp_index; - - INIT_LIST_HEAD(&hv_context.percpu_list[cpu]); return; } =20 diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index c386d8dc7223..97f3ad011c61 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -672,7 +672,7 @@ void vmbus_free_channels(void); =20 int vmbus_connect(void); =20 -int vmbus_post_msg(void *buffer, size_t buflen); +int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep); =20 int vmbus_set_event(struct vmbus_channel *channel); =20 diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index af3b3d032a9f..7a7b71e97ba4 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -80,6 +80,7 @@ #define ICIER_TEIE 0x40 #define ICIER_RIE 0x20 #define ICIER_NAKIE 0x10 +#define ICIER_SPIE 0x08 =20 #define ICSR2_NACKF 0x10 =20 @@ -216,11 +217,10 @@ static irqreturn_t riic_tend_isr(int irq, void *data) return IRQ_NONE; } =20 - if (riic->is_last || riic->err) + if (riic->is_last || riic->err) { + riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER); writeb(ICCR2_SP, riic->base + RIIC_ICCR2); - - writeb(0, riic->base + RIIC_ICIER); - complete(&riic->msg_done); + } =20 return IRQ_HANDLED; } @@ -240,13 +240,13 @@ static irqreturn_t riic_rdrf_isr(int irq, void *data) =20 if (riic->bytes_left =3D=3D 1) { /* STOP must come before we set ACKBT! */ - if (riic->is_last) + if (riic->is_last) { + riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER); writeb(ICCR2_SP, riic->base + RIIC_ICCR2); + } =20 riic_clear_set_bit(riic, 0, ICMR3_ACKBT, RIIC_ICMR3); =20 - writeb(0, riic->base + RIIC_ICIER); - complete(&riic->msg_done); } else { riic_clear_set_bit(riic, ICMR3_ACKBT, 0, RIIC_ICMR3); } @@ -259,6 +259,21 @@ static irqreturn_t riic_rdrf_isr(int irq, void *data) return IRQ_HANDLED; } =20 +static irqreturn_t riic_stop_isr(int irq, void *data) +{ + struct riic_dev *riic =3D data; + + /* read back registers to confirm writes have fully propagated */ + writeb(0, riic->base + RIIC_ICSR2); + readb(riic->base + RIIC_ICSR2); + writeb(0, riic->base + RIIC_ICIER); + readb(riic->base + RIIC_ICIER); + + complete(&riic->msg_done); + + return IRQ_HANDLED; +} + static u32 riic_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; @@ -326,6 +341,7 @@ static struct riic_irq_desc riic_irqs[] =3D { { .res_num =3D 0, .isr =3D riic_tend_isr, .name =3D "riic-tend" }, { .res_num =3D 1, .isr =3D riic_rdrf_isr, .name =3D "riic-rdrf" }, { .res_num =3D 2, .isr =3D riic_tdre_isr, .name =3D "riic-tdre" }, + { .res_num =3D 3, .isr =3D riic_stop_isr, .name =3D "riic-stop" }, { .res_num =3D 5, .isr =3D riic_tend_isr, .name =3D "riic-nack" }, }; =20 diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index a0d7deeac62f..3f90985d545e 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -136,6 +136,7 @@ static const struct iio_chan_spec mpl115_channels[] =3D= { { .type =3D IIO_TEMP, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), }, }; diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index 01b2e0b18878..0f5b8767ec2e 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -182,7 +182,7 @@ static const struct iio_chan_spec mpl3115_channels[] = =3D { { .type =3D IIO_PRESSURE, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), - BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE), .scan_index =3D 0, .scan_type =3D { .sign =3D 'u', @@ -195,7 +195,7 @@ static const struct iio_chan_spec mpl3115_channels[] = =3D { { .type =3D IIO_TEMP, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), - BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE), .scan_index =3D 1, .scan_type =3D { .sign =3D 's', diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure= /st_pressure_core.c index 0d70176af296..3653d8bf2b4f 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -116,7 +116,7 @@ static const struct iio_chan_spec st_press_1_channels[]= =3D { .address =3D ST_PRESS_1_OUT_XL_ADDR, .scan_index =3D ST_SENSORS_SCAN_X, .scan_type =3D { - .sign =3D 'u', + .sign =3D 's', .realbits =3D 24, .storagebits =3D 24, .endianness =3D IIO_LE, @@ -131,7 +131,7 @@ static const struct iio_chan_spec st_press_1_channels[]= =3D { .address =3D ST_TEMP_1_OUT_L_ADDR, .scan_index =3D -1, .scan_type =3D { - .sign =3D 'u', + .sign =3D 's', .realbits =3D 16, .storagebits =3D 16, .endianness =3D IIO_LE, @@ -152,7 +152,7 @@ static const struct iio_chan_spec st_press_lps001wp_cha= nnels[] =3D { .address =3D ST_PRESS_LPS001WP_OUT_L_ADDR, .scan_index =3D ST_SENSORS_SCAN_X, .scan_type =3D { - .sign =3D 'u', + .sign =3D 's', .realbits =3D 16, .storagebits =3D 16, .endianness =3D IIO_LE, @@ -168,7 +168,7 @@ static const struct iio_chan_spec st_press_lps001wp_cha= nnels[] =3D { .address =3D ST_TEMP_LPS001WP_OUT_L_ADDR, .scan_index =3D -1, .scan_type =3D { - .sign =3D 'u', + .sign =3D 's', .realbits =3D 16, .storagebits =3D 16, .endianness =3D IIO_LE, diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index cf3d9dee8aff..fb9bb266a517 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2952,6 +2952,9 @@ static int cma_accept_iw(struct rdma_id_private *id_p= riv, struct iw_cm_conn_param iw_param; int ret; =20 + if (!conn_param) + return -EINVAL; + ret =3D cma_modify_qp_rtr(id_priv, conn_param); if (ret) return ret; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/q= p.c index 85707b7d9fde..74cb286e6012 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -367,12 +367,21 @@ static int next_uuar(int n) return n; } =20 +enum { + /* this is the first blue flame register in the array of bfregs assigned + * to a processes. Since we do not use it for blue flame but rather + * regular 64 bit doorbells, we do not need a lock for maintaiing + * "odd/even" order + */ + NUM_NON_BLUE_FLAME_BFREGS =3D 1, +}; + static int num_med_uuar(struct mlx5_uuar_info *uuari) { int n; =20 n =3D uuari->num_uars * MLX5_NON_FP_BF_REGS_PER_PAGE - - uuari->num_low_latency_uuars - 1; + uuari->num_low_latency_uuars - NUM_NON_BLUE_FLAME_BFREGS; =20 return n >=3D 0 ? n : 0; } @@ -385,17 +394,9 @@ static int max_uuari(struct mlx5_uuar_info *uuari) static int first_hi_uuar(struct mlx5_uuar_info *uuari) { int med; - int i; - int t; =20 med =3D num_med_uuar(uuari); - for (t =3D 0, i =3D first_med_uuar();; i =3D next_uuar(i)) { - t++; - if (t =3D=3D med) - return next_uuar(i); - } - - return 0; + return next_uuar(med); } =20 static int alloc_high_class_uuar(struct mlx5_uuar_info *uuari) @@ -421,6 +422,8 @@ static int alloc_med_class_uuar(struct mlx5_uuar_info *= uuari) for (i =3D first_med_uuar(); i < first_hi_uuar(uuari); i =3D next_uuar(i)= ) { if (uuari->count[i] < uuari->count[minidx]) minidx =3D i; + if (!uuari->count[minidx]) + break; } =20 uuari->count[minidx]++; @@ -435,6 +438,7 @@ static int alloc_uuar(struct mlx5_uuar_info *uuari, mutex_lock(&uuari->lock); switch (lat) { case MLX5_IB_LATENCY_CLASS_LOW: + BUILD_BUG_ON(NUM_NON_BLUE_FLAME_BFREGS !=3D 1); uuarn =3D 0; uuari->count[uuarn]++; break; @@ -2332,8 +2336,9 @@ static int set_psv_wr(struct ib_sig_domain *domain, break; =20 default: - pr_err("Bad signature type given.\n"); - return 1; + pr_err("Bad signature type (%d) is given.\n", + domain->sig_type); + return -EINVAL; } =20 return 0; diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/= srq.c index 384af6dec5eb..7c2fe5235ae2 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c @@ -156,8 +156,6 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, s= truct mlx5_ib_srq *srq, int err; int i; struct mlx5_wqe_srq_next_seg *next; - int page_shift; - int npages; =20 err =3D mlx5_db_alloc(&dev->mdev, &srq->db); if (err) { @@ -172,7 +170,6 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, s= truct mlx5_ib_srq *srq, err =3D -ENOMEM; goto err_db; } - page_shift =3D srq->buf.page_shift; =20 srq->head =3D 0; srq->tail =3D srq->msrq.max - 1; @@ -184,10 +181,8 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, = struct mlx5_ib_srq *srq, cpu_to_be16((i + 1) & (srq->msrq.max - 1)); } =20 - npages =3D DIV_ROUND_UP(srq->buf.npages, 1 << (page_shift - PAGE_SHIFT)); - mlx5_ib_dbg(dev, "buf_size %d, page_shift %d, npages %d, calc npages %d\n= ", - buf_size, page_shift, srq->buf.npages, npages); - *inlen =3D sizeof(**in) + sizeof(*(*in)->pas) * npages; + mlx5_ib_dbg(dev, "srq->buf.page_shift =3D %d\n", srq->buf.page_shift); + *inlen =3D sizeof(**in) + sizeof(*(*in)->pas) * srq->buf.npages; *in =3D mlx5_vzalloc(*inlen); if (!*in) { err =3D -ENOMEM; @@ -204,7 +199,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, s= truct mlx5_ib_srq *srq, } srq->wq_sig =3D !!srq_signature; =20 - (*in)->ctx.log_pg_sz =3D page_shift - MLX5_ADAPTER_PAGE_SHIFT; + (*in)->ctx.log_pg_sz =3D srq->buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT; =20 return 0; =20 diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/u= lp/ipoib/ipoib_cm.c index 6f29bd05441f..d7db3486f933 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1376,7 +1376,7 @@ static void ipoib_cm_tx_reap(struct work_struct *work) =20 while (!list_empty(&priv->cm.reap_list)) { p =3D list_entry(priv->cm.reap_list.next, typeof(*p), list); - list_del(&p->list); + list_del_init(&p->list); spin_unlock_irqrestore(&priv->lock, flags); netif_tx_unlock_bh(dev); ipoib_cm_tx_destroy(p); @@ -1496,12 +1496,14 @@ static ssize_t set_mode(struct device *d, struct de= vice_attribute *attr, =20 ret =3D ipoib_set_mode(dev, buf); =20 - rtnl_unlock(); - - if (!ret) - return count; + /* The assumption is that the function ipoib_set_mode returned + * with the rtnl held by it, if not the value -EBUSY returned, + * then no need to rtnl_unlock + */ + if (ret !=3D -EBUSY) + rtnl_unlock(); =20 - return ret; + return (!ret || ret =3D=3D -EBUSY) ? count : ret; } =20 static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband= /ulp/ipoib/ipoib_main.c index dbfe8f1e6d7e..1aea17fe9cbe 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -226,6 +226,13 @@ int ipoib_set_mode(struct net_device *dev, const char = *buf) { struct ipoib_dev_priv *priv =3D netdev_priv(dev); =20 + if ((test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) && + !strcmp(buf, "connected\n")) || + (!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) && + !strcmp(buf, "datagram\n"))) { + return 0; + } + /* flush paths if we switch modes so that connections are restarted */ if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); @@ -236,8 +243,7 @@ int ipoib_set_mode(struct net_device *dev, const char *= buf) priv->tx_wr.send_flags &=3D ~IB_SEND_IP_CSUM; =20 ipoib_flush_paths(dev); - rtnl_lock(); - return 0; + return (!rtnl_trylock()) ? -EBUSY : 0; } =20 if (!strcmp(buf, "datagram\n")) { @@ -246,8 +252,7 @@ int ipoib_set_mode(struct net_device *dev, const char *= buf) dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); rtnl_unlock(); ipoib_flush_paths(dev); - rtnl_lock(); - return 0; + return (!rtnl_trylock()) ? -EBUSY : 0; } =20 return -EINVAL; @@ -935,7 +940,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *p= riv) rcu_dereference_protected(neigh->hnext, lockdep_is_held(&priv->lock))); /* remove from path/mc list */ - list_del(&neigh->list); + list_del_init(&neigh->list); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } else { np =3D &neigh->hnext; @@ -1098,7 +1103,7 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh) rcu_dereference_protected(neigh->hnext, lockdep_is_held(&priv->lock))); /* remove from parent list */ - list_del(&neigh->list); + list_del_init(&neigh->list); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); return; } else { @@ -1183,7 +1188,7 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, = u8 *gid) rcu_dereference_protected(neigh->hnext, lockdep_is_held(&priv->lock))); /* remove from parent list */ - list_del(&neigh->list); + list_del_init(&neigh->list); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } else { np =3D &neigh->hnext; @@ -1225,7 +1230,7 @@ static void ipoib_flush_neighs(struct ipoib_dev_priv = *priv) rcu_dereference_protected(neigh->hnext, lockdep_is_held(&priv->lock))); /* remove from path/mc list */ - list_del(&neigh->list); + list_del_init(&neigh->list); call_rcu(&neigh->rcu, ipoib_neigh_reclaim); } } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband= /ulp/ipoib/ipoib_vlan.c index 91da685cdafd..05467aa7f498 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -168,11 +168,11 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned = short pkey) out: up_write(&ppriv->vlan_rwsem); =20 + rtnl_unlock(); + if (result) free_netdev(priv->dev); =20 - rtnl_unlock(); - return result; } =20 @@ -196,7 +196,6 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned= short pkey) list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { if (priv->pkey =3D=3D pkey && priv->child_type =3D=3D IPOIB_LEGACY_CHILD) { - unregister_netdevice(priv->dev); list_del(&priv->list); dev =3D priv->dev; break; @@ -204,6 +203,11 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigne= d short pkey) } up_write(&ppriv->vlan_rwsem); =20 + if (dev) { + ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name); + unregister_netdevice(dev); + } + rtnl_unlock(); =20 if (dev) { diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d5b5878fa995..5b331109b4c4 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -972,7 +972,7 @@ static void dma_pte_free_level(struct dmar_domain *doma= in, int level, if (!dma_pte_present(pte) || dma_pte_superpage(pte)) goto next; =20 - level_pfn =3D pfn & level_mask(level - 1); + level_pfn =3D pfn & level_mask(level); level_pte =3D phys_to_virt(dma_pte_addr(pte)); =20 if (level > 2) diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 401af32ce1e2..30d019db2ac5 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -210,7 +210,7 @@ struct cache { /* * Fields for converting from sectors to blocks. */ - uint32_t sectors_per_block; + sector_t sectors_per_block; int sectors_per_block_shift; =20 spinlock_t lock; @@ -2823,11 +2823,11 @@ static void cache_status(struct dm_target *ti, stat= us_type_t type, =20 residency =3D policy_residency(cache->policy); =20 - DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ", + DMEMIT("%u %llu/%llu %llu %llu/%llu %u %u %u %u %u %u %lu ", (unsigned)(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT), (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata= ), (unsigned long long)nr_blocks_metadata, - cache->sectors_per_block, + (unsigned long long)cache->sectors_per_block, (unsigned long long) from_cblock(residency), (unsigned long long) from_cblock(cache->cache_size), (unsigned) atomic_read(&cache->stats.read_hit), diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 56f534b4a2d2..c2f4cf0b5903 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -97,6 +97,12 @@ static int linear_mergeable_bvec(struct request_queue *q, return maxsectors << 9; } =20 +/* + * In linear_congested() conf->raid_disks is used as a copy of + * mddev->raid_disks to iterate conf->disks[], because conf->raid_disks + * and conf->disks[] are created in linear_conf(), they are always + * consitent with each other, but mddev->raid_disks does not. + */ static int linear_congested(void *data, int bits) { struct mddev *mddev =3D data; @@ -109,7 +115,7 @@ static int linear_congested(void *data, int bits) rcu_read_lock(); conf =3D rcu_dereference(mddev->private); =20 - for (i =3D 0; i < mddev->raid_disks && !ret ; i++) { + for (i =3D 0; i < conf->raid_disks && !ret ; i++) { struct request_queue *q =3D bdev_get_queue(conf->disks[i].rdev->bdev); ret |=3D bdi_congested(&q->backing_dev_info, bits); } @@ -196,6 +202,19 @@ static struct linear_conf *linear_conf(struct mddev *m= ddev, int raid_disks) conf->disks[i-1].end_sector + conf->disks[i].rdev->sectors; =20 + /* + * conf->raid_disks is copy of mddev->raid_disks. The reason to + * keep a copy of mddev->raid_disks in struct linear_conf is, + * mddev->raid_disks may not be consistent with pointers number of + * conf->disks[] when it is updated in linear_add() and used to + * iterate old conf->disks[] earray in linear_congested(). + * Here conf->raid_disks is always consitent with number of + * pointers in conf->disks[] array, and mddev->private is updated + * with rcu_assign_pointer() in linear_addr(), such race can be + * avoided. + */ + conf->raid_disks =3D raid_disks; + return conf; =20 out: @@ -252,10 +271,18 @@ static int linear_add(struct mddev *mddev, struct md_= rdev *rdev) if (!newconf) return -ENOMEM; =20 + /* newconf->raid_disks already keeps a copy of * the increased + * value of mddev->raid_disks, WARN_ONCE() is just used to make + * sure of this. It is possible that oldconf is still referenced + * in linear_congested(), therefore kfree_rcu() is used to free + * oldconf until no one uses it anymore. + */ oldconf =3D rcu_dereference_protected(mddev->private, lockdep_is_held( &mddev->reconfig_mutex)); mddev->raid_disks++; + WARN_ONCE(mddev->raid_disks !=3D newconf->raid_disks, + "copied raid_disks doesn't match mddev->raid_disks"); rcu_assign_pointer(mddev->private, newconf); md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); set_capacity(mddev->gendisk, mddev->array_sectors); diff --git a/drivers/md/linear.h b/drivers/md/linear.h index b685ddd7d7f7..8d392e6098b3 100644 --- a/drivers/md/linear.h +++ b/drivers/md/linear.h @@ -10,6 +10,7 @@ struct linear_conf { struct rcu_head rcu; sector_t array_sectors; + int raid_disks; /* a copy of mddev->raid_disks */ struct dev_info disks[0]; }; #endif diff --git a/drivers/md/md.c b/drivers/md/md.c index 4db092cf3a1d..68d9714ffc57 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -8714,7 +8714,14 @@ static __exit void md_exit(void) =20 for_each_mddev(mddev, tmp) { export_array(mddev); + mddev->ctime =3D 0; mddev->hold_active =3D 0; + /* + * for_each_mddev() will call mddev_put() at the end of each + * iteration. As the mddev is now fully clear, this will + * schedule the mddev for destruction by a workqueue, and the + * destroy_workqueue() below will wait for that to complete. + */ } destroy_workqueue(md_misc_wq); destroy_workqueue(md_wq); diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f70cdea2fcc1..af8a99716de5 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2735,6 +2735,9 @@ static int adv7604_parse_dt(struct adv7604_state *sta= te) state->pdata.alt_data_sat =3D 1; state->pdata.op_format_mode_sel =3D ADV7604_OP_FORMAT_MODE0; state->pdata.bus_order =3D ADV7604_BUS_ORDER_RGB; + state->pdata.dr_str_data =3D ADV76XX_DR_STR_MEDIUM_HIGH; + state->pdata.dr_str_clk =3D ADV76XX_DR_STR_MEDIUM_HIGH; + state->pdata.dr_str_sync =3D ADV76XX_DR_STR_MEDIUM_HIGH; =20 return 0; } diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kc= onfig index 173daf0c0847..14fa7e40f2a6 100644 --- a/drivers/media/pci/dm1105/Kconfig +++ b/drivers/media/pci/dm1105/Kconfig @@ -1,6 +1,6 @@ config DVB_DM1105 tristate "SDMC DM1105 based PCI cards" - depends on DVB_CORE && PCI && I2C + depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/us= b/dvb-usb-v2/dvb_usb_core.c index e35580618936..75b11ff0e7d8 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -942,8 +942,8 @@ EXPORT_SYMBOL(dvb_usbv2_probe); void dvb_usbv2_disconnect(struct usb_interface *intf) { struct dvb_usb_device *d =3D usb_get_intfdata(intf); - const char *name =3D d->name; - struct device dev =3D d->udev->dev; + const char *devname =3D kstrdup(dev_name(&d->udev->dev), GFP_KERNEL); + const char *drvname =3D d->name; dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=3D%d\n", __func__, intf->cur_altsetting->desc.bInterfaceNumber); =20 @@ -952,8 +952,9 @@ void dvb_usbv2_disconnect(struct usb_interface *intf) =20 dvb_usbv2_exit(d); =20 - dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", - KBUILD_MODNAME, name); + pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n", + KBUILD_MODNAME, drvname, devname); + kfree(devname); } EXPORT_SYMBOL(dvb_usbv2_disconnect); =20 diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_= queue.c index 6e92d2080255..453094b28b41 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -390,7 +390,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_vid= eo_queue *queue, nextbuf =3D NULL; spin_unlock_irqrestore(&queue->irqlock, flags); =20 - buf->state =3D buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; + buf->state =3D buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); =20 diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index d4368603e67a..a0a02a8a572e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1393,10 +1393,11 @@ static int omap_hsmmc_setup_dma_transfer(struct oma= p_hsmmc_host *host, } =20 static void set_data_timeout(struct omap_hsmmc_host *host, - unsigned int timeout_ns, + unsigned long long timeout_ns, unsigned int timeout_clks) { - unsigned int timeout, cycle_ns; + unsigned long long timeout =3D timeout_ns; + unsigned int cycle_ns; uint32_t reg, clkd, dto =3D 0; =20 reg =3D OMAP_HSMMC_READ(host->base, SYSCTL); @@ -1405,7 +1406,7 @@ static void set_data_timeout(struct omap_hsmmc_host *= host, clkd =3D 1; =20 cycle_ns =3D 1000000000 / (host->clk_rate / clkd); - timeout =3D timeout_ns / cycle_ns; + do_div(timeout, cycle_ns); timeout +=3D timeout_clks; if (timeout) { while ((timeout & 0x80000000) =3D=3D 0) { diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c index ef674ecb82f8..69c10f3b4e27 100644 --- a/drivers/net/can/usb/usb_8dev.c +++ b/drivers/net/can/usb/usb_8dev.c @@ -957,8 +957,8 @@ static int usb_8dev_probe(struct usb_interface *intf, for (i =3D 0; i < MAX_TX_URBS; i++) priv->tx_contexts[i].echo_index =3D MAX_TX_URBS; =20 - priv->cmd_msg_buffer =3D kzalloc(sizeof(struct usb_8dev_cmd_msg), - GFP_KERNEL); + priv->cmd_msg_buffer =3D devm_kzalloc(&intf->dev, sizeof(struct usb_8dev_= cmd_msg), + GFP_KERNEL); if (!priv->cmd_msg_buffer) goto cleanup_candev; =20 @@ -972,7 +972,7 @@ static int usb_8dev_probe(struct usb_interface *intf, if (err) { netdev_err(netdev, "couldn't register CAN device: %d\n", err); - goto cleanup_cmd_msg_buffer; + goto cleanup_candev; } =20 err =3D usb_8dev_cmd_version(priv, &version); @@ -993,9 +993,6 @@ static int usb_8dev_probe(struct usb_interface *intf, cleanup_unregister_candev: unregister_netdev(priv->netdev); =20 -cleanup_cmd_msg_buffer: - kfree(priv->cmd_msg_buffer); - cleanup_candev: free_candev(netdev); =20 diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/b= roadcom/bgmac.c index 4f95e7222834..dcdc6692929e 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1238,12 +1238,16 @@ static netdev_tx_t bgmac_start_xmit(struct sk_buff = *skb, static int bgmac_set_mac_address(struct net_device *net_dev, void *addr) { struct bgmac *bgmac =3D netdev_priv(net_dev); + struct sockaddr *sa =3D addr; int ret; =20 ret =3D eth_prepare_mac_addr_change(net_dev, addr); if (ret < 0) return ret; - bgmac_write_mac_address(bgmac, (u8 *)addr); + + ether_addr_copy(net_dev->dev_addr, sa->sa_data); + bgmac_write_mac_address(bgmac, net_dev->dev_addr); + eth_commit_mac_addr_change(net_dev, addr); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/etherne= t/mellanox/mlx4/cmd.c index 0c158ec3170d..d38572de8946 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -42,6 +42,7 @@ #include #include #include +#include =20 #include =20 @@ -2409,7 +2410,7 @@ static int mlx4_slaves_closest_port(struct mlx4_dev *= dev, int slave, int port) return port; } =20 -int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) +int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u8 *mac) { struct mlx4_priv *priv =3D mlx4_priv(dev); struct mlx4_vport_state *s_info; @@ -2418,13 +2419,22 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port,= int vf, u64 mac) if (!mlx4_is_master(dev)) return -EPROTONOSUPPORT; =20 + if (is_multicast_ether_addr(mac)) + return -EINVAL; + slave =3D mlx4_get_slave_indx(dev, vf); if (slave < 0) return -EINVAL; =20 port =3D mlx4_slaves_closest_port(dev, slave, port); s_info =3D &priv->mfunc.master.vf_admin[slave].vport[port]; - s_info->mac =3D mac; + + if (s_info->spoofchk && is_zero_ether_addr(mac)) { + mlx4_info(dev, "MAC invalidation is not allowed when spoofchk is on\n"); + return -EPERM; + } + + s_info->mac =3D mlx4_mac_to_u64(mac); mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only= after vf restart\n", vf, port, s_info->mac); return 0; @@ -2496,6 +2506,7 @@ int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int po= rt, int vf, bool setting) struct mlx4_priv *priv =3D mlx4_priv(dev); struct mlx4_vport_state *s_info; int slave; + u8 mac[ETH_ALEN]; =20 if ((!mlx4_is_master(dev)) || !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FSM)) @@ -2507,6 +2518,13 @@ int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int p= ort, int vf, bool setting) =20 port =3D mlx4_slaves_closest_port(dev, slave, port); s_info =3D &priv->mfunc.master.vf_admin[slave].vport[port]; + + mlx4_u64_to_mac(mac, s_info->mac); + if (setting && !is_valid_ether_addr(mac)) { + mlx4_info(dev, "Illegal MAC with spoofchk\n"); + return -EPERM; + } + s_info->spoofchk =3D setting; =20 return 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/e= thernet/mellanox/mlx4/en_netdev.c index 6bf4ea400643..1006e770c109 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2253,12 +2253,8 @@ static int mlx4_en_set_vf_mac(struct net_device *dev= , int queue, u8 *mac) { struct mlx4_en_priv *en_priv =3D netdev_priv(dev); struct mlx4_en_dev *mdev =3D en_priv->mdev; - u64 mac_u64 =3D mlx4_mac_to_u64(mac); =20 - if (is_multicast_ether_addr(mac)) - return -EINVAL; - - return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac_u64); + return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac); } =20 static int mlx4_en_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u= 8 qos) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ether= net/mellanox/mlx4/en_rx.c index b07f4c0d617b..92045adc74fd 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -565,10 +565,10 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_pr= iv *priv, dma_sync_single_for_cpu(priv->ddev, dma, frag_info->frag_size, DMA_FROM_DEVICE); =20 - /* Save page reference in skb */ - __skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page); - skb_frag_size_set(&skb_frags_rx[nr], frag_info->frag_size); - skb_frags_rx[nr].page_offset =3D frags[nr].page_offset; + __skb_fill_page_desc(skb, nr, frags[nr].page, + frags[nr].page_offset, + frag_info->frag_size); + skb->truesize +=3D frag_info->frag_stride; frags[nr].page =3D NULL; } diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethern= et/mellanox/mlx4/main.c index a0c2155c47e8..c1c21231f444 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -585,8 +585,6 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENOSYS; } =20 - mlx4_log_num_mgm_entry_size =3D hca_param.log_mc_entry_sz; - dev->caps.hca_core_clock =3D hca_param.hca_core_clock; =20 memset(&dev_cap, 0, sizeof(dev_cap)); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/eth= ernet/mellanox/mlx4/mlx4_en.h index 4e47239d031d..625537010876 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -98,7 +98,8 @@ /* Use the maximum between 16384 and a single page */ #define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(16384) =20 -#define MLX4_EN_ALLOC_PREFER_ORDER PAGE_ALLOC_COSTLY_ORDER +#define MLX4_EN_ALLOC_PREFER_ORDER min_t(int, get_order(32768), \ + PAGE_ALLOC_COSTLY_ORDER) =20 /* Receive fragment sizes; we use at most 3 fragments (for 9600 byte MTU * and 4K allocations) */ diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 1e274045970f..4dd1971fd366 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -833,7 +833,7 @@ out: efx_schedule_reset(efx, RESET_TYPE_DISABLE); } else { efx_start_all(efx); - netif_device_attach(efx->net_dev); + efx_device_attach_if_not_resetting(efx); } return rc; =20 @@ -2036,6 +2036,8 @@ static int efx_net_open(struct net_device *net_dev) efx_link_status_changed(efx); =20 efx_start_all(efx); + if (efx->state =3D=3D STATE_DISABLED || efx->reset_pending) + netif_device_detach(efx->net_dev); efx_selftest_async_start(efx); return 0; } @@ -2106,7 +2108,7 @@ static int efx_change_mtu(struct net_device *net_dev,= int new_mtu) mutex_unlock(&efx->mac_lock); =20 efx_start_all(efx); - netif_device_attach(efx->net_dev); + efx_device_attach_if_not_resetting(efx); return 0; } =20 @@ -2455,7 +2457,7 @@ out: efx->state =3D STATE_DISABLED; } else { netif_dbg(efx, drv, efx->net_dev, "reset complete\n"); - netif_device_attach(efx->net_dev); + efx_device_attach_if_not_resetting(efx); } return rc; } @@ -3035,7 +3037,7 @@ static int efx_pm_thaw(struct device *dev) =20 efx_start_all(efx); =20 - netif_device_attach(efx->net_dev); + efx_device_attach_if_not_resetting(efx); =20 efx->state =3D STATE_READY; =20 diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 99032581336f..8c82a996b9f0 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -247,4 +247,10 @@ static inline void efx_device_detach_sync(struct efx_n= ic *efx) netif_tx_unlock_bh(dev); } =20 +static inline void efx_device_attach_if_not_resetting(struct efx_nic *efx) +{ + if ((efx->state !=3D STATE_DISABLED) && !efx->reset_pending) + netif_device_attach(efx->net_dev); +} + #endif /* EFX_EFX_H */ diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc= /selftest.c index b876e3847b1a..0516b24f76e4 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -749,7 +749,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_t= ests *tests, __efx_reconfigure_port(efx); mutex_unlock(&efx->mac_lock); =20 - netif_device_attach(efx->net_dev); + efx_device_attach_if_not_resetting(efx); =20 return rc_test; } diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 7badf2aa3f61..34f510f78d63 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2326,7 +2326,7 @@ static int vxlan_validate(struct nlattr *tb[], struct= nlattr *data[]) =20 if (data[IFLA_VXLAN_ID]) { __u32 id =3D nla_get_u32(data[IFLA_VXLAN_ID]); - if (id >=3D VXLAN_VID_MASK) + if (id >=3D VXLAN_N_VID) return -ERANGE; } =20 diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index f35f93c31b09..613c5580ff84 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1843,7 +1843,8 @@ static int adm8211_probe(struct pci_dev *pdev, priv->rx_ring_size =3D rx_ring_size; priv->tx_ring_size =3D tx_ring_size; =20 - if (adm8211_alloc_rings(dev)) { + err =3D adm8211_alloc_rings(dev); + if (err) { printk(KERN_ERR "%s (adm8211): Cannot allocate TX/RX ring\n", pci_name(pdev)); goto err_iounmap; diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wi= reless/ath/ath5k/mac80211-ops.c index afb23b3cc7be..eb118dce3c94 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -511,8 +511,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd= cmd, break; return -EOPNOTSUPP; default: - WARN_ON(1); - return -EINVAL; + return -EOPNOTSUPP; } =20 mutex_lock(&ah->lock); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/w= ireless/ath/ath9k/ar9003_eeprom.h index 694ca2e680e5..74670e08e6da 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -73,13 +73,13 @@ #define AR9300_OTP_BASE \ ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) #define AR9300_OTP_STATUS \ - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18) + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x31018 : 0x15f18) #define AR9300_OTP_STATUS_TYPE 0x7 #define AR9300_OTP_STATUS_VALID 0x4 #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 #define AR9300_OTP_STATUS_SM_BUSY 0x1 #define AR9300_OTP_READ_DATA \ - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c) + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3101c : 0x15f1c) =20 enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/= ath/ath9k/ath9k.h index 2ca8f7e06174..5841acfa8576 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -709,6 +709,7 @@ struct ath_softc { struct survey_info *cur_survey; struct survey_info survey[ATH9K_NUM_CHANNELS]; =20 + spinlock_t intr_lock; struct tasklet_struct intr_tq; struct tasklet_struct bcon_tasklet; struct ath_hw *sc_ah; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/a= th/ath9k/init.c index c67ef9331fbd..db35c89cf0e0 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -554,6 +554,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc= *sc, common->bt_ant_diversity =3D 1; =20 spin_lock_init(&common->cc_lock); + spin_lock_init(&sc->intr_lock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/at= h/ath9k/mac.c index 3e58bfa0c1fd..a204ef9fb0f9 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -805,21 +805,12 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_disable_interrupts); =20 -void ath9k_hw_enable_interrupts(struct ath_hw *ah) +static void __ath9k_hw_enable_interrupts(struct ath_hw *ah) { struct ath_common *common =3D ath9k_hw_common(ah); u32 sync_default =3D AR_INTR_SYNC_DEFAULT; u32 async_mask; =20 - if (!(ah->imask & ATH9K_INT_GLOBAL)) - return; - - if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { - ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", - atomic_read(&ah->intr_ref_cnt)); - return; - } - if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) sync_default &=3D ~AR_INTR_SYNC_HOST1_FATAL; =20 @@ -840,6 +831,39 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); } + +void ath9k_hw_resume_interrupts(struct ath_hw *ah) +{ + struct ath_common *common =3D ath9k_hw_common(ah); + + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + if (atomic_read(&ah->intr_ref_cnt) !=3D 0) { + ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", + atomic_read(&ah->intr_ref_cnt)); + return; + } + + __ath9k_hw_enable_interrupts(ah); +} +EXPORT_SYMBOL(ath9k_hw_resume_interrupts); + +void ath9k_hw_enable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common =3D ath9k_hw_common(ah); + + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { + ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", + atomic_read(&ah->intr_ref_cnt)); + return; + } + + __ath9k_hw_enable_interrupts(ah); +} EXPORT_SYMBOL(ath9k_hw_enable_interrupts); =20 void ath9k_hw_set_interrupts(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/at= h/ath9k/mac.h index da7686757535..e9e4a7f1b956 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -737,6 +737,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah); void ath9k_hw_enable_interrupts(struct ath_hw *ah); void ath9k_hw_disable_interrupts(struct ath_hw *ah); void ath9k_hw_kill_interrupts(struct ath_hw *ah); +void ath9k_hw_resume_interrupts(struct ath_hw *ah); =20 void ar9002_hw_attach_mac_ops(struct ath_hw *ah); =20 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/a= th/ath9k/main.c index bf6efbc2c9c0..d02417a1a69e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -441,21 +441,20 @@ void ath9k_tasklet(unsigned long data) struct ath_common *common =3D ath9k_hw_common(ah); enum ath_reset_type type; unsigned long flags; - u32 status =3D sc->intrstatus; + u32 status; u32 rxmask; =20 + spin_lock_irqsave(&sc->intr_lock, flags); + status =3D sc->intrstatus; + sc->intrstatus =3D 0; + spin_unlock_irqrestore(&sc->intr_lock, flags); + ath9k_ps_wakeup(sc); spin_lock(&sc->sc_pcu_lock); =20 if (status & ATH9K_INT_FATAL) { type =3D RESET_TYPE_FATAL_INT; ath9k_queue_reset(sc, type); - - /* - * Increment the ref. counter here so that - * interrupts are enabled in the reset routine. - */ - atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "FATAL: Skipping interrupts\n"); goto out; } @@ -471,11 +470,6 @@ void ath9k_tasklet(unsigned long data) type =3D RESET_TYPE_BB_WATCHDOG; ath9k_queue_reset(sc, type); =20 - /* - * Increment the ref. counter here so that - * interrupts are enabled in the reset routine. - */ - atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "BB_WATCHDOG: Skipping interrupts\n"); goto out; @@ -488,7 +482,6 @@ void ath9k_tasklet(unsigned long data) if ((sc->gtt_cnt >=3D MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) { type =3D RESET_TYPE_TX_GTT; ath9k_queue_reset(sc, type); - atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "GTT: Skipping interrupts\n"); goto out; @@ -545,7 +538,7 @@ void ath9k_tasklet(unsigned long data) ath9k_btcoex_handle_interrupt(sc, status); =20 /* re-enable hardware interrupt */ - ath9k_hw_enable_interrupts(ah); + ath9k_hw_resume_interrupts(ah); out: spin_unlock(&sc->sc_pcu_lock); ath9k_ps_restore(sc); @@ -612,7 +605,9 @@ irqreturn_t ath_isr(int irq, void *dev) return IRQ_NONE; =20 /* Cache the status */ - sc->intrstatus =3D status; + spin_lock(&sc->intr_lock); + sc->intrstatus |=3D status; + spin_unlock(&sc->intr_lock); =20 if (status & SCHED_INTR) sched =3D true; @@ -668,7 +663,7 @@ chip_reset: =20 if (sched) { /* turn off every interrupt */ - ath9k_hw_disable_interrupts(ah); + ath9k_hw_kill_interrupts(ah); tasklet_schedule(&sc->intr_tq); } =20 diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/i= wlwifi/mvm/rs.c index 306a6caa4868..e65714168e8e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2481,7 +2481,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, struct iwl_mvm_frame_stats *stats, u32 rate, bool agg) { - u8 nss =3D 0, mcs =3D 0; + u8 nss =3D 0; =20 spin_lock(&mvm->drv_stats_lock); =20 @@ -2506,11 +2506,9 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, =20 if (rate & RATE_MCS_HT_MSK) { stats->ht_frames++; - mcs =3D rate & RATE_HT_MCS_RATE_CODE_MSK; nss =3D ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; } else if (rate & RATE_MCS_VHT_MSK) { stats->vht_frames++; - mcs =3D rate & RATE_VHT_MCS_RATE_CODE_MSK; nss =3D ((rate & RATE_VHT_MCS_NSS_MSK) >> RATE_VHT_MCS_NSS_POS) + 1; } else { diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/= mwifiex/debugfs.c index 147250696181..a5909ef5c205 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -220,7 +220,8 @@ mwifiex_info_read(struct file *file, char __user *ubuf, if (GET_BSS_ROLE(priv) =3D=3D MWIFIEX_BSS_ROLE_STA) { p +=3D sprintf(p, "multicast_count=3D\"%d\"\n", netdev_mc_count(netdev)); - p +=3D sprintf(p, "essid=3D\"%s\"\n", info.ssid.ssid); + p +=3D sprintf(p, "essid=3D\"%.*s\"\n", info.ssid.ssid_len, + info.ssid.ssid); p +=3D sprintf(p, "bssid=3D\"%pM\"\n", info.bssid); p +=3D sprintf(p, "channel=3D\"%d\"\n", (int) info.bss_chan); p +=3D sprintf(p, "country_code =3D \"%s\"\n", info.country_code); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireles= s/mwifiex/sta_ioctl.c index c73470569e6d..da7f7d2fcb1f 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1082,8 +1082,6 @@ int mwifiex_set_encode(struct mwifiex_private *priv, = struct key_params *kp, encrypt_key.is_rx_seq_valid =3D true; } } else { - if (GET_BSS_ROLE(priv) =3D=3D MWIFIEX_BSS_ROLE_UAP) - return 0; encrypt_key.key_disable =3D true; if (mac_addr) memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfi= sh/pdev_bus.c index 8c43589c3edb..b3113971afdb 100644 --- a/drivers/platform/goldfish/pdev_bus.c +++ b/drivers/platform/goldfish/pdev_bus.c @@ -157,23 +157,26 @@ static int goldfish_new_pdev(void) static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id) { irqreturn_t ret =3D IRQ_NONE; + while (1) { u32 op =3D readl(pdev_bus_base + PDEV_BUS_OP); - switch (op) { - case PDEV_BUS_OP_DONE: - return IRQ_NONE; =20 + switch (op) { case PDEV_BUS_OP_REMOVE_DEV: goldfish_pdev_remove(); + ret =3D IRQ_HANDLED; break; =20 case PDEV_BUS_OP_ADD_DEV: goldfish_new_pdev(); + ret =3D IRQ_HANDLED; break; + + case PDEV_BUS_OP_DONE: + default: + return ret; } - ret =3D IRQ_HANDLED; } - return ret; } =20 static int goldfish_pdev_bus_probe(struct platform_device *pdev) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wm= i.c index 5eeddc00f210..72c1fa3c0bd0 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1866,11 +1866,24 @@ static int acer_wmi_enable_lm(void) return status; } =20 +#define ACER_WMID_ACCEL_HID "BST0001" + static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, void *ctx, void **retval) { + struct acpi_device *dev; + + if (!strcmp(ctx, "SENR")) { + if (acpi_bus_get_device(ah, &dev)) + return AE_OK; + if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) + return AE_OK; + } else + return AE_OK; + *(acpi_handle *)retval =3D ah; - return AE_OK; + + return AE_CTRL_TERMINATE; } =20 static int __init acer_wmi_get_handle(const char *name, const char *prop, @@ -1897,7 +1910,7 @@ static int __init acer_wmi_accel_setup(void) { int err; =20 - err =3D acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle); + err =3D acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle); if (err) return err; =20 @@ -2268,10 +2281,11 @@ static int __init acer_wmi_init(void) err =3D acer_wmi_input_setup(); if (err) return err; + err =3D acer_wmi_accel_setup(); + if (err) + return err; } =20 - acer_wmi_accel_setup(); - err =3D platform_driver_register(&acer_platform_driver); if (err) { pr_err("Unable to register platform driver\n"); diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charge= r.c index d0e8236a6404..4fc9dd2354bd 100644 --- a/drivers/power/bq24190_charger.c +++ b/drivers/power/bq24190_charger.c @@ -144,10 +144,7 @@ * so the first read after a fault returns the latched value and subsequent * reads return the current value. In order to return the fault status * to the user, have the interrupt handler save the reg's value and retrie= ve - * it in the appropriate health/status routine. Each routine has its own - * flag indicating whether it should use the value stored by the last run - * of the interrupt handler or do an actual reg read. That way each routi= ne - * can report back whatever fault may have occured. + * it in the appropriate health/status routine. */ struct bq24190_dev_info { struct i2c_client *client; @@ -159,10 +156,6 @@ struct bq24190_dev_info { unsigned int gpio_int; unsigned int irq; struct mutex f_reg_lock; - bool first_time; - bool charger_health_valid; - bool battery_health_valid; - bool battery_status_valid; u8 f_reg; u8 ss_reg; u8 watchdog; @@ -638,21 +631,11 @@ static int bq24190_charger_get_health(struct bq24190_= dev_info *bdi, union power_supply_propval *val) { u8 v; - int health, ret; + int health; =20 mutex_lock(&bdi->f_reg_lock); - - if (bdi->charger_health_valid) { - v =3D bdi->f_reg; - bdi->charger_health_valid =3D false; - mutex_unlock(&bdi->f_reg_lock); - } else { - mutex_unlock(&bdi->f_reg_lock); - - ret =3D bq24190_read(bdi, BQ24190_REG_F, &v); - if (ret < 0) - return ret; - } + v =3D bdi->f_reg; + mutex_unlock(&bdi->f_reg_lock); =20 if (v & BQ24190_REG_F_BOOST_FAULT_MASK) { /* @@ -944,18 +927,8 @@ static int bq24190_battery_get_status(struct bq24190_d= ev_info *bdi, int status, ret; =20 mutex_lock(&bdi->f_reg_lock); - - if (bdi->battery_status_valid) { - chrg_fault =3D bdi->f_reg; - bdi->battery_status_valid =3D false; - mutex_unlock(&bdi->f_reg_lock); - } else { - mutex_unlock(&bdi->f_reg_lock); - - ret =3D bq24190_read(bdi, BQ24190_REG_F, &chrg_fault); - if (ret < 0) - return ret; - } + chrg_fault =3D bdi->f_reg; + mutex_unlock(&bdi->f_reg_lock); =20 chrg_fault &=3D BQ24190_REG_F_CHRG_FAULT_MASK; chrg_fault >>=3D BQ24190_REG_F_CHRG_FAULT_SHIFT; @@ -1003,21 +976,11 @@ static int bq24190_battery_get_health(struct bq24190= _dev_info *bdi, union power_supply_propval *val) { u8 v; - int health, ret; + int health; =20 mutex_lock(&bdi->f_reg_lock); - - if (bdi->battery_health_valid) { - v =3D bdi->f_reg; - bdi->battery_health_valid =3D false; - mutex_unlock(&bdi->f_reg_lock); - } else { - mutex_unlock(&bdi->f_reg_lock); - - ret =3D bq24190_read(bdi, BQ24190_REG_F, &v); - if (ret < 0) - return ret; - } + v =3D bdi->f_reg; + mutex_unlock(&bdi->f_reg_lock); =20 if (v & BQ24190_REG_F_BAT_FAULT_MASK) { health =3D POWER_SUPPLY_HEALTH_OVERVOLTAGE; @@ -1207,9 +1170,12 @@ static void bq24190_battery_init(struct power_supply= *battery) static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) { struct bq24190_dev_info *bdi =3D data; - bool alert_userspace =3D false; + const u8 battery_mask_ss =3D BQ24190_REG_SS_CHRG_STAT_MASK; + const u8 battery_mask_f =3D BQ24190_REG_F_BAT_FAULT_MASK + | BQ24190_REG_F_NTC_FAULT_MASK; + bool alert_charger =3D false, alert_battery =3D false; u8 ss_reg =3D 0, f_reg =3D 0; - int ret; + int i, ret; =20 pm_runtime_get_sync(bdi->dev); =20 @@ -1219,6 +1185,32 @@ static irqreturn_t bq24190_irq_handler_thread(int ir= q, void *data) goto out; } =20 + i =3D 0; + do { + ret =3D bq24190_read(bdi, BQ24190_REG_F, &f_reg); + if (ret < 0) { + dev_err(bdi->dev, "Can't read F reg: %d\n", ret); + goto out; + } + } while (f_reg && ++i < 2); + + if (f_reg !=3D bdi->f_reg) { + dev_info(bdi->dev, + "Fault: boost %d, charge %d, battery %d, ntc %d\n", + !!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK), + !!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK), + !!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK), + !!(f_reg & BQ24190_REG_F_NTC_FAULT_MASK)); + + mutex_lock(&bdi->f_reg_lock); + if ((bdi->f_reg & battery_mask_f) !=3D (f_reg & battery_mask_f)) + alert_battery =3D true; + if ((bdi->f_reg & ~battery_mask_f) !=3D (f_reg & ~battery_mask_f)) + alert_charger =3D true; + bdi->f_reg =3D f_reg; + mutex_unlock(&bdi->f_reg_lock); + } + if (ss_reg !=3D bdi->ss_reg) { /* * The device is in host mode so when PG_STAT goes from 1->0 @@ -1235,44 +1227,17 @@ static irqreturn_t bq24190_irq_handler_thread(int i= rq, void *data) ret); } =20 + if ((bdi->ss_reg & battery_mask_ss) !=3D (ss_reg & battery_mask_ss)) + alert_battery =3D true; + if ((bdi->ss_reg & ~battery_mask_ss) !=3D (ss_reg & ~battery_mask_ss)) + alert_charger =3D true; bdi->ss_reg =3D ss_reg; - alert_userspace =3D true; - } - - mutex_lock(&bdi->f_reg_lock); - - ret =3D bq24190_read(bdi, BQ24190_REG_F, &f_reg); - if (ret < 0) { - mutex_unlock(&bdi->f_reg_lock); - dev_err(bdi->dev, "Can't read F reg: %d\n", ret); - goto out; } =20 - if (f_reg !=3D bdi->f_reg) { - bdi->f_reg =3D f_reg; - bdi->charger_health_valid =3D true; - bdi->battery_health_valid =3D true; - bdi->battery_status_valid =3D true; - - alert_userspace =3D true; - } - - mutex_unlock(&bdi->f_reg_lock); - - /* - * Sometimes bq24190 gives a steady trickle of interrupts even - * though the watchdog timer is turned off and neither the STATUS - * nor FAULT registers have changed. Weed out these sprurious - * interrupts so userspace isn't alerted for no reason. - * In addition, the chip always generates an interrupt after - * register reset so we should ignore that one (the very first - * interrupt received). - */ - if (alert_userspace && !bdi->first_time) { + if (alert_charger) power_supply_changed(&bdi->charger); + if (alert_battery) power_supply_changed(&bdi->battery); - bdi->first_time =3D false; - } =20 out: pm_runtime_put_sync(bdi->dev); @@ -1307,6 +1272,10 @@ static int bq24190_hw_init(struct bq24190_dev_info *= bdi) goto out; =20 ret =3D bq24190_set_mode_host(bdi); + if (ret < 0) + goto out; + + ret =3D bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); out: pm_runtime_put_sync(bdi->dev); return ret; @@ -1381,10 +1350,8 @@ static int bq24190_probe(struct i2c_client *client, bdi->model =3D id->driver_data; strncpy(bdi->model_name, id->name, I2C_NAME_SIZE); mutex_init(&bdi->f_reg_lock); - bdi->first_time =3D true; - bdi->charger_health_valid =3D false; - bdi->battery_health_valid =3D false; - bdi->battery_status_valid =3D false; + bdi->f_reg =3D 0; + bdi->ss_reg =3D BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ =20 i2c_set_clientdata(client, bdi); =20 @@ -1398,22 +1365,13 @@ static int bq24190_probe(struct i2c_client *client, return -EINVAL; } =20 - ret =3D devm_request_threaded_irq(dev, bdi->irq, NULL, - bq24190_irq_handler_thread, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "bq24190-charger", bdi); - if (ret < 0) { - dev_err(dev, "Can't set up irq handler\n"); - goto out1; - } - pm_runtime_enable(dev); pm_runtime_resume(dev); =20 ret =3D bq24190_hw_init(bdi); if (ret < 0) { dev_err(dev, "Hardware init failed\n"); - goto out2; + goto out1; } =20 bq24190_charger_init(&bdi->charger); @@ -1421,7 +1379,7 @@ static int bq24190_probe(struct i2c_client *client, ret =3D power_supply_register(dev, &bdi->charger); if (ret) { dev_err(dev, "Can't register charger\n"); - goto out2; + goto out1; } =20 bq24190_battery_init(&bdi->battery); @@ -1429,24 +1387,34 @@ static int bq24190_probe(struct i2c_client *client, ret =3D power_supply_register(dev, &bdi->battery); if (ret) { dev_err(dev, "Can't register battery\n"); - goto out3; + goto out2; } =20 ret =3D bq24190_sysfs_create_group(bdi); if (ret) { dev_err(dev, "Can't create sysfs entries\n"); + goto out3; + } + + ret =3D devm_request_threaded_irq(dev, bdi->irq, NULL, + bq24190_irq_handler_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "bq24190-charger", bdi); + if (ret < 0) { + dev_err(dev, "Can't set up irq handler\n"); goto out4; } =20 return 0; =20 out4: - power_supply_unregister(&bdi->battery); + bq24190_sysfs_remove_group(bdi); out3: - power_supply_unregister(&bdi->charger); + power_supply_unregister(&bdi->battery); out2: - pm_runtime_disable(dev); + power_supply_unregister(&bdi->charger); out1: + pm_runtime_disable(dev); if (bdi->gpio_int) gpio_free(bdi->gpio_int); =20 @@ -1490,12 +1458,13 @@ static int bq24190_pm_resume(struct device *dev) struct i2c_client *client =3D to_i2c_client(dev); struct bq24190_dev_info *bdi =3D i2c_get_clientdata(client); =20 - bdi->charger_health_valid =3D false; - bdi->battery_health_valid =3D false; - bdi->battery_status_valid =3D false; + bdi->f_reg =3D 0; + bdi->ss_reg =3D BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ =20 pm_runtime_get_sync(bdi->dev); bq24190_register_reset(bdi); + bq24190_set_mode_host(bdi); + bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); pm_runtime_put_sync(bdi->dev); =20 /* Things may have changed while suspended so alert upper layer */ diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index 4d80fc67a06b..1aec5ae5dbd6 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -138,13 +138,15 @@ static inline int tpi(struct tpi_info *addr) static inline int chsc(void *chsc_area) { typedef struct { char _[4096]; } addr_type; - int cc; + int cc =3D -EIO; =20 asm volatile( " .insn rre,0xb25f0000,%2,0\n" - " ipm %0\n" + "0: ipm %0\n" " srl %0,28\n" - : "=3Dd" (cc), "=3Dm" (*(addr_type *) chsc_area) + "1:\n" + EX_TABLE(0b, 1b) + : "+d" (cc), "=3Dm" (*(addr_type *) chsc_area) : "d" (chsc_area), "m" (*(addr_type *) chsc_area) : "cc"); return cc; diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinin= t.c index 5d06253c2a7a..30e9fbbff051 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -147,11 +147,11 @@ static inline void tiqdio_call_inq_handlers(struct qd= io_irq *irq) struct qdio_q *q; int i; =20 - for_each_input_queue(irq, q, i) { - if (!references_shared_dsci(irq) && - has_multiple_inq_on_dsci(irq)) - xchg(q->irq_ptr->dsci, 0); + if (!references_shared_dsci(irq) && + has_multiple_inq_on_dsci(irq)) + xchg(irq->dsci, 0); =20 + for_each_input_queue(irq, q, i) { if (q->u.in.queue_start_poll) { /* skip if polling is enabled or already in work */ if (test_and_set_bit(QDIO_QUEUE_IRQS_DISABLED, diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index ce177a50ec05..8c2d9efcabb3 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -83,12 +83,20 @@ static int fib_map_alloc(struct aac_dev *dev) =20 void aac_fib_map_free(struct aac_dev *dev) { - if (dev->hw_fib_va && dev->max_fib_size) { - pci_free_consistent(dev->pdev, - (dev->max_fib_size * - (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)), - dev->hw_fib_va, dev->hw_fib_pa); - } + size_t alloc_size; + size_t fib_size; + int num_fibs; + + if(!dev->hw_fib_va || !dev->max_fib_size) + return; + + num_fibs =3D dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB; + fib_size =3D dev->max_fib_size + sizeof(struct aac_fib_xporthdr); + alloc_size =3D fib_size * num_fibs + ALIGN32 - 1; + + pci_free_consistent(dev->pdev, alloc_size, dev->hw_fib_va, + dev->hw_fib_pa); + dev->hw_fib_va =3D NULL; dev->hw_fib_pa =3D 0; } @@ -116,22 +124,20 @@ int aac_fib_setup(struct aac_dev * dev) if (i<0) return -ENOMEM; =20 - /* 32 byte alignment for PMC */ - hw_fib_pa =3D (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1); - dev->hw_fib_va =3D (struct hw_fib *)((unsigned char *)dev->hw_fib_va + - (hw_fib_pa - dev->hw_fib_pa)); - dev->hw_fib_pa =3D hw_fib_pa; memset(dev->hw_fib_va, 0, (dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)); =20 + /* 32 byte alignment for PMC */ + hw_fib_pa =3D (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1); + hw_fib =3D (struct hw_fib *)((unsigned char *)dev->hw_fib_va + + (hw_fib_pa - dev->hw_fib_pa)); + /* add Xport header */ - dev->hw_fib_va =3D (struct hw_fib *)((unsigned char *)dev->hw_fib_va + + hw_fib =3D (struct hw_fib *)((unsigned char *)hw_fib + sizeof(struct aac_fib_xporthdr)); - dev->hw_fib_pa +=3D sizeof(struct aac_fib_xporthdr); + hw_fib_pa +=3D sizeof(struct aac_fib_xporthdr); =20 - hw_fib =3D dev->hw_fib_va; - hw_fib_pa =3D dev->hw_fib_pa; /* * Initialise the fibs */ diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 9c65aed26212..700d1e3ce6b2 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c @@ -359,16 +359,23 @@ static int aac_src_check_health(struct aac_dev *dev) u32 status =3D src_readl(dev, MUnit.OMR); =20 /* + * Check to see if the board panic'd. + */ + if (unlikely(status & KERNEL_PANIC)) + goto err_blink; + + /* * Check to see if the board failed any self tests. */ if (unlikely(status & SELF_TEST_FAILED)) - return -1; + goto err_out; =20 /* - * Check to see if the board panic'd. + * Check to see if the board failed any self tests. */ - if (unlikely(status & KERNEL_PANIC)) - return (status >> 16) & 0xFF; + if (unlikely(status & MONITOR_PANIC)) + goto err_out; + /* * Wait for the adapter to be up and running. */ @@ -378,6 +385,12 @@ static int aac_src_check_health(struct aac_dev *dev) * Everything is OK */ return 0; + +err_out: + return -1; + +err_blink: + return (status > 16) & 0xFF; } =20 /** diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index f9da66fa850b..739e651acc47 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -133,6 +133,8 @@ struct hv_fc_wwn_packet { #define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000 #define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000 =20 +#define SP_UNTAGGED ((unsigned char) ~0) +#define SRB_SIMPLE_TAG_REQUEST 0x20 =20 /* * Platform neutral description of a scsi request - @@ -300,11 +302,15 @@ enum storvsc_request_type { */ =20 #define SRB_STATUS_AUTOSENSE_VALID 0x80 +#define SRB_STATUS_QUEUE_FROZEN 0x40 #define SRB_STATUS_INVALID_LUN 0x20 #define SRB_STATUS_SUCCESS 0x01 #define SRB_STATUS_ABORTED 0x02 #define SRB_STATUS_ERROR 0x04 +#define SRB_STATUS_DATA_OVERRUN 0x12 =20 +#define SRB_STATUS(status) \ + (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) /* * This is the end of Protocol specific defines. */ @@ -1006,9 +1012,16 @@ static void storvsc_handle_error(struct vmscsi_reque= st *vm_srb, void (*process_err_fn)(struct work_struct *work); bool do_work =3D false; =20 - switch (vm_srb->srb_status) { + switch (SRB_STATUS(vm_srb->srb_status)) { case SRB_STATUS_ERROR: /* + * Let upper layer deal with error when + * sense message is present. + */ + + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) + break; + /* * If there is an error; offline the device since all * error recovery strategies would have already been * deployed on the host side. However, if the command @@ -1072,6 +1085,7 @@ static void storvsc_command_completion(struct storvsc= _cmd_request *cmd_request) void (*scsi_done_fn)(struct scsi_cmnd *); struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; + u32 data_transfer_length; struct stor_mem_pools *memp =3D scmnd->device->hostdata; struct Scsi_Host *host; struct storvsc_device *stor_dev; @@ -1081,6 +1095,7 @@ static void storvsc_command_completion(struct storvsc= _cmd_request *cmd_request) host =3D stor_dev->host; =20 vm_srb =3D &cmd_request->vstor_packet.vm_srb; + data_transfer_length =3D vm_srb->data_transfer_length; if (cmd_request->bounce_sgl_count) { if (vm_srb->data_in =3D=3D READ_TYPE) copy_from_bounce_buffer(scsi_sglist(scmnd), @@ -1099,13 +1114,20 @@ static void storvsc_command_completion(struct storv= sc_cmd_request *cmd_request) scsi_print_sense_hdr("storvsc", &sense_hdr); } =20 - if (vm_srb->srb_status !=3D SRB_STATUS_SUCCESS) + if (vm_srb->srb_status !=3D SRB_STATUS_SUCCESS) { storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc, sense_hdr.ascq); + /* + * The Windows driver set data_transfer_length on + * SRB_STATUS_DATA_OVERRUN. On other errors, this value + * is untouched. In these cases we set it to 0. + */ + if (vm_srb->srb_status !=3D SRB_STATUS_DATA_OVERRUN) + data_transfer_length =3D 0; + } =20 scsi_set_resid(scmnd, - cmd_request->data_buffer.len - - vm_srb->data_transfer_length); + cmd_request->data_buffer.len - data_transfer_length); =20 scsi_done_fn =3D scmnd->scsi_done; =20 @@ -1612,6 +1634,13 @@ static int storvsc_queuecommand(struct Scsi_Host *ho= st, struct scsi_cmnd *scmnd) vm_srb->win8_extension.srb_flags |=3D SRB_FLAGS_DISABLE_SYNCH_TRANSFER; =20 + if (scmnd->device->tagged_supported) { + vm_srb->win8_extension.srb_flags |=3D + (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE); + vm_srb->win8_extension.queue_tag =3D SP_UNTAGGED; + vm_srb->win8_extension.queue_action =3D SRB_SIMPLE_TAG_REQUEST; + } + /* Build the SRB */ switch (scmnd->sc_data_direction) { case DMA_TO_DEVICE: diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rt= l8188eu/core/rtw_recv.c index 0e73df5975b8..ed6daa2eec73 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1419,10 +1419,14 @@ static int wlanhdr_to_ethhdr(struct recv_frame *pre= cvframe) eth_type =3D 0x8712; /* append rx status for mp test packets */ ptr =3D recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24); + if (!ptr) + return _FAIL; memcpy(ptr, get_rxmem(precvframe), 24); ptr +=3D 24; } else { ptr =3D recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr) + (bsn= aphdr ? 2 : 0))); + if (!ptr) + return _FAIL; } =20 memcpy(ptr, pattrib->dst, ETH_ALEN); diff --git a/drivers/staging/rtl8192ee/rtl8192ee/hw.c b/drivers/staging/rtl= 8192ee/rtl8192ee/hw.c index 26af119e2ca4..0c33677d627e 100644 --- a/drivers/staging/rtl8192ee/rtl8192ee/hw.c +++ b/drivers/staging/rtl8192ee/rtl8192ee/hw.c @@ -1006,7 +1006,7 @@ static void _rtl92ee_hw_configure(struct ieee80211_hw= *hw) rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x100a); =20 /* Note Data sheet don't define */ - rtl_write_word(rtlpriv, 0x4C7, 0x80); + rtl_write_byte(rtlpriv, 0x4C7, 0x80); =20 rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); =20 diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl87= 12/rtl871x_recv.c index eb775872c93c..df2daf351c9b 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -639,11 +639,16 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvf= rame) /* append rx status for mp test packets */ ptr =3D recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24); + if (!ptr) + return _FAIL; memcpy(ptr, get_rxmem(precvframe), 24); ptr +=3D 24; - } else + } else { ptr =3D recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); + if (!ptr) + return _FAIL; + } =20 memcpy(ptr, pattrib->dst, ETH_ALEN); memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN); diff --git a/drivers/staging/rtl8821ae/rtl8821ae/hw.c b/drivers/staging/rtl= 8821ae/rtl8821ae/hw.c index 1b8583b689d4..ed3ed924b683 100644 --- a/drivers/staging/rtl8821ae/rtl8821ae/hw.c +++ b/drivers/staging/rtl8821ae/rtl8821ae/hw.c @@ -1098,7 +1098,7 @@ static u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpri= v, u16 addr) } if (0 =3D=3D tmp) { read_addr =3D REG_DBI_RDATA + addr % 4; - ret =3D rtl_read_word(rtlpriv, read_addr); + ret =3D rtl_read_byte(rtlpriv, read_addr); } return ret; } diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-= ng/p80211netdev.c index 00b186c59725..0b30340a0f0e 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -257,7 +257,7 @@ static int p80211_convert_to_ether(wlandevice_t *wlande= v, struct sk_buff *skb) struct p80211_hdr_a3 *hdr; =20 hdr =3D (struct p80211_hdr_a3 *) skb->data; - if (p80211_rx_typedrop(wlandev, hdr->fc)) + if (p80211_rx_typedrop(wlandev, le16_to_cpu(hdr->fc))) return CONV_TO_ETHER_SKIPPED; =20 /* perform mcast filtering: allow my local address through but reject diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8= 250_pci.c index e90ea3da5cda..405ab5e1f8e8 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1661,10 +1661,7 @@ pci_xr17v35x_setup(struct serial_private *priv, struct uart_8250_port *port, int idx) { u8 __iomem *p; - - p =3D pci_ioremap_bar(priv->dev, 0); - if (p =3D=3D NULL) - return -ENOMEM; + int ret; =20 port->port.flags |=3D UPF_EXAR_EFR; =20 @@ -1675,6 +1672,17 @@ pci_xr17v35x_setup(struct serial_private *priv, if (xr17v35x_has_slave(priv) && idx >=3D 8) port->port.uartclk =3D (7812500 * 16 / 2); =20 + ret =3D pci_default_setup(priv, board, port, idx); + if (ret) + return ret; + + p =3D port->port.membase; + + writeb(0x00, p + UART_EXAR_8XMODE); + writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR); + writeb(128, p + UART_EXAR_TXTRG); + writeb(128, p + UART_EXAR_RXTRG); + /* * Setup Multipurpose Input/Output pins. */ @@ -1692,13 +1700,8 @@ pci_xr17v35x_setup(struct serial_private *priv, writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/ writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/ } - writeb(0x00, p + UART_EXAR_8XMODE); - writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR); - writeb(128, p + UART_EXAR_TXTRG); - writeb(128, p + UART_EXAR_RXTRG); - iounmap(p); =20 - return pci_default_setup(priv, board, port, idx); + return 0; } =20 #define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004 @@ -2697,6 +2700,8 @@ enum pci_board_num_t { pbn_b0_4_1152000_200, pbn_b0_8_1152000_200, =20 + pbn_b0_4_1250000, + pbn_b0_2_1843200, pbn_b0_4_1843200, =20 @@ -2927,6 +2932,13 @@ static struct pciserial_board pci_boards[] =3D { .uart_offset =3D 0x200, }, =20 + [pbn_b0_4_1250000] =3D { + .flags =3D FL_BASE0, + .num_ports =3D 4, + .base_baud =3D 1250000, + .uart_offset =3D 8, + }, + [pbn_b0_2_1843200] =3D { .flags =3D FL_BASE0, .num_ports =3D 2, @@ -5526,6 +5538,10 @@ static struct pci_device_id serial_pci_tbl[] =3D { { PCI_DEVICE(0x1c29, 0x1108), .driver_data =3D pbn_fintek_8 }, { PCI_DEVICE(0x1c29, 0x1112), .driver_data =3D pbn_fintek_12 }, =20 + /* MKS Tenta SCOM-080x serial cards */ + { PCI_DEVICE(0x1601, 0x0800), .driver_data =3D pbn_b0_4_1250000 }, + { PCI_DEVICE(0x1601, 0xa801), .driver_data =3D pbn_b0_4_1250000 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_seria= l.c index 5a82ca2f4bad..6c938adae429 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1054,6 +1054,7 @@ static struct of_device_id msm_match_table[] =3D { { .compatible =3D "qcom,msm-uartdm" }, {} }; +MODULE_DEVICE_TABLE(of, msm_match_table); =20 static struct platform_driver msm_platform_driver =3D { .remove =3D msm_serial_remove, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e81cda1129a3..691c63297e4c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1346,6 +1346,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, in= t value, int protocol) memset(¶ms, 0x00, sizeof(params)); =20 if (value) { + if (dep->flags & DWC3_EP_STALL) + return 0; + if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) || (!list_empty(&dep->req_queued) || !list_empty(&dep->request_list)))) { @@ -1362,6 +1365,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, in= t value, int protocol) else dep->flags |=3D DWC3_EP_STALL; } else { + if (!(dep->flags & DWC3_EP_STALL)) + return 0; + ret =3D dwc3_send_gadget_ep_cmd(dwc, dep->number, DWC3_DEPCMD_CLEARSTALL, ¶ms); if (ret) diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index a95290a1289f..f69fd43d9f03 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -44,12 +44,12 @@ struct f_hidg { =20 /* recv report */ struct list_head completed_out_req; - spinlock_t spinlock; + spinlock_t read_spinlock; wait_queue_head_t read_queue; unsigned int qlen; =20 /* send report */ - struct mutex lock; + spinlock_t write_spinlock; bool write_pending; wait_queue_head_t write_queue; struct usb_request *req; @@ -178,28 +178,35 @@ static ssize_t f_hidg_read(struct file *file, char __= user *buffer, if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; =20 - spin_lock_irqsave(&hidg->spinlock, flags); + spin_lock_irqsave(&hidg->read_spinlock, flags); =20 #define READ_COND (!list_empty(&hidg->completed_out_req)) =20 /* wait for at least one buffer to complete */ while (!READ_COND) { - spin_unlock_irqrestore(&hidg->spinlock, flags); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); if (file->f_flags & O_NONBLOCK) return -EAGAIN; =20 if (wait_event_interruptible(hidg->read_queue, READ_COND)) return -ERESTARTSYS; =20 - spin_lock_irqsave(&hidg->spinlock, flags); + spin_lock_irqsave(&hidg->read_spinlock, flags); } =20 /* pick the first one */ list =3D list_first_entry(&hidg->completed_out_req, struct f_hidg_req_list, list); + + /* + * Remove this from list to protect it from beign free() + * while host disables our function + */ + list_del(&list->list); + req =3D list->req; count =3D min_t(unsigned int, count, req->actual - list->pos); - spin_unlock_irqrestore(&hidg->spinlock, flags); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); =20 /* copy to user outside spinlock */ count -=3D copy_to_user(buffer, req->buf + list->pos, count); @@ -212,15 +219,20 @@ static ssize_t f_hidg_read(struct file *file, char __= user *buffer, * call, taking into account its current read position. */ if (list->pos =3D=3D req->actual) { - spin_lock_irqsave(&hidg->spinlock, flags); - list_del(&list->list); kfree(list); - spin_unlock_irqrestore(&hidg->spinlock, flags); =20 req->length =3D hidg->report_length; ret =3D usb_ep_queue(hidg->out_ep, req, GFP_KERNEL); - if (ret < 0) + if (ret < 0) { + free_ep_req(hidg->out_ep, req); return ret; + } + } else { + spin_lock_irqsave(&hidg->read_spinlock, flags); + list_add(&list->list, &hidg->completed_out_req); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); + + wake_up(&hidg->read_queue); } =20 return count; @@ -229,13 +241,16 @@ static ssize_t f_hidg_read(struct file *file, char __= user *buffer, static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req) { struct f_hidg *hidg =3D (struct f_hidg *)ep->driver_data; + unsigned long flags; =20 if (req->status !=3D 0) { ERROR(hidg->func.config->cdev, "End Point Request ERROR: %d\n", req->status); } =20 + spin_lock_irqsave(&hidg->write_spinlock, flags); hidg->write_pending =3D 0; + spin_unlock_irqrestore(&hidg->write_spinlock, flags); wake_up(&hidg->write_queue); } =20 @@ -243,18 +258,19 @@ static ssize_t f_hidg_write(struct file *file, const = char __user *buffer, size_t count, loff_t *offp) { struct f_hidg *hidg =3D file->private_data; + unsigned long flags; ssize_t status =3D -ENOMEM; =20 if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; =20 - mutex_lock(&hidg->lock); + spin_lock_irqsave(&hidg->write_spinlock, flags); =20 #define WRITE_COND (!hidg->write_pending) =20 /* write queue */ while (!WRITE_COND) { - mutex_unlock(&hidg->lock); + spin_unlock_irqrestore(&hidg->write_spinlock, flags); if (file->f_flags & O_NONBLOCK) return -EAGAIN; =20 @@ -262,17 +278,20 @@ static ssize_t f_hidg_write(struct file *file, const = char __user *buffer, hidg->write_queue, WRITE_COND)) return -ERESTARTSYS; =20 - mutex_lock(&hidg->lock); + spin_lock_irqsave(&hidg->write_spinlock, flags); } =20 + hidg->write_pending =3D 1; count =3D min_t(unsigned, count, hidg->report_length); + + spin_unlock_irqrestore(&hidg->write_spinlock, flags); status =3D copy_from_user(hidg->req->buf, buffer, count); =20 if (status !=3D 0) { ERROR(hidg->func.config->cdev, "copy_from_user error\n"); - mutex_unlock(&hidg->lock); - return -EINVAL; + status =3D -EINVAL; + goto release_write_pending; } =20 hidg->req->status =3D 0; @@ -280,19 +299,23 @@ static ssize_t f_hidg_write(struct file *file, const = char __user *buffer, hidg->req->length =3D count; hidg->req->complete =3D f_hidg_req_complete; hidg->req->context =3D hidg; - hidg->write_pending =3D 1; =20 status =3D usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC); if (status < 0) { ERROR(hidg->func.config->cdev, "usb_ep_queue error on int endpoint %zd\n", status); - hidg->write_pending =3D 0; - wake_up(&hidg->write_queue); + goto release_write_pending; } else { status =3D count; } =20 - mutex_unlock(&hidg->lock); + return status; +release_write_pending: + spin_lock_irqsave(&hidg->write_spinlock, flags); + hidg->write_pending =3D 0; + spin_unlock_irqrestore(&hidg->write_spinlock, flags); + + wake_up(&hidg->write_queue); =20 return status; } @@ -345,20 +368,36 @@ static inline struct usb_request *hidg_alloc_ep_req(s= truct usb_ep *ep, static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request= *req) { struct f_hidg *hidg =3D (struct f_hidg *) req->context; + struct usb_composite_dev *cdev =3D hidg->func.config->cdev; struct f_hidg_req_list *req_list; unsigned long flags; =20 - req_list =3D kzalloc(sizeof(*req_list), GFP_ATOMIC); - if (!req_list) - return; + switch (req->status) { + case 0: + req_list =3D kzalloc(sizeof(*req_list), GFP_ATOMIC); + if (!req_list) { + ERROR(cdev, "Unable to allocate mem for req_list\n"); + goto free_req; + } =20 - req_list->req =3D req; + req_list->req =3D req; =20 - spin_lock_irqsave(&hidg->spinlock, flags); - list_add_tail(&req_list->list, &hidg->completed_out_req); - spin_unlock_irqrestore(&hidg->spinlock, flags); + spin_lock_irqsave(&hidg->read_spinlock, flags); + list_add_tail(&req_list->list, &hidg->completed_out_req); + spin_unlock_irqrestore(&hidg->read_spinlock, flags); =20 - wake_up(&hidg->read_queue); + wake_up(&hidg->read_queue); + break; + default: + ERROR(cdev, "Set report failed %d\n", req->status); + /* FALLTHROUGH */ + case -ECONNABORTED: /* hardware forced ep reset */ + case -ECONNRESET: /* request dequeued */ + case -ESHUTDOWN: /* disconnect from host */ +free_req: + free_ep_req(ep, req); + return; + } } =20 static int hidg_setup(struct usb_function *f, @@ -455,6 +494,7 @@ static void hidg_disable(struct usb_function *f) { struct f_hidg *hidg =3D func_to_hidg(f); struct f_hidg_req_list *list, *next; + unsigned long flags; =20 usb_ep_disable(hidg->in_ep); hidg->in_ep->driver_data =3D NULL; @@ -462,10 +502,13 @@ static void hidg_disable(struct usb_function *f) usb_ep_disable(hidg->out_ep); hidg->out_ep->driver_data =3D NULL; =20 + spin_lock_irqsave(&hidg->read_spinlock, flags); list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) { + free_ep_req(hidg->out_ep, list->req); list_del(&list->list); kfree(list); } + spin_unlock_irqrestore(&hidg->read_spinlock, flags); } =20 static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned al= t) @@ -610,8 +653,8 @@ static int __init hidg_bind(struct usb_configuration *c= , struct usb_function *f) if (status) goto fail; =20 - mutex_init(&hidg->lock); - spin_lock_init(&hidg->spinlock); + spin_lock_init(&hidg->write_spinlock); + spin_lock_init(&hidg->read_spinlock); init_waitqueue_head(&hidg->write_queue); init_waitqueue_head(&hidg->read_queue); INIT_LIST_HEAD(&hidg->completed_out_req); diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 807b31c0edc3..7ac38446be50 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -199,12 +199,6 @@ static inline struct usb_request *midi_alloc_ep_req(st= ruct usb_ep *ep, return alloc_ep_req(ep, length, length); } =20 -static void free_ep_req(struct usb_ep *ep, struct usb_request *req) -{ - kfree(req->buf); - usb_ep_free_request(ep, req); -} - static const uint8_t f_midi_cin_length[] =3D { 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 }; diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourc= esink.c index d3cd52db78fe..b9f06357f442 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -307,12 +307,6 @@ static inline struct usb_request *ss_alloc_ep_req(stru= ct usb_ep *ep, int len) return alloc_ep_req(ep, len, buflen); } =20 -void free_ep_req(struct usb_ep *ep, struct usb_request *req) -{ - kfree(req->buf); - usb_ep_free_request(ep, req); -} - static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) { int value; diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index 15f180904f8a..5ed90b437f18 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -59,7 +59,6 @@ void lb_modexit(void); int lb_modinit(void); =20 /* common utilities */ -void free_ep_req(struct usb_ep *ep, struct usb_request *req); void disable_endpoints(struct usb_composite_dev *cdev, struct usb_ep *in, struct usb_ep *out, struct usb_ep *iso_in, struct usb_ep *iso_out); diff --git a/drivers/usb/gadget/u_f.c b/drivers/usb/gadget/u_f.c index c6276f0268ae..4bc7eea8bfc8 100644 --- a/drivers/usb/gadget/u_f.c +++ b/drivers/usb/gadget/u_f.c @@ -11,7 +11,6 @@ * published by the Free Software Foundation. */ =20 -#include #include "u_f.h" =20 struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_l= en) diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h index 1d5f0eb68552..4247cc098a89 100644 --- a/drivers/usb/gadget/u_f.h +++ b/drivers/usb/gadget/u_f.h @@ -16,6 +16,8 @@ #ifndef __U_F_H__ #define __U_F_H__ =20 +#include + /* Variable Length Array Macros ******************************************= ****/ #define vla_group(groupname) size_t groupname##__next =3D 0 #define vla_group_size(groupname) groupname##__next @@ -45,8 +47,12 @@ struct usb_ep; struct usb_request; =20 +/* Requests allocated via alloc_ep_req() must be freed by free_ep_req(). */ struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_l= en); +static inline void free_ep_req(struct usb_ep *ep, struct usb_request *req) +{ + kfree(req->buf); + usb_ep_free_request(ep, req); +} =20 #endif /* __U_F_H__ */ - - diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 3071c0ef909b..5cfaf69bc62f 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -389,10 +389,6 @@ static ssize_t adu_read(struct file *file, __user char= *buffer, size_t count, dev->secondary_head +=3D (amount - i); bytes_read +=3D (amount - i); bytes_to_read -=3D (amount - i); - if (i) { - retval =3D bytes_read ? bytes_read : -EFAULT; - goto exit; - } } else { /* we check the primary buffer */ spin_lock_irqsave (&dev->buflock, flags); diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 1950e87b4219..e4d17878743e 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -787,12 +787,6 @@ static int iowarrior_probe(struct usb_interface *inter= face, iface_desc =3D interface->cur_altsetting; dev->product_id =3D le16_to_cpu(udev->descriptor.idProduct); =20 - if (iface_desc->desc.bNumEndpoints < 1) { - dev_err(&interface->dev, "Invalid number of endpoints\n"); - retval =3D -EINVAL; - goto error; - } - /* set up the endpoint information */ for (i =3D 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint =3D &iface_desc->endpoint[i].desc; @@ -803,6 +797,13 @@ static int iowarrior_probe(struct usb_interface *inter= face, /* this one will match for the IOWarrior56 only */ dev->int_out_endpoint =3D endpoint; } + + if (!dev->int_in_endpoint) { + dev_err(&interface->dev, "no interrupt-in endpoint found\n"); + retval =3D -ENODEV; + goto error; + } + /* we have to check the report_size often, so remember it in the endianne= ss suitable for our machine */ dev->report_size =3D usb_endpoint_maxp(dev->int_in_endpoint); if ((dev->interface->cur_altsetting->desc.bInterfaceNumber =3D=3D 0) && diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 1532cde8a437..754fc3e41005 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -99,10 +99,17 @@ static int ark3116_read_reg(struct usb_serial *serial, usb_rcvctrlpipe(serial->dev, 0), 0xfe, 0xc0, 0, reg, buf, 1, ARK_TIMEOUT); - if (result < 0) + if (result < 1) { + dev_err(&serial->interface->dev, + "failed to read register %u: %d\n", + reg, result); + if (result >=3D 0) + result =3D -EIO; + return result; - else - return buf[0]; + } + + return buf[0]; } =20 static inline int calc_divisor(int bps) @@ -366,23 +373,29 @@ static int ark3116_open(struct tty_struct *tty, struc= t usb_serial_port *port) dev_dbg(&port->dev, "%s - usb_serial_generic_open failed: %d\n", __func__, result); - goto err_out; + goto err_free; } =20 /* remove any data still left: also clears error state */ ark3116_read_reg(serial, UART_RX, buf); =20 /* read modem status */ - priv->msr =3D ark3116_read_reg(serial, UART_MSR, buf); + result =3D ark3116_read_reg(serial, UART_MSR, buf); + if (result < 0) + goto err_close; + priv->msr =3D *buf; + /* read line status */ - priv->lsr =3D ark3116_read_reg(serial, UART_LSR, buf); + result =3D ark3116_read_reg(serial, UART_LSR, buf); + if (result < 0) + goto err_close; + priv->lsr =3D *buf; =20 result =3D usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) { dev_err(&port->dev, "submit irq_in urb failed %d\n", result); - ark3116_close(port); - goto err_out; + goto err_close; } =20 /* activate interrupts */ @@ -395,8 +408,15 @@ static int ark3116_open(struct tty_struct *tty, struct= usb_serial_port *port) if (tty) ark3116_set_termios(tty, port, NULL); =20 -err_out: kfree(buf); + + return 0; + +err_close: + usb_serial_generic_close(port); +err_free: + kfree(buf); + return result; } =20 diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 6a8044291ab4..22eed0b08b8a 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -246,21 +246,11 @@ static int ch341_configure(struct usb_device *dev, st= ruct ch341_private *priv) if (r < 0) goto out; =20 - /* expect 0xff 0xee */ - r =3D ch341_get_status(dev, priv); - if (r < 0) - goto out; - r =3D ch341_set_baudrate_lcr(dev, priv, 0); if (r < 0) goto out; =20 r =3D ch341_set_handshake(dev, priv->line_control); - if (r < 0) - goto out; - - /* expect 0x9f 0xee */ - r =3D ch341_get_status(dev, priv); =20 out: kfree(buffer); return r; @@ -332,14 +322,9 @@ static void ch341_close(struct usb_serial_port *port) /* open this device, set default parameters */ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct usb_serial *serial =3D port->serial; struct ch341_private *priv =3D usb_get_serial_port_data(port); int r; =20 - r =3D ch341_configure(serial->dev, priv); - if (r) - return r; - if (tty) ch341_set_termios(tty, port, NULL); =20 @@ -351,6 +336,12 @@ static int ch341_open(struct tty_struct *tty, struct u= sb_serial_port *port) return r; } =20 + r =3D ch341_get_status(port->serial->dev, priv); + if (r < 0) { + dev_err(&port->dev, "failed to read modem status: %d\n", r); + goto err_kill_interrupt_urb; + } + r =3D usb_serial_generic_open(tty, port); if (r) goto err_kill_interrupt_urb; @@ -593,6 +584,12 @@ static int ch341_reset_resume(struct usb_serial *seria= l) ret); return ret; } + + ret =3D ch341_get_status(port->serial->dev, priv); + if (ret < 0) { + dev_err(&port->dev, "failed to read modem status: %d\n", + ret); + } } =20 return usb_serial_generic_resume(serial); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 5c4ef5a964cc..6b72aacdd779 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -171,6 +171,8 @@ static const struct usb_device_id id_table[] =3D { { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ + { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART inter= face */ + { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi= _acceleport.c index cd6df875163e..df5aec4faee6 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1400,25 +1400,30 @@ static int digi_read_inb_callback(struct urb *urb) { struct usb_serial_port *port =3D urb->context; struct digi_port *priv =3D usb_get_serial_port_data(port); - int opcode =3D ((unsigned char *)urb->transfer_buffer)[0]; - int len =3D ((unsigned char *)urb->transfer_buffer)[1]; - int port_status =3D ((unsigned char *)urb->transfer_buffer)[2]; - unsigned char *data =3D ((unsigned char *)urb->transfer_buffer) + 3; + unsigned char *buf =3D urb->transfer_buffer; + int opcode; + int len; + int port_status; + unsigned char *data; int flag, throttled; - int status =3D urb->status; - - /* do not process callbacks on closed ports */ - /* but do continue the read chain */ - if (urb->status =3D=3D -ENOENT) - return 0; =20 /* short/multiple packet check */ + if (urb->actual_length < 2) { + dev_warn(&port->dev, "short packet received\n"); + return -1; + } + + opcode =3D buf[0]; + len =3D buf[1]; + if (urb->actual_length !=3D len + 2) { - dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, " - "status=3D%d, port=3D%d, opcode=3D%d, len=3D%d, " - "actual_length=3D%d, status=3D%d\n", __func__, status, - priv->dp_port_num, opcode, len, urb->actual_length, - port_status); + dev_err(&port->dev, "malformed packet received: port=3D%d, opcode=3D%d, = len=3D%d, actual_length=3D%u\n", + priv->dp_port_num, opcode, len, urb->actual_length); + return -1; + } + + if (opcode =3D=3D DIGI_CMD_RECEIVE_DATA && len < 1) { + dev_err(&port->dev, "malformed data packet received\n"); return -1; } =20 @@ -1432,6 +1437,9 @@ static int digi_read_inb_callback(struct urb *urb) =20 /* receive data */ if (opcode =3D=3D DIGI_CMD_RECEIVE_DATA) { + port_status =3D buf[2]; + data =3D &buf[3]; + /* get flag from port_status */ flag =3D 0; =20 @@ -1484,16 +1492,20 @@ static int digi_read_oob_callback(struct urb *urb) struct usb_serial *serial =3D port->serial; struct tty_struct *tty; struct digi_port *priv =3D usb_get_serial_port_data(port); + unsigned char *buf =3D urb->transfer_buffer; int opcode, line, status, val; int i; unsigned int rts; =20 + if (urb->actual_length < 4) + return -1; + /* handle each oob command */ - for (i =3D 0; i < urb->actual_length - 3;) { - opcode =3D ((unsigned char *)urb->transfer_buffer)[i++]; - line =3D ((unsigned char *)urb->transfer_buffer)[i++]; - status =3D ((unsigned char *)urb->transfer_buffer)[i++]; - val =3D ((unsigned char *)urb->transfer_buffer)[i++]; + for (i =3D 0; i < urb->actual_length - 4; i +=3D 4) { + opcode =3D buf[i]; + line =3D buf[i + 1]; + status =3D buf[i + 2]; + val =3D buf[i + 3]; =20 dev_dbg(&port->dev, "digi_read_oob_callback: opcode=3D%d, line=3D%d, sta= tus=3D%d, val=3D%d\n", opcode, line, status, val); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 99db89ad482e..56f88df5906b 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1452,10 +1452,13 @@ static int read_latency_timer(struct usb_serial_por= t *port) FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, 0, priv->interface, buf, 1, WDR_TIMEOUT); - if (rv < 0) + if (rv < 1) { dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); - else + if (rv >=3D 0) + rv =3D -EIO; + } else { priv->latency =3D buf[0]; + } =20 kfree(buf); =20 @@ -1825,8 +1828,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port= *port) =20 mutex_init(&priv->cfg_lock); =20 - priv->flags =3D ASYNC_LOW_LATENCY; - if (quirk && quirk->port_probe) quirk->port_probe(priv); =20 @@ -2108,6 +2109,20 @@ static int ftdi_process_packet(struct usb_serial_por= t *port, priv->prev_status =3D status; } =20 + /* save if the transmitter is empty or not */ + if (packet[1] & FTDI_RS_TEMT) + priv->transmit_empty =3D 1; + else + priv->transmit_empty =3D 0; + + len -=3D 2; + if (!len) + return 0; /* status only */ + + /* + * Break and error status must only be processed for packets with + * data payload to avoid over-reporting. + */ flag =3D TTY_NORMAL; if (packet[1] & FTDI_RS_ERR_MASK) { /* Break takes precedence over parity, which takes precedence @@ -2130,15 +2145,6 @@ static int ftdi_process_packet(struct usb_serial_por= t *port, } } =20 - /* save if the transmitter is empty or not */ - if (packet[1] & FTDI_RS_TEMT) - priv->transmit_empty =3D 1; - else - priv->transmit_empty =3D 0; - - len -=3D 2; - if (!len) - return 0; /* status only */ port->icount.rx +=3D len; ch =3D packet + 2; =20 @@ -2469,8 +2475,12 @@ static int ftdi_get_modem_status(struct usb_serial_p= ort *port, FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, priv->interface, buf, len, WDR_TIMEOUT); - if (ret < 0) { + + /* NOTE: We allow short responses and handle that below. */ + if (ret < 1) { dev_err(&port->dev, "failed to get modem status: %d\n", ret); + if (ret >=3D 0) + ret =3D -EIO; ret =3D usb_translate_errors(ret); goto out; } diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgep= ort.c index b63a6c3899c5..749e1b674145 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -492,20 +492,24 @@ static int get_epic_descriptor(struct edgeport_serial= *ep) int result; struct usb_serial *serial =3D ep->serial; struct edgeport_product_info *product_info =3D &ep->product_info; - struct edge_compatibility_descriptor *epic =3D &ep->epic_descriptor; + struct edge_compatibility_descriptor *epic; struct edge_compatibility_bits *bits; struct device *dev =3D &serial->dev->dev; =20 ep->is_epic =3D 0; + + epic =3D kmalloc(sizeof(*epic), GFP_KERNEL); + if (!epic) + return -ENOMEM; + result =3D usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_GET_EPIC_DESC, 0xC0, 0x00, 0x00, - &ep->epic_descriptor, - sizeof(struct edge_compatibility_descriptor), + epic, sizeof(*epic), 300); - - if (result > 0) { + if (result =3D=3D sizeof(*epic)) { ep->is_epic =3D 1; + memcpy(&ep->epic_descriptor, epic, sizeof(*epic)); memset(product_info, 0, sizeof(struct edgeport_product_info)); =20 product_info->NumPorts =3D epic->NumPorts; @@ -534,8 +538,16 @@ static int get_epic_descriptor(struct edgeport_serial = *ep) dev_dbg(dev, " IOSPWriteLCR : %s\n", bits->IOSPWriteLCR ? "TRUE": "= FALSE"); dev_dbg(dev, " IOSPSetBaudRate : %s\n", bits->IOSPSetBaudRate ? "TRUE"= : "FALSE"); dev_dbg(dev, " TrueEdgeport : %s\n", bits->TrueEdgeport ? "TRUE": "= FALSE"); + + result =3D 0; + } else if (result >=3D 0) { + dev_warn(&serial->interface->dev, "short epic descriptor received: %d\n", + result); + result =3D -EIO; } =20 + kfree(epic); + return result; } =20 @@ -2097,8 +2109,7 @@ static int rom_write(struct usb_serial *serial, __u16= extAddr, __u16 addr, * rom_read * reads a number of bytes from the Edgeport device starting at the given * address. - * If successful returns the number of bytes read, otherwise it returns - * a negative error number of the problem. + * Returns zero on success or a negative error number. *************************************************************************= ***/ static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data) @@ -2123,12 +2134,17 @@ static int rom_read(struct usb_serial *serial, __u1= 6 extAddr, USB_REQUEST_ION_READ_ROM, 0xC0, addr, extAddr, transfer_buffer, current_length, 300); - if (result < 0) + if (result < current_length) { + if (result >=3D 0) + result =3D -EIO; break; + } memcpy(data, transfer_buffer, current_length); length -=3D current_length; addr +=3D current_length; data +=3D current_length; + + result =3D 0; } =20 kfree(transfer_buffer); @@ -2585,9 +2601,10 @@ static void get_manufacturing_desc(struct edgeport_s= erial *edge_serial) EDGE_MANUF_DESC_LEN, (__u8 *)(&edge_serial->manuf_descriptor)); =20 - if (response < 1) - dev_err(dev, "error in getting manufacturer descriptor\n"); - else { + if (response < 0) { + dev_err(dev, "error in getting manufacturer descriptor: %d\n", + response); + } else { char string[30]; dev_dbg(dev, "**Manufacturer Descriptor\n"); dev_dbg(dev, " RomSize: %dK\n", @@ -2644,9 +2661,10 @@ static void get_boot_desc(struct edgeport_serial *ed= ge_serial) EDGE_BOOT_DESC_LEN, (__u8 *)(&edge_serial->boot_descriptor)); =20 - if (response < 1) - dev_err(dev, "error in getting boot descriptor\n"); - else { + if (response < 0) { + dev_err(dev, "error in getting boot descriptor: %d\n", + response); + } else { dev_dbg(dev, "**Boot Descriptor:\n"); dev_dbg(dev, " BootCodeLength: %d\n", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); @@ -2789,7 +2807,7 @@ static int edge_startup(struct usb_serial *serial) dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); =20 /* Read the epic descriptor */ - if (get_epic_descriptor(edge_serial) <=3D 0) { + if (get_epic_descriptor(edge_serial) < 0) { /* memcpy descriptor to Supports structures */ memcpy(&edge_serial->epic_descriptor.Supports, descriptor, sizeof(struct edge_compatibility_bits)); diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index eea16550e582..1b42908bd8eb 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1630,7 +1630,7 @@ static void edge_bulk_in_callback(struct urb *urb) =20 port_number =3D edge_port->port->port_number; =20 - if (edge_port->lsr_event) { + if (urb->actual_length > 0 && edge_port->lsr_event) { edge_port->lsr_event =3D 0; dev_dbg(dev, "%s =3D=3D=3D=3D=3D Port %u LSR Status =3D %02x, Data =3D %= 02x =3D=3D=3D=3D=3D=3D\n", __func__, port_number, edge_port->lsr_mask, *data); diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_= pda.c index 930be98d59b3..6b0942428917 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -139,6 +139,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) { struct usb_serial_port *port =3D urb->context; unsigned char *data =3D urb->transfer_buffer; + unsigned int len =3D urb->actual_length; int retval; int status =3D urb->status; struct keyspan_pda_private *priv; @@ -159,18 +160,26 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) goto exit; } =20 + if (len < 1) { + dev_warn(&port->dev, "short message received\n"); + goto exit; + } + /* see if the message is data or a status interrupt */ switch (data[0]) { case 0: /* rest of message is rx data */ - if (urb->actual_length) { - tty_insert_flip_string(&port->port, data + 1, - urb->actual_length - 1); - tty_flip_buffer_push(&port->port); - } + if (len < 2) + break; + tty_insert_flip_string(&port->port, data + 1, len - 1); + tty_flip_buffer_push(&port->port); break; case 1: /* status interrupt */ + if (len < 3) { + dev_warn(&port->dev, "short interrupt message received\n"); + break; + } dev_dbg(&port->dev, "rx int, d1=3D%d, d2=3D%d\n", data[1], data[2]); switch (data[1]) { case 1: /* modemline change */ diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 89726f702202..9bf82c262c5b 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -322,8 +322,12 @@ static int mct_u232_get_modem_stat(struct usb_serial_p= ort *port, MCT_U232_GET_REQUEST_TYPE, 0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE, WDR_TIMEOUT); - if (rc < 0) { + if (rc < MCT_U232_GET_MODEM_STAT_SIZE) { dev_err(&port->dev, "Get MODEM STATus failed (error =3D %d)\n", rc); + + if (rc >=3D 0) + rc =3D -EIO; + *msr =3D 0; } else { *msr =3D buf[0]; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 7cb48d3af1f4..f2a7981ba9ac 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1024,6 +1024,7 @@ static int mos7840_open(struct tty_struct *tty, struc= t usb_serial_port *port) * (can't set it up in mos7840_startup as the structures * * were not set up at that time.) */ if (port0->open_ports =3D=3D 1) { + /* FIXME: Buffer never NULL, so URB is not submitted. */ if (serial->port[0]->interrupt_in_buffer =3D=3D NULL) { /* set up interrupt urb */ usb_fill_int_urb(serial->port[0]->interrupt_in_urb, @@ -2180,7 +2181,8 @@ static int mos7840_calc_num_ports(struct usb_serial *= serial) static int mos7840_attach(struct usb_serial *serial) { if (serial->num_bulk_in < serial->num_ports || - serial->num_bulk_out < serial->num_ports) { + serial->num_bulk_out < serial->num_ports || + serial->num_interrupt_in < 1) { dev_err(&serial->interface->dev, "missing endpoints\n"); return -ENODEV; } diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index a180b17d2432..76564b3bebb9 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -142,12 +142,6 @@ static int omninet_port_remove(struct usb_serial_port = *port) =20 static int omninet_open(struct tty_struct *tty, struct usb_serial_port *po= rt) { - struct usb_serial *serial =3D port->serial; - struct usb_serial_port *wport; - - wport =3D serial->port[1]; - tty_port_tty_set(&wport->port, tty); - return usb_serial_generic_open(tty, port); } =20 diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 4b7bfb394a32..64bf258e7e00 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -142,7 +142,7 @@ static int opticon_open(struct tty_struct *tty, struct = usb_serial_port *port) usb_clear_halt(port->serial->dev, port->read_urb->pipe); =20 res =3D usb_serial_generic_open(tty, port); - if (!res) + if (res) return res; =20 /* Request CTS line state, sometimes during opening the current diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index a3ed07c58754..af0c87276299 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -188,22 +188,22 @@ static inline int qt2_setdevice(struct usb_device *de= v, u8 *data) } =20 =20 -static inline int qt2_getdevice(struct usb_device *dev, u8 *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_DEVICE, 0xc0, 0, 0, - data, 3, QT2_USB_TIMEOUT); -} - static inline int qt2_getregister(struct usb_device *dev, u8 uart, u8 reg, u8 *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_REGISTER, 0xc0, reg, - uart, data, sizeof(*data), QT2_USB_TIMEOUT); + int ret; + + ret =3D usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + QT_SET_GET_REGISTER, 0xc0, reg, + uart, data, sizeof(*data), QT2_USB_TIMEOUT); + if (ret < sizeof(*data)) { + if (ret >=3D 0) + ret =3D -EIO; + } =20 + return ret; } =20 static inline int qt2_setregister(struct usb_device *dev, @@ -372,9 +372,11 @@ static int qt2_open(struct tty_struct *tty, struct usb= _serial_port *port) 0xc0, 0, device_port, data, 2, QT2_USB_TIMEOUT); =20 - if (status < 0) { + if (status < 2) { dev_err(&port->dev, "%s - open port failed %i\n", __func__, status); + if (status >=3D 0) + status =3D -EIO; kfree(data); return status; } diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 07d1ecd564f7..26281d331859 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -137,24 +137,9 @@ static int is_himemory(const u8 ifnum, return 0; } =20 -static int sierra_calc_interface(struct usb_serial *serial) +static u8 sierra_interface_num(struct usb_serial *serial) { - int interface; - struct usb_interface *p_interface; - struct usb_host_interface *p_host_interface; - - /* Get the interface structure pointer from the serial struct */ - p_interface =3D serial->interface; - - /* Get a pointer to the host interface structure */ - p_host_interface =3D p_interface->cur_altsetting; - - /* read the interface descriptor for this active altsetting - * to find out the interface number we are on - */ - interface =3D p_host_interface->desc.bInterfaceNumber; - - return interface; + return serial->interface->cur_altsetting->desc.bInterfaceNumber; } =20 static int sierra_probe(struct usb_serial *serial, @@ -165,7 +150,7 @@ static int sierra_probe(struct usb_serial *serial, u8 ifnum; =20 udev =3D serial->dev; - ifnum =3D sierra_calc_interface(serial); + ifnum =3D sierra_interface_num(serial); =20 /* * If this interface supports more than 1 alternate @@ -178,9 +163,6 @@ static int sierra_probe(struct usb_serial *serial, usb_set_interface(udev, ifnum, 1); } =20 - /* ifnum could have changed - by calling usb_set_interface */ - ifnum =3D sierra_calc_interface(serial); - if (is_blacklisted(ifnum, (struct sierra_iface_info *)id->driver_info)) { dev_dbg(&serial->dev->dev, @@ -342,7 +324,7 @@ static int sierra_send_setup(struct usb_serial_port *po= rt) =20 /* If composite device then properly report interface */ if (serial->num_ports =3D=3D 1) { - interface =3D sierra_calc_interface(serial); + interface =3D sierra_interface_num(serial); /* Control message is sent only to interfaces with * interrupt_in endpoints */ @@ -916,7 +898,7 @@ static int sierra_port_probe(struct usb_serial_port *po= rt) /* Determine actual memory requirements */ if (serial->num_ports =3D=3D 1) { /* Get interface number for composite device */ - ifnum =3D sierra_calc_interface(serial); + ifnum =3D sierra_interface_num(serial); himemoryp =3D &typeB_interface_list; } else { /* This is really the usb-serial port number of the interface diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 475e6c31b266..ddfd787c461c 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -232,11 +232,17 @@ static int spcp8x5_get_msr(struct usb_serial_port *po= rt, u8 *status) ret =3D usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_UART_STATUS, GET_UART_STATUS_TYPE, 0, GET_UART_STATUS_MSR, buf, 1, 100); - if (ret < 0) + if (ret < 1) { dev_err(&port->dev, "failed to get modem status: %d\n", ret); + if (ret >=3D 0) + ret =3D -EIO; + goto out; + } =20 dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf); *status =3D *buf; + ret =3D 0; +out: kfree(buf); =20 return ret; diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 70a098de429f..886e1294b120 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -80,9 +80,17 @@ static inline int ssu100_setdevice(struct usb_device *de= v, u8 *data) =20 static inline int ssu100_getdevice(struct usb_device *dev, u8 *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_DEVICE, 0xc0, 0, 0, - data, 3, 300); + int ret; + + ret =3D usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + QT_SET_GET_DEVICE, 0xc0, 0, 0, + data, 3, 300); + if (ret < 3) { + if (ret >=3D 0) + ret =3D -EIO; + } + + return ret; } =20 static inline int ssu100_getregister(struct usb_device *dev, @@ -90,10 +98,17 @@ static inline int ssu100_getregister(struct usb_device = *dev, unsigned short reg, u8 *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - QT_SET_GET_REGISTER, 0xc0, reg, - uart, data, sizeof(*data), 300); + int ret; + + ret =3D usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + QT_SET_GET_REGISTER, 0xc0, reg, + uart, data, sizeof(*data), 300); + if (ret < sizeof(*data)) { + if (ret >=3D 0) + ret =3D -EIO; + } =20 + return ret; } =20 =20 @@ -289,8 +304,10 @@ static int ssu100_open(struct tty_struct *tty, struct = usb_serial_port *port) QT_OPEN_CLOSE_CHANNEL, QT_TRANSFER_IN, 0x01, 0, data, 2, 300); - if (result < 0) { + if (result < 2) { dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result); + if (result >=3D 0) + result =3D -EIO; kfree(data); return result; } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_= usb_3410_5052.c index f60a1c8f2e66..1d314ede0d65 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1357,13 +1357,10 @@ static int ti_command_out_sync(struct ti_device *td= ev, __u8 command, (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT), value, moduleid, data, size, 1000); =20 - if (status =3D=3D size) - status =3D 0; - - if (status > 0) - status =3D -ECOMM; + if (status < 0) + return status; =20 - return status; + return 0; } =20 =20 @@ -1379,8 +1376,7 @@ static int ti_command_in_sync(struct ti_device *tdev,= __u8 command, =20 if (status =3D=3D size) status =3D 0; - - if (status > 0) + else if (status >=3D 0) status =3D -ECOMM; =20 return status; diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 7404ad3062b7..176b88fa694c 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c @@ -153,6 +153,9 @@ struct ds_device */ u16 spu_bit; =20 + u8 st_buf[ST_SIZE]; + u8 byte_buf; + struct w1_bus_master master; }; =20 @@ -174,7 +177,6 @@ struct ds_status u8 data_in_buffer_status; u8 reserved1; u8 reserved2; - }; =20 static struct usb_device_id ds_id_table [] =3D { @@ -244,27 +246,6 @@ static int ds_send_control(struct ds_device *dev, u16 = value, u16 index) return err; } =20 -static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *= st, - unsigned char *buf, int size) -{ - int count, err; - - memset(st, 0, sizeof(*st)); - - count =3D 0; - err =3D usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev, - dev->ep[EP_STATUS]), buf, size, &count, 100); - if (err < 0) { - printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=3D%d.\n", dev= ->ep[EP_STATUS], err); - return err; - } - - if (count >=3D sizeof(*st)) - memcpy(st, buf, sizeof(*st)); - - return count; -} - static inline void ds_print_msg(unsigned char *buf, unsigned char *str, in= t off) { printk(KERN_INFO "%45s: %8x\n", str, buf[off]); @@ -323,6 +304,35 @@ static void ds_dump_status(struct ds_device *dev, unsi= gned char *buf, int count) } } =20 +static int ds_recv_status(struct ds_device *dev, struct ds_status *st, + bool dump) +{ + int count, err; + + if (st) + memset(st, 0, sizeof(*st)); + + count =3D 0; + err =3D usb_interrupt_msg(dev->udev, + usb_rcvintpipe(dev->udev, + dev->ep[EP_STATUS]), + dev->st_buf, sizeof(dev->st_buf), + &count, 1000); + if (err < 0) { + pr_err("Failed to read 1-wire data from 0x%x: err=3D%d.\n", + dev->ep[EP_STATUS], err); + return err; + } + + if (dump) + ds_dump_status(dev, dev->st_buf, count); + + if (st && count >=3D sizeof(*st)) + memcpy(st, dev->st_buf, sizeof(*st)); + + return count; +} + static void ds_reset_device(struct ds_device *dev) { ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); @@ -345,7 +355,6 @@ static void ds_reset_device(struct ds_device *dev) static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int siz= e) { int count, err; - struct ds_status st; =20 /* Careful on size. If size is less than what is available in * the input buffer, the device fails the bulk transfer and @@ -360,14 +369,9 @@ static int ds_recv_data(struct ds_device *dev, unsigne= d char *buf, int size) err =3D usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DAT= A_IN]), buf, size, &count, 1000); if (err < 0) { - u8 buf[ST_SIZE]; - int count; - printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]= )); - - count =3D ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); - ds_dump_status(dev, buf, count); + ds_recv_status(dev, NULL, true); return err; } =20 @@ -405,7 +409,6 @@ int ds_stop_pulse(struct ds_device *dev, int limit) { struct ds_status st; int count =3D 0, err =3D 0; - u8 buf[ST_SIZE]; =20 do { err =3D ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); @@ -414,7 +417,7 @@ int ds_stop_pulse(struct ds_device *dev, int limit) err =3D ds_send_control(dev, CTL_RESUME_EXE, 0); if (err) break; - err =3D ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); + err =3D ds_recv_status(dev, &st, false); if (err) break; =20 @@ -457,18 +460,17 @@ int ds_detect(struct ds_device *dev, struct ds_status= *st) =20 static int ds_wait_status(struct ds_device *dev, struct ds_status *st) { - u8 buf[ST_SIZE]; int err, count =3D 0; =20 do { st->status =3D 0; - err =3D ds_recv_status_nodump(dev, st, buf, sizeof(buf)); + err =3D ds_recv_status(dev, st, false); #if 0 if (err >=3D 0) { int i; printk("0x%x: count=3D%d, status: ", dev->ep[EP_STATUS], err); for (i=3D0; ist_buf[i]); printk("\n"); } #endif @@ -486,7 +488,7 @@ static int ds_wait_status(struct ds_device *dev, struct= ds_status *st) * can do something with it). */ if (err > 16 || count >=3D 100 || err < 0) - ds_dump_status(dev, buf, err); + ds_dump_status(dev, dev->st_buf, err); =20 /* Extended data isn't an error. Well, a short is, but the dump * would have already told the user that and we can't do anything @@ -609,7 +611,6 @@ static int ds_write_byte(struct ds_device *dev, u8 byte) { int err; struct ds_status st; - u8 rbyte; =20 err =3D ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte); if (err) @@ -622,11 +623,11 @@ static int ds_write_byte(struct ds_device *dev, u8 by= te) if (err) return err; =20 - err =3D ds_recv_data(dev, &rbyte, sizeof(rbyte)); + err =3D ds_recv_data(dev, &dev->byte_buf, 1); if (err < 0) return err; =20 - return !(byte =3D=3D rbyte); + return !(byte =3D=3D dev->byte_buf); } =20 static int ds_read_byte(struct ds_device *dev, u8 *byte) @@ -713,7 +714,6 @@ static void ds9490r_search(void *data, struct w1_master= *master, int err; u16 value, index; struct ds_status st; - u8 st_buf[ST_SIZE]; int search_limit; int found =3D 0; int i; @@ -725,7 +725,12 @@ static void ds9490r_search(void *data, struct w1_maste= r *master, /* FIFO 128 bytes, bulk packet size 64, read a multiple of the * packet size. */ - u64 buf[2*64/8]; + const size_t bufsize =3D 2 * 64; + u64 *buf; + + buf =3D kmalloc(bufsize, GFP_KERNEL); + if (!buf) + return; =20 mutex_lock(&master->bus_mutex); =20 @@ -746,10 +751,9 @@ static void ds9490r_search(void *data, struct w1_maste= r *master, do { schedule_timeout(jtime); =20 - if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) < - sizeof(st)) { + err =3D ds_recv_status(dev, &st, false); + if (err < 0 || err < sizeof(st)) break; - } =20 if (st.data_in_buffer_status) { /* Bulk in can receive partial ids, but when it does @@ -759,7 +763,7 @@ static void ds9490r_search(void *data, struct w1_master= *master, * bulk without first checking if status says there * is data to read. */ - err =3D ds_recv_data(dev, (u8 *)buf, sizeof(buf)); + err =3D ds_recv_data(dev, (u8 *)buf, bufsize); if (err < 0) break; for (i =3D 0; i < err/8; ++i) { @@ -795,9 +799,14 @@ static void ds9490r_search(void *data, struct w1_maste= r *master, } search_out: mutex_unlock(&master->bus_mutex); + kfree(buf); } =20 #if 0 +/* + * FIXME: if this disabled code is ever used in the future all ds_send_dat= a() + * calls must be changed to use a DMAable buffer. + */ static int ds_match_access(struct ds_device *dev, u64 init) { int err; @@ -846,13 +855,12 @@ static int ds_set_path(struct ds_device *dev, u64 ini= t) =20 static u8 ds9490r_touch_bit(void *data, u8 bit) { - u8 ret; struct ds_device *dev =3D data; =20 - if (ds_touch_bit(dev, bit, &ret)) + if (ds_touch_bit(dev, bit, &dev->byte_buf)) return 0; =20 - return ret; + return dev->byte_buf; } =20 #if 0 @@ -867,13 +875,12 @@ static u8 ds9490r_read_bit(void *data) { struct ds_device *dev =3D data; int err; - u8 bit =3D 0; =20 - err =3D ds_touch_bit(dev, 1, &bit); + err =3D ds_touch_bit(dev, 1, &dev->byte_buf); if (err) return 0; =20 - return bit & 1; + return dev->byte_buf & 1; } #endif =20 @@ -888,32 +895,52 @@ static u8 ds9490r_read_byte(void *data) { struct ds_device *dev =3D data; int err; - u8 byte =3D 0; =20 - err =3D ds_read_byte(dev, &byte); + err =3D ds_read_byte(dev, &dev->byte_buf); if (err) return 0; =20 - return byte; + return dev->byte_buf; } =20 static void ds9490r_write_block(void *data, const u8 *buf, int len) { struct ds_device *dev =3D data; + u8 *tbuf; + + if (len <=3D 0) + return; + + tbuf =3D kmalloc(len, GFP_KERNEL); + if (!tbuf) + return; + + memcpy(tbuf, buf, len); + ds_write_block(dev, tbuf, len); =20 - ds_write_block(dev, (u8 *)buf, len); + kfree(tbuf); } =20 static u8 ds9490r_read_block(void *data, u8 *buf, int len) { struct ds_device *dev =3D data; int err; + u8 *tbuf; =20 - err =3D ds_read_block(dev, buf, len); - if (err < 0) + if (len <=3D 0) + return 0; + + tbuf =3D kmalloc(len, GFP_KERNEL); + if (!tbuf) return 0; =20 - return len; + err =3D ds_read_block(dev, tbuf, len); + if (err >=3D 0) + memcpy(buf, tbuf, len); + + kfree(tbuf); + + return err >=3D 0 ? len : 0; } =20 static u8 ds9490r_reset(void *data) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 5d7341520544..6ca5f35bdb21 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -749,6 +749,7 @@ int w1_attach_slave_device(struct w1_master *dev, struc= t w1_reg_num *rn) dev_err(&dev->dev, "%s: Attaching %s failed.\n", __func__, sl->name); w1_family_put(sl->family); + atomic_dec(&sl->master->refcnt); kfree(sl); return err; } diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 7bd13f3d1790..fa89f7b23ab9 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -380,7 +380,7 @@ out: static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode, unsigned int len) { - int ret, size; + int ret, size, no_expand; struct ext4_inode_info *ei =3D EXT4_I(inode); =20 if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) @@ -390,15 +390,14 @@ static int ext4_prepare_inline_data(handle_t *handle,= struct inode *inode, if (size < len) return -ENOSPC; =20 - down_write(&EXT4_I(inode)->xattr_sem); + ext4_write_lock_xattr(inode, &no_expand); =20 if (ei->i_inline_off) ret =3D ext4_update_inline_data(handle, inode, len); else ret =3D ext4_create_inline_data(handle, inode, len); =20 - up_write(&EXT4_I(inode)->xattr_sem); - + ext4_write_unlock_xattr(inode, &no_expand); return ret; } =20 @@ -528,7 +527,7 @@ static int ext4_convert_inline_data_to_extent(struct ad= dress_space *mapping, struct inode *inode, unsigned flags) { - int ret, needed_blocks; + int ret, needed_blocks, no_expand; handle_t *handle =3D NULL; int retries =3D 0, sem_held =3D 0; struct page *page =3D NULL; @@ -568,7 +567,7 @@ retry: goto out; } =20 - down_write(&EXT4_I(inode)->xattr_sem); + ext4_write_lock_xattr(inode, &no_expand); sem_held =3D 1; /* If some one has already done this for us, just exit. */ if (!ext4_has_inline_data(inode)) { @@ -603,7 +602,7 @@ retry: unlock_page(page); page_cache_release(page); ext4_orphan_add(handle, inode); - up_write(&EXT4_I(inode)->xattr_sem); + ext4_write_unlock_xattr(inode, &no_expand); sem_held =3D 0; ext4_journal_stop(handle); handle =3D NULL; @@ -628,7 +627,7 @@ out: page_cache_release(page); } if (sem_held) - up_write(&EXT4_I(inode)->xattr_sem); + ext4_write_unlock_xattr(inode, &no_expand); if (handle) ext4_journal_stop(handle); brelse(iloc.bh); @@ -721,7 +720,7 @@ convert: int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned l= en, unsigned copied, struct page *page) { - int ret; + int ret, no_expand; void *kaddr; struct ext4_iloc iloc; =20 @@ -739,7 +738,7 @@ int ext4_write_inline_data_end(struct inode *inode, lof= f_t pos, unsigned len, goto out; } =20 - down_write(&EXT4_I(inode)->xattr_sem); + ext4_write_lock_xattr(inode, &no_expand); BUG_ON(!ext4_has_inline_data(inode)); =20 kaddr =3D kmap_atomic(page); @@ -749,7 +748,7 @@ int ext4_write_inline_data_end(struct inode *inode, lof= f_t pos, unsigned len, /* clear page dirty so that writepages wouldn't work for us. */ ClearPageDirty(page); =20 - up_write(&EXT4_I(inode)->xattr_sem); + ext4_write_unlock_xattr(inode, &no_expand); brelse(iloc.bh); out: return copied; @@ -760,7 +759,7 @@ ext4_journalled_write_inline_data(struct inode *inode, unsigned len, struct page *page) { - int ret; + int ret, no_expand; void *kaddr; struct ext4_iloc iloc; =20 @@ -770,11 +769,11 @@ ext4_journalled_write_inline_data(struct inode *inode, return NULL; } =20 - down_write(&EXT4_I(inode)->xattr_sem); + ext4_write_lock_xattr(inode, &no_expand); kaddr =3D kmap_atomic(page); ext4_write_inline_data(inode, &iloc, kaddr, 0, len); kunmap_atomic(kaddr); - up_write(&EXT4_I(inode)->xattr_sem); + ext4_write_unlock_xattr(inode, &no_expand); =20 return iloc.bh; } @@ -932,8 +931,15 @@ int ext4_da_write_inline_data_end(struct inode *inode,= loff_t pos, struct page *page) { int i_size_changed =3D 0; + int ret; =20 - copied =3D ext4_write_inline_data_end(inode, pos, len, copied, page); + ret =3D ext4_write_inline_data_end(inode, pos, len, copied, page); + if (ret < 0) { + unlock_page(page); + put_page(page); + return ret; + } + copied =3D ret; =20 /* * No need to use i_size_read() here, the i_size @@ -1238,7 +1244,7 @@ out: int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry, struct inode *inode) { - int ret, inline_size; + int ret, inline_size, no_expand; void *inline_start; struct ext4_iloc iloc; struct inode *dir =3D dentry->d_parent->d_inode; @@ -1247,7 +1253,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struc= t dentry *dentry, if (ret) return ret; =20 - down_write(&EXT4_I(dir)->xattr_sem); + ext4_write_lock_xattr(dir, &no_expand); if (!ext4_has_inline_data(dir)) goto out; =20 @@ -1292,7 +1298,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struc= t dentry *dentry, =20 out: ext4_mark_inode_dirty(handle, dir); - up_write(&EXT4_I(dir)->xattr_sem); + ext4_write_unlock_xattr(dir, &no_expand); brelse(iloc.bh); return ret; } @@ -1648,7 +1654,7 @@ int ext4_delete_inline_entry(handle_t *handle, struct buffer_head *bh, int *has_inline_data) { - int err, inline_size; + int err, inline_size, no_expand; struct ext4_iloc iloc; void *inline_start; =20 @@ -1656,7 +1662,7 @@ int ext4_delete_inline_entry(handle_t *handle, if (err) return err; =20 - down_write(&EXT4_I(dir)->xattr_sem); + ext4_write_lock_xattr(dir, &no_expand); if (!ext4_has_inline_data(dir)) { *has_inline_data =3D 0; goto out; @@ -1691,7 +1697,7 @@ int ext4_delete_inline_entry(handle_t *handle, =20 ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size); out: - up_write(&EXT4_I(dir)->xattr_sem); + ext4_write_unlock_xattr(dir, &no_expand); brelse(iloc.bh); if (err !=3D -ENOENT) ext4_std_error(dir->i_sb, err); @@ -1790,11 +1796,11 @@ out: =20 int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) { - int ret; + int ret, no_expand; =20 - down_write(&EXT4_I(inode)->xattr_sem); + ext4_write_lock_xattr(inode, &no_expand); ret =3D ext4_destroy_inline_data_nolock(handle, inode); - up_write(&EXT4_I(inode)->xattr_sem); + ext4_write_unlock_xattr(inode, &no_expand); =20 return ret; } @@ -1872,7 +1878,7 @@ out: void ext4_inline_data_truncate(struct inode *inode, int *has_inline) { handle_t *handle; - int inline_size, value_len, needed_blocks; + int inline_size, value_len, needed_blocks, no_expand; size_t i_size; void *value =3D NULL; struct ext4_xattr_ibody_find is =3D { @@ -1889,7 +1895,7 @@ void ext4_inline_data_truncate(struct inode *inode, i= nt *has_inline) if (IS_ERR(handle)) return; =20 - down_write(&EXT4_I(inode)->xattr_sem); + ext4_write_lock_xattr(inode, &no_expand); if (!ext4_has_inline_data(inode)) { *has_inline =3D 0; ext4_journal_stop(handle); @@ -1947,7 +1953,7 @@ out_error: up_write(&EXT4_I(inode)->i_data_sem); out: brelse(is.iloc.bh); - up_write(&EXT4_I(inode)->xattr_sem); + ext4_write_unlock_xattr(inode, &no_expand); kfree(value); if (inode->i_nlink) ext4_orphan_del(handle, inode); @@ -1963,7 +1969,7 @@ out: =20 int ext4_convert_inline_data(struct inode *inode) { - int error, needed_blocks; + int error, needed_blocks, no_expand; handle_t *handle; struct ext4_iloc iloc; =20 @@ -1985,15 +1991,10 @@ int ext4_convert_inline_data(struct inode *inode) goto out_free; } =20 - down_write(&EXT4_I(inode)->xattr_sem); - if (!ext4_has_inline_data(inode)) { - up_write(&EXT4_I(inode)->xattr_sem); - goto out; - } - - error =3D ext4_convert_inline_data_nolock(handle, inode, &iloc); - up_write(&EXT4_I(inode)->xattr_sem); -out: + ext4_write_lock_xattr(inode, &no_expand); + if (ext4_has_inline_data(inode)) + error =3D ext4_convert_inline_data_nolock(handle, inode, &iloc); + ext4_write_unlock_xattr(inode, &no_expand); ext4_journal_stop(handle); out_free: brelse(iloc.bh); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 898e9659ebf1..7719a2a52c97 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1118,8 +1118,11 @@ static int ext4_write_end(struct file *file, if (ext4_has_inline_data(inode)) { ret =3D ext4_write_inline_data_end(inode, pos, len, copied, page); - if (ret < 0) + if (ret < 0) { + unlock_page(page); + put_page(page); goto errout; + } copied =3D ret; } else copied =3D block_write_end(file, mapping, pos, @@ -1166,6 +1169,40 @@ errout: return ret ? ret : copied; } =20 +/* + * This is a private version of page_zero_new_buffers() which doesn't + * set the buffer to be dirty, since in data=3Djournalled mode we need + * to call ext4_handle_dirty_metadata() instead. + */ +static void ext4_journalled_zero_new_buffers(handle_t *handle, + struct page *page, + unsigned from, unsigned to) +{ + unsigned int block_start =3D 0, block_end; + struct buffer_head *head, *bh; + + bh =3D head =3D page_buffers(page); + do { + block_end =3D block_start + bh->b_size; + if (buffer_new(bh)) { + if (block_end > from && block_start < to) { + if (!PageUptodate(page)) { + unsigned start, size; + + start =3D max(from, block_start); + size =3D min(to, block_end) - start; + + zero_user(page, start, size); + write_end_fn(handle, bh); + } + clear_buffer_new(bh); + } + } + block_start =3D block_end; + bh =3D bh->b_this_page; + } while (bh !=3D head); +} + static int ext4_journalled_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, @@ -1184,18 +1221,25 @@ static int ext4_journalled_write_end(struct file *f= ile, =20 BUG_ON(!ext4_handle_valid(handle)); =20 - if (ext4_has_inline_data(inode)) - copied =3D ext4_write_inline_data_end(inode, pos, len, - copied, page); - else { - if (copied < len) { - if (!PageUptodate(page)) - copied =3D 0; - page_zero_new_buffers(page, from+copied, to); + if (ext4_has_inline_data(inode)) { + ret =3D ext4_write_inline_data_end(inode, pos, len, + copied, page); + if (ret < 0) { + unlock_page(page); + put_page(page); + goto errout; } - + copied =3D ret; + } else if (unlikely(copied < len) && !PageUptodate(page)) { + copied =3D 0; + ext4_journalled_zero_new_buffers(handle, page, from, to); + } else { + if (unlikely(copied < len)) + ext4_journalled_zero_new_buffers(handle, page, + from + copied, to); ret =3D ext4_walk_page_buffers(handle, page_buffers(page), from, - to, &partial, write_end_fn); + from + copied, &partial, + write_end_fn); if (!partial) SetPageUptodate(page); } @@ -1218,6 +1262,7 @@ static int ext4_journalled_write_end(struct file *fil= e, */ ext4_orphan_add(handle, inode); =20 +errout: ret2 =3D ext4_journal_stop(handle); if (!ret) ret =3D ret2; @@ -5062,8 +5107,6 @@ int ext4_mark_inode_dirty(handle_t *handle, struct in= ode *inode) sbi->s_want_extra_isize, iloc, handle); if (ret) { - ext4_set_inode_state(inode, - EXT4_STATE_NO_EXPAND); if (mnt_count !=3D le16_to_cpu(sbi->s_es->s_mnt_count)) { ext4_warning(inode->i_sb, diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 425dd618a9e2..e634db9fa351 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3091,6 +3091,13 @@ ext4_mb_normalize_request(struct ext4_allocation_con= text *ac, if (ar->pright && start + size - 1 >=3D ar->lright) size -=3D start + size - ar->lright; =20 + /* + * Trim allocation request for filesystems with artificially small + * groups. + */ + if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)) + size =3D EXT4_BLOCKS_PER_GROUP(ac->ac_sb); + end =3D start + size; =20 /* check we don't cross already preallocated blocks */ diff --git a/fs/ext4/super.c b/fs/ext4/super.c index c608d805f509..af0267fbecf4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -783,6 +783,7 @@ static void ext4_put_super(struct super_block *sb) { struct ext4_sb_info *sbi =3D EXT4_SB(sb); struct ext4_super_block *es =3D sbi->s_es; + int aborted =3D 0; int i, err; =20 ext4_unregister_li_request(sb); @@ -792,9 +793,10 @@ static void ext4_put_super(struct super_block *sb) destroy_workqueue(sbi->rsv_conversion_wq); =20 if (sbi->s_journal) { + aborted =3D is_journal_aborted(sbi->s_journal); err =3D jbd2_journal_destroy(sbi->s_journal); sbi->s_journal =3D NULL; - if (err < 0) + if ((err < 0) && !aborted) ext4_abort(sb, "Couldn't clean up the journal"); } =20 @@ -805,7 +807,7 @@ static void ext4_put_super(struct super_block *sb) ext4_ext_release(sb); ext4_xattr_put_super(sb); =20 - if (!(sb->s_flags & MS_RDONLY)) { + if (!(sb->s_flags & MS_RDONLY) && !aborted) { EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); es->s_state =3D cpu_to_le16(sbi->s_mount_state); } @@ -3914,7 +3916,7 @@ static int ext4_fill_super(struct super_block *sb, vo= id *data, int silent) db_count =3D (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / EXT4_DESC_PER_BLOCK(sb); if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG)) { - if (le32_to_cpu(es->s_first_meta_bg) >=3D db_count) { + if (le32_to_cpu(es->s_first_meta_bg) > db_count) { ext4_msg(sb, KERN_WARNING, "first meta block group too large: %u " "(group descriptor block count %u)", @@ -4036,7 +4038,8 @@ static int ext4_fill_super(struct super_block *sb, vo= id *data, int silent) */ if (!test_opt(sb, NOLOAD) && EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { - if (ext4_load_journal(sb, es, journal_devnum)) + err =3D ext4_load_journal(sb, es, journal_devnum); + if (err) goto failed_mount3; } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 2d1e5803839f..ff8fd85edcfe 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1106,16 +1106,14 @@ ext4_xattr_set_handle(handle_t *handle, struct inod= e *inode, int name_index, struct ext4_xattr_block_find bs =3D { .s =3D { .not_found =3D -ENODATA, }, }; - unsigned long no_expand; + int no_expand; int error; =20 if (!name) return -EINVAL; if (strlen(name) > 255) return -ERANGE; - down_write(&EXT4_I(inode)->xattr_sem); - no_expand =3D ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND); - ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); + ext4_write_lock_xattr(inode, &no_expand); =20 error =3D ext4_reserve_inode_write(handle, inode, &is.iloc); if (error) @@ -1176,7 +1174,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode = *inode, int name_index, ext4_xattr_update_super_block(handle, inode->i_sb); inode->i_ctime =3D ext4_current_time(inode); if (!value) - ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); + no_expand =3D 0; error =3D ext4_mark_iloc_dirty(handle, inode, &is.iloc); /* * The bh is consumed by ext4_mark_iloc_dirty, even with @@ -1190,9 +1188,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode = *inode, int name_index, cleanup: brelse(is.iloc.bh); brelse(bs.bh); - if (no_expand =3D=3D 0) - ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); - up_write(&EXT4_I(inode)->xattr_sem); + ext4_write_unlock_xattr(inode, &no_expand); return error; } =20 @@ -1275,13 +1271,14 @@ int ext4_expand_extra_isize_ea(struct inode *inode,= int new_extra_isize, void *base, *start, *end; int extra_isize =3D 0, error =3D 0, tried_min_extra_isize =3D 0; int s_min_extra_isize =3D le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_e= xtra_isize); + int no_expand; =20 - down_write(&EXT4_I(inode)->xattr_sem); -retry: - if (EXT4_I(inode)->i_extra_isize >=3D new_extra_isize) { - up_write(&EXT4_I(inode)->xattr_sem); + if (ext4_write_trylock_xattr(inode, &no_expand) =3D=3D 0) return 0; - } + +retry: + if (EXT4_I(inode)->i_extra_isize >=3D new_extra_isize) + goto out; =20 header =3D IHDR(inode, raw_inode); entry =3D IFIRST(header); @@ -1306,8 +1303,7 @@ retry: (void *)header, total_ino, inode->i_sb->s_blocksize); EXT4_I(inode)->i_extra_isize =3D new_extra_isize; - error =3D 0; - goto cleanup; + goto out; } =20 /* @@ -1467,7 +1463,8 @@ retry: kfree(bs); } brelse(bh); - up_write(&EXT4_I(inode)->xattr_sem); +out: + ext4_write_unlock_xattr(inode, &no_expand); return 0; =20 cleanup: @@ -1478,7 +1475,11 @@ cleanup: kfree(is); kfree(bs); brelse(bh); - up_write(&EXT4_I(inode)->xattr_sem); + /* + * Inode size expansion failed; don't try again + */ + no_expand =3D 1; + ext4_write_unlock_xattr(inode, &no_expand); return error; } =20 diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 29bedf5589f6..2e8f23e78bc2 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h @@ -98,6 +98,38 @@ extern const struct xattr_handler ext4_xattr_user_handle= r; extern const struct xattr_handler ext4_xattr_trusted_handler; extern const struct xattr_handler ext4_xattr_security_handler; =20 +/* + * The EXT4_STATE_NO_EXPAND is overloaded and used for two purposes. + * The first is to signal that there the inline xattrs and data are + * taking up so much space that we might as well not keep trying to + * expand it. The second is that xattr_sem is taken for writing, so + * we shouldn't try to recurse into the inode expansion. For this + * second case, we need to make sure that we take save and restore the + * NO_EXPAND state flag appropriately. + */ +static inline void ext4_write_lock_xattr(struct inode *inode, int *save) +{ + down_write(&EXT4_I(inode)->xattr_sem); + *save =3D ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND); + ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); +} + +static inline int ext4_write_trylock_xattr(struct inode *inode, int *save) +{ + if (down_write_trylock(&EXT4_I(inode)->xattr_sem) =3D=3D 0) + return 0; + *save =3D ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND); + ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND); + return 1; +} + +static inline void ext4_write_unlock_xattr(struct inode *inode, int *save) +{ + if (*save =3D=3D 0) + ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND); + up_write(&EXT4_I(inode)->xattr_sem); +} + extern ssize_t ext4_listxattr(struct dentry *, char *, size_t); =20 extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_= t); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 58df97e174d0..22e6307b25e2 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -489,6 +489,9 @@ struct f2fs_sb_info { struct f2fs_gc_kthread *gc_thread; /* GC thread */ unsigned int cur_victim_sec; /* current victim section num */ =20 + /* threshold for converting bg victims for fg */ + u64 fggc_threshold; + /* maximum # of trials to find a victim segment for SSR and GC */ unsigned int max_victim_search; =20 diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b90dbe55403a..6267817dfe87 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -163,7 +163,8 @@ static void select_policy(struct f2fs_sb_info *sbi, int= gc_type, p->ofs_unit =3D sbi->segs_per_sec; } =20 - if (p->max_search > sbi->max_victim_search) + /* we need to check every dirty segments in the FG_GC case */ + if (gc_type !=3D FG_GC && p->max_search > sbi->max_victim_search) p->max_search =3D sbi->max_victim_search; =20 p->offset =3D sbi->last_victim[p->gc_mode]; @@ -186,7 +187,6 @@ static unsigned int get_max_cost(struct f2fs_sb_info *s= bi, static unsigned int check_bg_victims(struct f2fs_sb_info *sbi) { struct dirty_seglist_info *dirty_i =3D DIRTY_I(sbi); - unsigned int hint =3D 0; unsigned int secno; =20 /* @@ -194,11 +194,13 @@ static unsigned int check_bg_victims(struct f2fs_sb_i= nfo *sbi) * selected by background GC before. * Those segments guarantee they have small valid blocks. */ -next: - secno =3D find_next_bit(dirty_i->victim_secmap, TOTAL_SECS(sbi), hint++); - if (secno < TOTAL_SECS(sbi)) { + for_each_set_bit(secno, dirty_i->victim_secmap, TOTAL_SECS(sbi)) { if (sec_usage_check(sbi, secno)) - goto next; + continue; + + if (no_fggc_candidate(sbi, secno)) + continue; + clear_bit(secno, dirty_i->victim_secmap); return secno * sbi->segs_per_sec; } @@ -305,6 +307,9 @@ static int get_victim_by_default(struct f2fs_sb_info *s= bi, continue; if (gc_type =3D=3D BG_GC && test_bit(secno, dirty_i->victim_secmap)) continue; + if (gc_type =3D=3D FG_GC && p.alloc_mode =3D=3D LFS && + no_fggc_candidate(sbi, secno)) + continue; =20 cost =3D get_gc_cost(sbi, segno, &p); =20 @@ -736,7 +741,18 @@ stop: =20 void build_gc_manager(struct f2fs_sb_info *sbi) { + u64 main_count, resv_count, ovp_count, blocks_per_sec; + DIRTY_I(sbi)->v_ops =3D &default_v_ops; + + /* threshold of # of valid blocks in a section for victims of FG_GC */ + main_count =3D SM_I(sbi)->main_segments << sbi->log_blocks_per_seg; + resv_count =3D SM_I(sbi)->reserved_segments << sbi->log_blocks_per_seg; + ovp_count =3D SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg; + blocks_per_sec =3D sbi->blocks_per_seg * sbi->segs_per_sec; + + sbi->fggc_threshold =3D div_u64((main_count - ovp_count) * blocks_per_sec, + (main_count - resv_count)); } =20 int __init create_gc_caches(void) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d04613df710a..00dec8840068 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -437,17 +437,12 @@ static void add_discard_addrs(struct f2fs_sb_info *sb= i, static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) { struct dirty_seglist_info *dirty_i =3D DIRTY_I(sbi); - unsigned int segno =3D -1; + unsigned int segno; unsigned int total_segs =3D TOTAL_SEGS(sbi); =20 mutex_lock(&dirty_i->seglist_lock); - while (1) { - segno =3D find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, - segno + 1); - if (segno >=3D total_segs) - break; + for_each_set_bit(segno, dirty_i->dirty_segmap[PRE], total_segs) __set_test_and_free(sbi, segno); - } mutex_unlock(&dirty_i->seglist_lock); } =20 @@ -1532,7 +1527,7 @@ void flush_sit_entries(struct f2fs_sb_info *sbi) struct page *page =3D NULL; struct f2fs_sit_block *raw_sit =3D NULL; unsigned int start =3D 0, end =3D 0; - unsigned int segno =3D -1; + unsigned int segno; bool flushed; =20 mutex_lock(&curseg->curseg_mutex); @@ -1544,7 +1539,7 @@ void flush_sit_entries(struct f2fs_sb_info *sbi) */ flushed =3D flush_sits_in_journal(sbi); =20 - while ((segno =3D find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) { + for_each_set_bit(segno, bitmap, nsegs) { struct seg_entry *se =3D get_seg_entry(sbi, segno); int sit_offset, offset; =20 diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index 7091204680f4..64f2d83958ba 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -651,6 +651,15 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info= *sbi, int base, int type) - (base + 1) + type; } =20 +static inline bool no_fggc_candidate(struct f2fs_sb_info *sbi, + unsigned int secno) +{ + if (get_valid_blocks(sbi, secno, sbi->segs_per_sec) >=3D + sbi->fggc_threshold) + return true; + return false; +} + static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int = secno) { if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec =3D=3D secno)) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 4e9cfbc453c7..d583c976fff2 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -136,6 +136,7 @@ static void fuse_file_put(struct fuse_file *ff, bool sy= nc) path_put(&req->misc.release.path); fuse_put_request(ff->fc, req); } else if (sync) { + req->force =3D 1; req->background =3D 0; fuse_request_send(ff->fc, req); path_put(&req->misc.release.path); diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index f156390113db..3a5c29a5733d 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1784,7 +1784,9 @@ static void __jbd2_journal_temp_unlink_buffer(struct = journal_head *jh) =20 __blist_del_buffer(list, jh); jh->b_jlist =3D BJ_None; - if (test_clear_buffer_jbddirty(bh)) + if (transaction && is_journal_aborted(transaction->t_journal)) + clear_buffer_jbddirty(bh); + else if (test_clear_buffer_jbddirty(bh)) mark_buffer_dirty(bh); /* Expose it to the VM */ } =20 diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e07fbf97a93b..666eadb0447c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2233,6 +2233,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opend= ata *opendata, ret =3D PTR_ERR(state); if (IS_ERR(state)) goto out; + ctx->state =3D state; if (server->caps & NFS_CAP_POSIX_LOCK) set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); =20 @@ -2255,7 +2256,6 @@ static int _nfs4_open_and_get_state(struct nfs4_opend= ata *opendata, if (ret !=3D 0) goto out; =20 - ctx->state =3D state; if (dentry->d_inode =3D=3D state->inode) { nfs_inode_attach_open_context(ctx); if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) @@ -4444,7 +4444,7 @@ out: */ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, siz= e_t buflen) { - struct page *pages[NFS4ACL_MAXPAGES] =3D {NULL, }; + struct page *pages[NFS4ACL_MAXPAGES + 1] =3D {NULL, }; struct nfs_getaclargs args =3D { .fh =3D NFS_FH(inode), .acl_pages =3D pages, @@ -4458,13 +4458,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode = *inode, void *buf, size_t bu .rpc_argp =3D &args, .rpc_resp =3D &res, }; - unsigned int npages =3D DIV_ROUND_UP(buflen, PAGE_SIZE); + unsigned int npages =3D DIV_ROUND_UP(buflen, PAGE_SIZE) + 1; int ret =3D -ENOMEM, i; =20 - /* As long as we're doing a round trip to the server anyway, - * let's be prepared for a page of acl data. */ - if (npages =3D=3D 0) - npages =3D 1; if (npages > ARRAY_SIZE(pages)) return -ERANGE; =20 diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 939ae606cfa4..de6d473ea645 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -165,8 +165,10 @@ static int nfs4_stat_to_errno(int); open_owner_id_maxsz + \ encode_opentype_maxsz + \ encode_claim_null_maxsz) +#define decode_space_limit_maxsz (3) #define decode_ace_maxsz (3 + nfs4_owner_maxsz) #define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \ + decode_space_limit_maxsz + \ decode_ace_maxsz) #define decode_change_info_maxsz (5) #define decode_open_maxsz (op_decode_hdr_maxsz + \ @@ -2502,7 +2504,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req,= struct xdr_stream *xdr, encode_compound_hdr(xdr, req, &hdr); encode_sequence(xdr, &args->seq_args, &hdr); encode_putfh(xdr, args->fh, &hdr); - replen =3D hdr.replen + op_decode_hdr_maxsz + 1; + replen =3D hdr.replen + op_decode_hdr_maxsz; encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr); =20 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e6c01e80325e..d9fa85ebc8ac 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -363,6 +363,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32= *p, { unsigned int len, v, hdr, dlen; u32 max_blocksize =3D svc_max_payload(rqstp); + struct kvec *head =3D rqstp->rq_arg.head; =20 p =3D decode_fh(p, &args->fh); if (!p) @@ -372,6 +373,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32= *p, args->count =3D ntohl(*p++); args->stable =3D ntohl(*p++); len =3D args->len =3D ntohl(*p++); + if ((void *)p > head->iov_base + head->iov_len) + return 0; /* * The count must equal the amount of data passed. */ @@ -382,9 +385,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32= *p, * Check to make sure that we got the right number of * bytes. */ - hdr =3D (void*)p - rqstp->rq_arg.head[0].iov_base; - dlen =3D rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len - - hdr; + hdr =3D (void*)p - head->iov_base; + dlen =3D head->iov_len + rqstp->rq_arg.page_len - hdr; /* * Round the length of the data which was specified up to * the next multiple of XDR units and then compare that @@ -401,7 +403,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32= *p, len =3D args->len =3D max_blocksize; } rqstp->rq_vec[0].iov_base =3D (void*)p; - rqstp->rq_vec[0].iov_len =3D rqstp->rq_arg.head[0].iov_len - hdr; + rqstp->rq_vec[0].iov_len =3D head->iov_len - hdr; v =3D 0; while (len > rqstp->rq_vec[v].iov_len) { len -=3D rqstp->rq_vec[v].iov_len; @@ -476,6 +478,8 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be= 32 *p, /* first copy and check from the first page */ old =3D (char*)p; vec =3D &rqstp->rq_arg.head[0]; + if ((void *)old > vec->iov_base + vec->iov_len) + return 0; avail =3D vec->iov_len - (old - (char*)vec->iov_base); while (len && avail && *old) { *new++ =3D *old++; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 2f2edbb2a4a3..96c3dc200e80 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -642,6 +642,37 @@ static __be32 map_new_errors(u32 vers, __be32 nfserr) return nfserr; } =20 +/* + * A write procedure can have a large argument, and a read procedure can + * have a large reply, but no NFSv2 or NFSv3 procedure has argument and + * reply that can both be larger than a page. The xdr code has taken + * advantage of this assumption to be a sloppy about bounds checking in + * some cases. Pending a rewrite of the NFSv2/v3 xdr code to fix that + * problem, we enforce these assumptions here: + */ +static bool nfs_request_too_big(struct svc_rqst *rqstp, + struct svc_procedure *proc) +{ + /* + * The ACL code has more careful bounds-checking and is not + * susceptible to this problem: + */ + if (rqstp->rq_prog !=3D NFS_PROGRAM) + return false; + /* + * Ditto NFSv4 (which can in theory have argument and reply both + * more than a page): + */ + if (rqstp->rq_vers >=3D 4) + return false; + /* The reply will be small, we're OK: */ + if (proc->pc_xdrressize > 0 && + proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE)) + return false; + + return rqstp->rq_arg.len > PAGE_SIZE; +} + int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) { @@ -654,6 +685,11 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) rqstp->rq_vers, rqstp->rq_proc); proc =3D rqstp->rq_procinfo; =20 + if (nfs_request_too_big(rqstp, proc)) { + dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers); + *statp =3D rpc_garbage_args; + return 1; + } /* * Give the xdr decoder a chance to change this if it wants * (necessary in the NFSv4.0 compound case) diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 1ac306b769df..a41c3572bde5 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -281,6 +281,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 = *p, struct nfsd_writeargs *args) { unsigned int len, hdr, dlen; + struct kvec *head =3D rqstp->rq_arg.head; int v; =20 p =3D decode_fh(p, &args->fh); @@ -301,9 +302,10 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32= *p, * Check to make sure that we got the right number of * bytes. */ - hdr =3D (void*)p - rqstp->rq_arg.head[0].iov_base; - dlen =3D rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len - - hdr; + hdr =3D (void*)p - head->iov_base; + if (hdr > head->iov_len) + return 0; + dlen =3D head->iov_len + rqstp->rq_arg.page_len - hdr; =20 /* * Round the length of the data which was specified up to @@ -317,7 +319,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 = *p, return 0; =20 rqstp->rq_vec[0].iov_base =3D (void*)p; - rqstp->rq_vec[0].iov_len =3D rqstp->rq_arg.head[0].iov_len - hdr; + rqstp->rq_vec[0].iov_len =3D head->iov_len - hdr; v =3D 0; while (len > rqstp->rq_vec[v].iov_len) { len -=3D rqstp->rq_vec[v].iov_len; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 521f717b4a99..5c7f72cea0de 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -407,7 +407,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp= , struct iattr *iap, __be32 err; int host_err; bool get_write_count; - int size_change =3D 0; + bool size_change =3D (iap->ia_valid & ATTR_SIZE); =20 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) accmode |=3D NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; @@ -420,11 +420,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *f= hp, struct iattr *iap, /* Get inode */ err =3D fh_verify(rqstp, fhp, ftype, accmode); if (err) - goto out; + return err; if (get_write_count) { host_err =3D fh_want_write(fhp); if (host_err) - return nfserrno(host_err); + goto out; } =20 dentry =3D fhp->fh_dentry; @@ -435,40 +435,65 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *f= hp, struct iattr *iap, iap->ia_valid &=3D ~ATTR_MODE; =20 if (!iap->ia_valid) - goto out; + return 0; =20 nfsd_sanitize_attrs(dentry, iap); =20 + if (check_guard && guardtime !=3D inode->i_ctime.tv_sec) + return nfserr_notsync; + /* * The size case is special, it changes the file in addition to the - * attributes. + * attributes, and file systems don't expect it to be mixed with + * "random" attribute changes. We thus split out the size change + * into a separate call to ->setattr, and do the rest as a separate + * setattr call. */ - if (iap->ia_valid & ATTR_SIZE) { + if (size_change) { err =3D nfsd_get_write_access(rqstp, fhp, iap); if (err) - goto out; - size_change =3D 1; + return err; } =20 - iap->ia_valid |=3D ATTR_CTIME; + fh_lock(fhp); + if (size_change) { + /* + * RFC5661, Section 18.30.4: + * Changing the size of a file with SETATTR indirectly + * changes the time_modify and change attributes. + * + * (and similar for the older RFCs) + */ + struct iattr size_attr =3D { + .ia_valid =3D ATTR_SIZE | ATTR_CTIME | ATTR_MTIME, + .ia_size =3D iap->ia_size, + }; =20 - if (check_guard && guardtime !=3D inode->i_ctime.tv_sec) { - err =3D nfserr_notsync; - goto out_put_write_access; + host_err =3D notify_change(dentry, &size_attr, NULL); + if (host_err) + goto out_unlock; + iap->ia_valid &=3D ~ATTR_SIZE; + + /* + * Avoid the additional setattr call below if the only other + * attribute that the client sends is the mtime, as we update + * it as part of the size change above. + */ + if ((iap->ia_valid & ~ATTR_MTIME) =3D=3D 0) + goto out_unlock; } =20 - fh_lock(fhp); + iap->ia_valid |=3D ATTR_CTIME; host_err =3D notify_change(dentry, iap, NULL); - fh_unlock(fhp); - err =3D nfserrno(host_err); =20 -out_put_write_access: +out_unlock: + fh_unlock(fhp); if (size_change) put_write_access(inode); - if (!err) - commit_metadata(fhp); out: - return err; + if (!host_err) + commit_metadata(fhp); + return nfserrno(host_err); } =20 #if defined(CONFIG_NFSD_V4) diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index 9b6f32a6cad1..66fc42c57aff 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -164,6 +164,16 @@ static inline struct ahash_instance *ahash_alloc_insta= nce( return crypto_alloc_instance2(name, alg, ahash_instance_headroom()); } =20 +static inline void ahash_request_complete(struct ahash_request *req, int e= rr) +{ + req->base.complete(&req->base, err); +} + +static inline u32 ahash_request_flags(struct ahash_request *req) +{ + return req->base.flags; +} + static inline struct crypto_ahash *crypto_spawn_ahash( struct crypto_ahash_spawn *spawn) { diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h index 784304b222b3..f0d0cc763236 100644 --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h @@ -203,4 +203,24 @@ static inline bool static_key_enabled(struct static_ke= y *key) return static_key_count(key) > 0; } =20 +static inline void static_key_enable(struct static_key *key) +{ + int count =3D static_key_count(key); + + WARN_ON_ONCE(count < 0 || count > 1); + + if (!count) + static_key_slow_inc(key); +} + +static inline void static_key_disable(struct static_key *key) +{ + int count =3D static_key_count(key); + + WARN_ON_ONCE(count < 0 || count > 1); + + if (count) + static_key_slow_dec(key); +} + #endif /* _LINUX_JUMP_LABEL_H */ diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 294e23c243c6..1281a65c2305 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -355,7 +355,8 @@ static inline int nlm_privileged_requester(const struct= svc_rqst *rqstp) static inline int nlm_compare_locks(const struct file_lock *fl1, const struct file_lock *fl2) { - return fl1->fl_pid =3D=3D fl2->fl_pid + return file_inode(fl1->fl_file) =3D=3D file_inode(fl2->fl_file) + && fl1->fl_pid =3D=3D fl2->fl_pid && fl1->fl_owner =3D=3D fl2->fl_owner && fl1->fl_start =3D=3D fl2->fl_start && fl1->fl_end =3D=3D fl2->fl_end diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h index c8450366c130..b9a6cdf7ba67 100644 --- a/include/linux/mlx4/cmd.h +++ b/include/linux/mlx4/cmd.h @@ -236,7 +236,7 @@ struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct = mlx4_dev *dev); void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *= mailbox); =20 u32 mlx4_comm_get_version(void); -int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac); +int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u8 *mac); int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 = qos); int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool sett= ing); int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla= _vf_info *ivf); diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h index 022055c8fb26..4a78bdee4ed4 100644 --- a/include/linux/mlx4/driver.h +++ b/include/linux/mlx4/driver.h @@ -76,4 +76,14 @@ static inline u64 mlx4_mac_to_u64(u8 *addr) return mac; } =20 +static inline void mlx4_u64_to_mac(u8 *addr, u64 mac) +{ + int i; + + for (i =3D ETH_ALEN; i > 0; i--) { + addr[i - 1] =3D mac & 0xFF; + mac >>=3D 8; + } +} + #endif /* MLX4_DRIVER_H */ diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 10b57940dc62..ed204eba0e87 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -293,7 +293,6 @@ static inline struct page *find_get_page_flags(struct a= ddress_space *mapping, =20 /** * find_lock_page - locate, pin and lock a pagecache page - * pagecache_get_page - find and get a page reference * @mapping: the address_space to search * @offset: the page index * diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h index 760399a470bd..340c31ed84d7 100644 --- a/include/linux/ww_mutex.h +++ b/include/linux/ww_mutex.h @@ -51,10 +51,10 @@ struct ww_mutex { }; =20 #ifdef CONFIG_DEBUG_LOCK_ALLOC -# define __WW_CLASS_MUTEX_INITIALIZER(lockname, ww_class) \ - , .ww_class =3D &ww_class +# define __WW_CLASS_MUTEX_INITIALIZER(lockname, class) \ + , .ww_class =3D class #else -# define __WW_CLASS_MUTEX_INITIALIZER(lockname, ww_class) +# define __WW_CLASS_MUTEX_INITIALIZER(lockname, class) #endif =20 #define __WW_CLASS_INITIALIZER(ww_class) \ @@ -63,7 +63,7 @@ struct ww_mutex { , .mutex_name =3D #ww_class "_mutex" } =20 #define __WW_MUTEX_INITIALIZER(lockname, class) \ - { .base =3D { \__MUTEX_INITIALIZER(lockname) } \ + { .base =3D __MUTEX_INITIALIZER(lockname.base) \ __WW_CLASS_MUTEX_INITIALIZER(lockname, class) } =20 #define DEFINE_WW_CLASS(classname) \ diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index 7e071a6abb34..5d60be66c05a 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h @@ -137,12 +137,12 @@ struct ib_sa_path_rec { union ib_gid sgid; __be16 dlid; __be16 slid; - int raw_traffic; + u8 raw_traffic; /* reserved */ __be32 flow_label; u8 hop_limit; u8 traffic_class; - int reversible; + u8 reversible; u8 numb_path; __be16 pkey; __be16 qos_class; @@ -196,7 +196,7 @@ struct ib_sa_mcmember_rec { u8 hop_limit; u8 scope; u8 join_state; - int proxy_join; + u8 proxy_join; }; =20 /* Service Record Component Mask Sec 15.2.5.14 Ver 1.1 */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f2c0bcc4ba6c..2fc44b2466f3 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -196,14 +196,12 @@ struct static_key sched_feat_keys[__SCHED_FEAT_NR] = =3D { =20 static void sched_feat_disable(int i) { - if (static_key_enabled(&sched_feat_keys[i])) - static_key_slow_dec(&sched_feat_keys[i]); + static_key_disable(&sched_feat_keys[i]); } =20 static void sched_feat_enable(int i) { - if (!static_key_enabled(&sched_feat_keys[i])) - static_key_slow_inc(&sched_feat_keys[i]); + static_key_enable(&sched_feat_keys[i]); } #else static void sched_feat_disable(int i) { }; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8df0ed9af291..a64a7073bffe 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1567,7 +1567,7 @@ static void __trace_find_cmdline(int pid, char comm[]) =20 map =3D savedcmd->map_pid_to_cmdline[pid]; if (map !=3D NO_CMDLINE_MAP) - strcpy(comm, get_saved_cmdlines(map)); + strlcpy(comm, get_saved_cmdlines(map), TASK_COMM_LEN); else strcpy(comm, "<...>"); } diff --git a/mm/filemap.c b/mm/filemap.c index 31b5b25c3d2d..128f3d34d874 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -795,9 +795,12 @@ void page_endio(struct page *page, int rw, int err) unlock_page(page); } else { /* rw =3D=3D WRITE */ if (err) { + struct address_space *mapping; + SetPageError(page); - if (page->mapping) - mapping_set_error(page->mapping, err); + mapping =3D page_mapping(page); + if (mapping) + mapping_set_error(mapping, err); } end_page_writeback(page); } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index abc04a803aa8..4397b89155f8 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1226,7 +1226,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_str= uct *vma, VM_BUG_ON_PAGE(!PageHead(page), page); =20 if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, page, flags)) - goto out; + return NULL; =20 if (flags & FOLL_TOUCH) { pmd_t _pmd; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 7832affffda5..ca088a55b902 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1559,7 +1559,6 @@ COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, p= olicy, COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, = nmask, compat_ulong_t, maxnode) { - long err =3D 0; unsigned long __user *nm =3D NULL; unsigned long nr_bits, alloc_size; DECLARE_BITMAP(bm, MAX_NUMNODES); @@ -1568,14 +1567,13 @@ COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, co= mpat_ulong_t __user *, nmask, alloc_size =3D ALIGN(nr_bits, BITS_PER_LONG) / 8; =20 if (nmask) { - err =3D compat_get_bitmap(bm, nmask, nr_bits); + if (compat_get_bitmap(bm, nmask, nr_bits)) + return -EFAULT; nm =3D compat_alloc_user_space(alloc_size); - err |=3D copy_to_user(nm, bm, alloc_size); + if (copy_to_user(nm, bm, alloc_size)) + return -EFAULT; } =20 - if (err) - return -EFAULT; - return sys_set_mempolicy(mode, nm, nr_bits+1); } =20 @@ -1583,7 +1581,6 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, = compat_ulong_t, len, compat_ulong_t, mode, compat_ulong_t __user *, nmask, compat_ulong_t, maxnode, compat_ulong_t, flags) { - long err =3D 0; unsigned long __user *nm =3D NULL; unsigned long nr_bits, alloc_size; nodemask_t bm; @@ -1592,14 +1589,13 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start= , compat_ulong_t, len, alloc_size =3D ALIGN(nr_bits, BITS_PER_LONG) / 8; =20 if (nmask) { - err =3D compat_get_bitmap(nodes_addr(bm), nmask, nr_bits); + if (compat_get_bitmap(nodes_addr(bm), nmask, nr_bits)) + return -EFAULT; nm =3D compat_alloc_user_space(alloc_size); - err |=3D copy_to_user(nm, nodes_addr(bm), alloc_size); + if (copy_to_user(nm, nodes_addr(bm), alloc_size)) + return -EFAULT; } =20 - if (err) - return -EFAULT; - return sys_mbind(start, len, mode, nm, nr_bits+1, flags); } =20 diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9ddea0200c94..ab7938d2248e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1883,7 +1883,7 @@ static bool zone_local(struct zone *local_zone, struc= t zone *zone) =20 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone) { - return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) < + return node_distance(zone_to_nid(local_zone), zone_to_nid(zone)) <=3D RECLAIM_DISTANCE; } =20 diff --git a/mm/vmpressure.c b/mm/vmpressure.c index c5afd573d7da..3fb15c25af87 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -112,9 +112,16 @@ static enum vmpressure_levels vmpressure_calc_level(un= signed long scanned, unsigned long reclaimed) { unsigned long scale =3D scanned + reclaimed; - unsigned long pressure; + unsigned long pressure =3D 0; =20 /* + * reclaimed can be greater than scanned in cases + * like THP, where the scanned is 1 and reclaimed + * could be 512 + */ + if (reclaimed >=3D scanned) + goto out; + /* * We calculate the ratio (in percents) of how many pages were * scanned vs. reclaimed in a given time frame (window). Note that * time is in VM reclaimer's "ticks", i.e. number of pages @@ -124,6 +131,7 @@ static enum vmpressure_levels vmpressure_calc_level(uns= igned long scanned, pressure =3D scale - (reclaimed * scale / scanned); pressure =3D pressure * 100 / scale; =20 +out: pr_debug("%s: %3lu (s: %lu r: %lu)\n", __func__, pressure, scanned, reclaimed); =20 diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index d2b6d5066c33..66cef51574d4 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -212,8 +212,10 @@ err_unlock: spin_unlock_bh(&chain->lock); =20 err: - if (!ret) + if (!ret) { kfree(frag_entry_new); + kfree_skb(skb); + } =20 return ret; } @@ -288,7 +290,7 @@ free: * * There are three possible outcomes: 1) Packet is merged: Return true and * set *skb to merged packet; 2) Packet is buffered: Return true and set *= skb - * to NULL; 3) Error: Return false and leave skb as is. + * to NULL; 3) Error: Return false and free skb. */ bool batadv_frag_skb_buffer(struct sk_buff **skb, struct batadv_orig_node *orig_node_src) @@ -310,9 +312,9 @@ bool batadv_frag_skb_buffer(struct sk_buff **skb, goto out_err; =20 out: - *skb =3D skb_out; ret =3D true; out_err: + *skb =3D skb_out; return ret; } =20 @@ -459,6 +461,10 @@ bool batadv_frag_send_packet(struct sk_buff *skb, =20 /* Eat and send fragments from the tail of skb */ while (skb->len > max_fragment_size) { + /* The initial check in this function should cover this case */ + if (unlikely(frag_header.no =3D=3D BATADV_FRAG_MAX_FRAGMENTS - 1)) + goto out_err; + skb_fragment =3D batadv_frag_create(skb, &frag_header, mtu); if (!skb_fragment) goto out_err; @@ -469,10 +475,6 @@ bool batadv_frag_send_packet(struct sk_buff *skb, batadv_send_skb_packet(skb_fragment, neigh_node->if_incoming, neigh_node->addr); frag_header.no++; - - /* The initial check in this function should cover this case */ - if (frag_header.no =3D=3D BATADV_FRAG_MAX_FRAGMENTS - 1) - goto out_err; } =20 /* Make room for the fragment header. */ diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 34c20cc0670c..7a1032348ea9 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1025,6 +1025,12 @@ int batadv_recv_frag_packet(struct sk_buff *skb, batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX); batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len); =20 + /* batadv_frag_skb_buffer will always consume the skb and + * the caller should therefore never try to free the + * skb after this point + */ + ret =3D NET_RX_SUCCESS; + /* Add fragment to buffer and merge if possible. */ if (!batadv_frag_skb_buffer(&skb, orig_node_src)) goto out; @@ -1036,8 +1042,6 @@ int batadv_recv_frag_packet(struct sk_buff *skb, batadv_batman_skb_recv(skb, recv_if->net_dev, &recv_if->batman_adv_ptype, NULL); =20 - ret =3D NET_RX_SUCCESS; - out: if (orig_node_src) batadv_orig_node_free_ref(orig_node_src); diff --git a/net/core/dev.c b/net/core/dev.c index c14258a3841e..1441a4934c18 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1601,27 +1601,54 @@ EXPORT_SYMBOL(call_netdevice_notifiers); static struct static_key netstamp_needed __read_mostly; #ifdef HAVE_JUMP_LABEL static atomic_t netstamp_needed_deferred; +static atomic_t netstamp_wanted; static void netstamp_clear(struct work_struct *work) { int deferred =3D atomic_xchg(&netstamp_needed_deferred, 0); + int wanted; =20 - while (deferred--) - static_key_slow_dec(&netstamp_needed); + wanted =3D atomic_add_return(deferred, &netstamp_wanted); + if (wanted > 0) + static_key_enable(&netstamp_needed); + else + static_key_disable(&netstamp_needed); } static DECLARE_WORK(netstamp_work, netstamp_clear); #endif =20 void net_enable_timestamp(void) { +#ifdef HAVE_JUMP_LABEL + int wanted; + + while (1) { + wanted =3D atomic_read(&netstamp_wanted); + if (wanted <=3D 0) + break; + if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted + 1) =3D=3D wanted) + return; + } + atomic_inc(&netstamp_needed_deferred); + schedule_work(&netstamp_work); +#else static_key_slow_inc(&netstamp_needed); +#endif } EXPORT_SYMBOL(net_enable_timestamp); =20 void net_disable_timestamp(void) { #ifdef HAVE_JUMP_LABEL - /* net_disable_timestamp() can be called from non process context */ - atomic_inc(&netstamp_needed_deferred); + int wanted; + + while (1) { + wanted =3D atomic_read(&netstamp_wanted); + if (wanted <=3D 1) + break; + if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted - 1) =3D=3D wanted) + return; + } + atomic_dec(&netstamp_needed_deferred); schedule_work(&netstamp_work); #else static_key_slow_dec(&netstamp_needed); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 7d9b21a7dbb6..429ac19094f8 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1045,9 +1045,15 @@ static void __net_exit dccp_v4_exit_net(struct net *= net) inet_ctl_sock_destroy(net->dccp.v4_ctl_sk); } =20 +static void __net_exit dccp_v4_exit_batch(struct list_head *net_exit_list) +{ + inet_twsk_purge(&dccp_hashinfo, &dccp_death_row, AF_INET); +} + static struct pernet_operations dccp_v4_ops =3D { .init =3D dccp_v4_init_net, .exit =3D dccp_v4_exit_net, + .exit_batch =3D dccp_v4_exit_batch, }; =20 static int __init dccp_v4_init(void) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index b42151be8afa..0622f721eb2c 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -486,6 +486,9 @@ static struct sock *dccp_v6_request_recv_sock(struct so= ck *sk, newsk->sk_backlog_rcv =3D dccp_v4_do_rcv; newnp->pktoptions =3D NULL; newnp->opt =3D NULL; + newnp->ipv6_mc_list =3D NULL; + newnp->ipv6_ac_list =3D NULL; + newnp->ipv6_fl_list =3D NULL; newnp->mcast_oif =3D inet6_iif(skb); newnp->mcast_hops =3D ipv6_hdr(skb)->hop_limit; =20 @@ -561,6 +564,9 @@ static struct sock *dccp_v6_request_recv_sock(struct so= ck *sk, /* Clone RX bits */ newnp->rxopt.all =3D np->rxopt.all; =20 + newnp->ipv6_mc_list =3D NULL; + newnp->ipv6_ac_list =3D NULL; + newnp->ipv6_fl_list =3D NULL; /* Clone pktoptions received with SYN */ newnp->pktoptions =3D NULL; if (ireq->pktopts !=3D NULL) { @@ -1143,9 +1149,15 @@ static void __net_exit dccp_v6_exit_net(struct net *= net) inet_ctl_sock_destroy(net->dccp.v6_ctl_sk); } =20 +static void __net_exit dccp_v6_exit_batch(struct list_head *net_exit_list) +{ + inet_twsk_purge(&dccp_hashinfo, &dccp_death_row, AF_INET6); +} + static struct pernet_operations dccp_v6_ops =3D { .init =3D dccp_v6_init_net, .exit =3D dccp_v6_exit_net, + .exit_batch =3D dccp_v6_exit_batch, }; =20 static int __init dccp_v6_init(void) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_soc= k.c index 14d02ea905b6..5e2c4d535b26 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -677,6 +677,8 @@ struct sock *inet_csk_clone_lock(const struct sock *sk, inet_sk(newsk)->inet_sport =3D htons(inet_rsk(req)->ir_num); newsk->sk_write_space =3D sk_stream_write_space; =20 + inet_sk(newsk)->mc_list =3D NULL; + newsk->sk_mark =3D inet_rsk(req)->ir_mark; =20 newicsk->icsk_retransmits =3D 0; diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 571dabfe9ef3..3e3bd0819987 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -154,17 +154,18 @@ void ping_hash(struct sock *sk) void ping_unhash(struct sock *sk) { struct inet_sock *isk =3D inet_sk(sk); + pr_debug("ping_unhash(isk=3D%p,isk->num=3D%u)\n", isk, isk->inet_num); + write_lock_bh(&ping_table.lock); if (sk_hashed(sk)) { - write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); sk_nulls_node_init(&sk->sk_nulls_node); sock_put(sk); isk->inet_num =3D 0; isk->inet_sport =3D 0; sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); - write_unlock_bh(&ping_table.lock); } + write_unlock_bh(&ping_table.lock); } EXPORT_SYMBOL_GPL(ping_unhash); =20 diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 77bf6bde38cc..b8dc5d8cdedf 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1879,6 +1879,7 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 = daddr, __be32 saddr, { int res; =20 + tos &=3D IPTOS_RT_MASK; rcu_read_lock(); =20 /* Multicast recognition logic is moved from route cache to here. diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0c0255136992..93a731614f6a 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -101,7 +101,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *t= w, struct sk_buff *skb, tcp_parse_options(skb, &tmp_opt, 0, NULL); =20 if (tmp_opt.saw_tstamp) { - tmp_opt.rcv_tsecr -=3D tcptw->tw_ts_offset; + if (tmp_opt.rcv_tsecr) + tmp_opt.rcv_tsecr -=3D tcptw->tw_ts_offset; tmp_opt.ts_recent =3D tcptw->tw_ts_recent; tmp_opt.ts_recent_stamp =3D tcptw->tw_ts_recent_stamp; paws_reject =3D tcp_paws_reject(&tmp_opt, th->rst); diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index f987e8a1282b..0d5772393014 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -86,7 +86,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *s= kb, const struct net_offload *ops; int proto; struct frag_hdr *fptr; - unsigned int unfrag_ip6hlen; u8 *prevhdr; int offset =3D 0; bool encap, udpfrag; @@ -144,8 +143,10 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff= *skb, skb->network_header =3D (u8 *)ipv6h - skb->head; =20 if (udpfrag) { - unfrag_ip6hlen =3D ip6_find_1stfragopt(skb, &prevhdr); - fptr =3D (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); + int err =3D ip6_find_1stfragopt(skb, &prevhdr); + if (err < 0) + return ERR_PTR(err); + fptr =3D (struct frag_hdr *)((u8 *)ipv6h + err); fptr->frag_off =3D htons(offset); if (skb->next !=3D NULL) fptr->frag_off |=3D htons(IP6_MF); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7046af25d6be..cbe7ddeb69c0 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -566,7 +566,10 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(st= ruct sk_buff *)) u8 *prevhdr, nexthdr =3D 0; struct net *net =3D dev_net(skb_dst(skb)->dev); =20 - hlen =3D ip6_find_1stfragopt(skb, &prevhdr); + err =3D ip6_find_1stfragopt(skb, &prevhdr); + if (err < 0) + goto fail; + hlen =3D err; nexthdr =3D *prevhdr; =20 mtu =3D ip6_skb_dst_mtu(skb); @@ -1364,6 +1367,11 @@ alloc_new_skb: */ alloclen +=3D sizeof(struct frag_hdr); =20 + copy =3D datalen - transhdrlen - fraggap; + if (copy < 0) { + err =3D -EINVAL; + goto error; + } if (transhdrlen) { skb =3D sock_alloc_send_skb(sk, alloclen + hh_len, @@ -1416,13 +1424,9 @@ alloc_new_skb: data +=3D fraggap; pskb_trim_unique(skb_prev, maxfraglen); } - copy =3D datalen - transhdrlen - fraggap; - - if (copy < 0) { - err =3D -EINVAL; - kfree_skb(skb); - goto error; - } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, = fraggap, skb) < 0) { + if (copy > 0 && + getfrag(from, data + transhdrlen, offset, + copy, fraggap, skb) < 0) { err =3D -EFAULT; kfree_skb(skb); goto error; diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 1e987e68e510..0fcaf38006f9 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -45,14 +45,13 @@ EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) { u16 offset =3D sizeof(struct ipv6hdr); - struct ipv6_opt_hdr *exthdr =3D - (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); unsigned int packet_len =3D skb_tail_pointer(skb) - skb_network_header(skb); int found_rhdr =3D 0; *nexthdr =3D &ipv6_hdr(skb)->nexthdr; =20 - while (offset + 1 <=3D packet_len) { + while (offset <=3D packet_len) { + struct ipv6_opt_hdr *exthdr; =20 switch (**nexthdr) { =20 @@ -73,13 +72,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexth= dr) return offset; } =20 - offset +=3D ipv6_optlen(exthdr); - *nexthdr =3D &exthdr->nexthdr; + if (offset + sizeof(struct ipv6_opt_hdr) > packet_len) + return -EINVAL; + exthdr =3D (struct ipv6_opt_hdr *)(skb_network_header(skb) + offset); + offset +=3D ipv6_optlen(exthdr); + *nexthdr =3D &exthdr->nexthdr; } =20 - return offset; + return -EINVAL; } EXPORT_SYMBOL(ip6_find_1stfragopt); =20 diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 889e06626c26..80a3b621dc09 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1733,6 +1733,8 @@ static int ip6_route_del(struct fib6_config *cfg) continue; if (cfg->fc_metric && cfg->fc_metric !=3D rt->rt6i_metric) continue; + if (cfg->fc_protocol && cfg->fc_protocol !=3D rt->rt6i_protocol) + continue; dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); =20 diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c6c921d15de4..b5735b30667d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1177,6 +1177,7 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock = *sk, struct sk_buff *skb, newtp->af_specific =3D &tcp_sock_ipv6_mapped_specific; #endif =20 + newnp->ipv6_mc_list =3D NULL; newnp->ipv6_ac_list =3D NULL; newnp->ipv6_fl_list =3D NULL; newnp->pktoptions =3D NULL; @@ -1246,6 +1247,7 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock = *sk, struct sk_buff *skb, First: no IPv4 options. */ newinet->inet_opt =3D NULL; + newnp->ipv6_mc_list =3D NULL; newnp->ipv6_ac_list =3D NULL; newnp->ipv6_fl_list =3D NULL; =20 diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 0ae3d98f83e0..3dd9891cfa77 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -51,6 +51,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *= skb, int offset; __wsum csum; int tnl_hlen; + int err; =20 mss =3D skb_shinfo(skb)->gso_size; if (unlikely(skb->len <=3D mss)) @@ -101,7 +102,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buf= f *skb, /* Find the unfragmentable header and shift it left by frag_hdr_sz * bytes to insert fragment header. */ - unfrag_ip6hlen =3D ip6_find_1stfragopt(skb, &prevhdr); + err =3D ip6_find_1stfragopt(skb, &prevhdr); + if (err < 0) + return ERR_PTR(err); + unfrag_ip6hlen =3D err; nexthdr =3D *prevhdr; *prevhdr =3D NEXTHDR_FRAGMENT; unfrag_len =3D (skb_network_header(skb) - skb_mac_header(skb)) + diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 1b095ca37aa4..bc043dc98963 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1168,11 +1168,10 @@ static int ipxitf_ioctl(unsigned int cmd, void __us= er *arg) sipx->sipx_network =3D ipxif->if_netnum; memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node)); - rc =3D -EFAULT; + rc =3D 0; if (copy_to_user(arg, &ifr, sizeof(ifr))) - break; + rc =3D -EFAULT; ipxitf_put(ipxif); - rc =3D 0; break; } case SIOCAIPXITFCRT: diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 76f4c5c9a466..6e1e98c3bdcd 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1316,6 +1316,9 @@ static void l2tp_tunnel_del_work(struct work_struct *= work) struct sock *sk =3D NULL; =20 tunnel =3D container_of(work, struct l2tp_tunnel, del_work); + + l2tp_tunnel_closeall(tunnel); + sk =3D l2tp_tunnel_sock_lookup(tunnel); if (!sk) goto out; @@ -1676,7 +1679,6 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) { l2tp_tunnel_inc_refcount(tunnel); - l2tp_tunnel_closeall(tunnel); if (false =3D=3D queue_work(l2tp_wq, &tunnel->del_work)) { l2tp_tunnel_dec_refcount(tunnel); return 1; diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 090bdf11caed..c5706b0bb683 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -114,6 +114,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct= cfg80211_wowlan *wowlan) break; } =20 + flush_delayed_work(&sdata->dec_tailroom_needed_wk); drv_remove_interface(local, sdata); } =20 diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 193eac992814..5b4fb92144b0 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3349,6 +3349,8 @@ packet_setsockopt(struct socket *sock, int level, int= optname, char __user *optv return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; + if (val > INT_MAX) + return -EINVAL; po->tp_reserve =3D val; return 0; } @@ -3842,8 +3844,8 @@ static int packet_set_ring(struct sock *sk, union tpa= cket_req_u *req_u, if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) goto out; if (po->tp_version >=3D TPACKET_V3 && - (int)(req->tp_block_size - - BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <=3D 0) + req->tp_block_size <=3D + BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv)) goto out; if (unlikely(req->tp_frame_size < po->tp_hdrlen + po->tp_reserve)) @@ -3854,6 +3856,8 @@ static int packet_set_ring(struct sock *sk, union tpa= cket_req_u *req_u, rb->frames_per_block =3D req->tp_block_size/req->tp_frame_size; if (unlikely(rb->frames_per_block <=3D 0)) goto out; + if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr)) + goto out; if (unlikely((rb->frames_per_block * req->tp_block_nr) !=3D req->tp_frame_nr)) goto out; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 55307ccf4453..e7b0c7af46dc 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -799,10 +799,8 @@ static int tca_action_flush(struct net *net, struct nl= attr *nla, goto out_module_put; =20 err =3D a.ops->walk(skb, &dcb, RTM_DELACTION, &a); - if (err < 0) + if (err <=3D 0) goto out_module_put; - if (err =3D=3D 0) - goto noflush_out; =20 nla_nest_end(skb, nest); =20 @@ -819,7 +817,6 @@ static int tca_action_flush(struct net *net, struct nla= ttr *nla, out_module_put: module_put(a.ops->owner); err_out: -noflush_out: kfree_skb(skb); return err; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 68265b255638..8ad13ba731b9 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -659,6 +659,9 @@ static struct sock *sctp_v6_create_accept_sk(struct soc= k *sk, newnp =3D inet6_sk(newsk); =20 memcpy(newnp, np, sizeof(struct ipv6_pinfo)); + newnp->ipv6_mc_list =3D NULL; + newnp->ipv6_ac_list =3D NULL; + newnp->ipv6_fl_list =3D NULL; =20 rcu_read_lock(); opt =3D rcu_dereference(np->opt); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 8059e412c9f3..a6d54a9a1133 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -387,7 +387,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_r= eplay_state_esn *replay_es up =3D nla_data(rp); ulen =3D xfrm_replay_state_esn_len(up); =20 - if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) !=3D ulen) + /* Check the overall length and the internal bitmap length to avoid + * potential overflow. */ + if (nla_len(rp) < ulen || + xfrm_replay_state_esn_len(replay_esn) !=3D ulen || + replay_esn->bmp_len !=3D up->bmp_len) + return -EINVAL; + + if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) return -EINVAL; =20 return 0; diff --git a/samples/seccomp/bpf-helper.h b/samples/seccomp/bpf-helper.h index 38ee70f3cd5b..1d8de9edd858 100644 --- a/samples/seccomp/bpf-helper.h +++ b/samples/seccomp/bpf-helper.h @@ -138,7 +138,7 @@ union arg64 { #define ARG_32(idx) \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)) =20 -/* Loads hi into A and lo in X */ +/* Loads lo into M[0] and hi into M[1] and A */ #define ARG_64(idx) \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \ BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \ @@ -153,88 +153,107 @@ union arg64 { BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \ jt =20 -/* Checks the lo, then swaps to check the hi. A=3Dlo,X=3Dhi */ +#define JA32(value, jt) \ + BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \ + jt + +#define JGE32(value, jt) \ + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \ + jt + +#define JGT32(value, jt) \ + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \ + jt + +#define JLE32(value, jt) \ + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \ + jt + +#define JLT32(value, jt) \ + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \ + jt + +/* + * All the JXX64 checks assume lo is saved in M[0] and hi is saved in both + * A and M[1]. This invariant is kept by restoring A if necessary. + */ #define JEQ64(lo, hi, jt) \ + /* if (hi !=3D arg.hi) goto NOMATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ + /* if (lo !=3D arg.lo) goto NOMATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \ - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ + BPF_STMT(BPF_LD+BPF_MEM, 1), \ jt, \ - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ + BPF_STMT(BPF_LD+BPF_MEM, 1) =20 #define JNE64(lo, hi, jt) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \ - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ + /* if (hi !=3D arg.hi) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \ + BPF_STMT(BPF_LD+BPF_MEM, 0), \ + /* if (lo !=3D arg.lo) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \ - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ + BPF_STMT(BPF_LD+BPF_MEM, 1), \ jt, \ - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ - -#define JA32(value, jt) \ - BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \ - jt + BPF_STMT(BPF_LD+BPF_MEM, 1) =20 #define JA64(lo, hi, jt) \ + /* if (hi & arg.hi) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \ - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ + BPF_STMT(BPF_LD+BPF_MEM, 0), \ + /* if (lo & arg.lo) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \ - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ + BPF_STMT(BPF_LD+BPF_MEM, 1), \ jt, \ - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ + BPF_STMT(BPF_LD+BPF_MEM, 1) =20 -#define JGE32(value, jt) \ - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \ - jt - -#define JLT32(value, jt) \ - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \ - jt - -/* Shortcut checking if hi > arg.hi. */ #define JGE64(lo, hi, jt) \ + /* if (hi > arg.hi) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \ + /* if (hi !=3D arg.hi) goto NOMATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ + BPF_STMT(BPF_LD+BPF_MEM, 0), \ + /* if (lo >=3D arg.lo) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \ - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ - jt, \ - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ - -#define JLT64(lo, hi, jt) \ - BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \ - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ + BPF_STMT(BPF_LD+BPF_MEM, 1), \ jt, \ - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ + BPF_STMT(BPF_LD+BPF_MEM, 1) =20 -#define JGT32(value, jt) \ - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \ - jt - -#define JLE32(value, jt) \ - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \ - jt - -/* Check hi > args.hi first, then do the GE checking */ #define JGT64(lo, hi, jt) \ + /* if (hi > arg.hi) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \ + /* if (hi !=3D arg.hi) goto NOMATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ + BPF_STMT(BPF_LD+BPF_MEM, 0), \ + /* if (lo > arg.lo) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \ - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ + BPF_STMT(BPF_LD+BPF_MEM, 1), \ jt, \ - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ + BPF_STMT(BPF_LD+BPF_MEM, 1) =20 #define JLE64(lo, hi, jt) \ - BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \ - BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ + /* if (hi < arg.hi) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ + /* if (hi !=3D arg.hi) goto NOMATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ + BPF_STMT(BPF_LD+BPF_MEM, 0), \ + /* if (lo <=3D arg.lo) goto MATCH; */ \ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \ - BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ + BPF_STMT(BPF_LD+BPF_MEM, 1), \ + jt, \ + BPF_STMT(BPF_LD+BPF_MEM, 1) + +#define JLT64(lo, hi, jt) \ + /* if (hi < arg.hi) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ + /* if (hi !=3D arg.hi) goto NOMATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ + BPF_STMT(BPF_LD+BPF_MEM, 0), \ + /* if (lo < arg.lo) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \ + BPF_STMT(BPF_LD+BPF_MEM, 1), \ jt, \ - BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ + BPF_STMT(BPF_LD+BPF_MEM, 1) =20 #define LOAD_SYSCALL_NR \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encry= pted-keys/encrypted.c index 556c43df6636..9c321a25348f 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -428,7 +428,7 @@ static int init_blkcipher_desc(struct blkcipher_desc *d= esc, const u8 *key, static struct key *request_master_key(struct encrypted_key_payload *epaylo= ad, u8 **master_key, size_t *master_keylen) { - struct key *mkey =3D NULL; + struct key *mkey =3D ERR_PTR(-EINVAL); =20 if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 3553f197789b..57f8e162b51b 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -86,6 +86,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, if (!*description) { kfree(description); description =3D NULL; + } else if ((description[0] =3D=3D '.') && + (strncmp(type, "keyring", 7) =3D=3D 0)) { + ret =3D -EPERM; + goto error2; } } =20 @@ -271,7 +275,8 @@ error: * Create and join an anonymous session keyring or join a named session * keyring, creating it if necessary. A named session keyring must have S= earch * permission for it to be joined. Session keyrings without this permit w= ill - * be skipped over. + * be skipped over. It is not permitted for userspace to create or join + * keyrings whose name begin with a dot. * * If successful, the ID of the joined session keyring will be returned. */ @@ -288,12 +293,16 @@ long keyctl_join_session_keyring(const char __user *_= name) ret =3D PTR_ERR(name); goto error; } + + ret =3D -EPERM; + if (name[0] =3D=3D '.') + goto error_name; } =20 /* join the session */ ret =3D join_session_keyring(name); +error_name: kfree(name); - error: return ret; } @@ -1240,8 +1249,8 @@ error: * Read or set the default keyring in which request_key() will cache keys = and * return the old setting. * - * If a process keyring is specified then this will be created if it doesn= 't - * yet exist. The old setting will be returned if successful. + * If a thread or process keyring is specified then it will be created if = it + * doesn't yet exist. The old setting will be returned if successful. */ long keyctl_set_reqkey_keyring(int reqkey_defl) { @@ -1266,11 +1275,8 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) =20 case KEY_REQKEY_DEFL_PROCESS_KEYRING: ret =3D install_process_keyring_to_cred(new); - if (ret < 0) { - if (ret !=3D -EEXIST) - goto error; - ret =3D 0; - } + if (ret < 0) + goto error; goto set; =20 case KEY_REQKEY_DEFL_DEFAULT: diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 4e56371f239f..18bad7caf602 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -125,13 +125,18 @@ error: } =20 /* - * Install a fresh thread keyring directly to new credentials. This keyri= ng is - * allowed to overrun the quota. + * Install a thread keyring to the given credentials struct if it didn't h= ave + * one already. This is allowed to overrun the quota. + * + * Return: 0 if a thread keyring is now present; -errno on failure. */ int install_thread_keyring_to_cred(struct cred *new) { struct key *keyring; =20 + if (new->thread_keyring) + return 0; + keyring =3D keyring_alloc("_tid", new->uid, new->gid, new, KEY_POS_ALL | KEY_USR_VIEW, KEY_ALLOC_QUOTA_OVERRUN, NULL); @@ -143,7 +148,9 @@ int install_thread_keyring_to_cred(struct cred *new) } =20 /* - * Install a fresh thread keyring, discarding the old one. + * Install a thread keyring to the current task if it didn't have one alre= ady. + * + * Return: 0 if a thread keyring is now present; -errno on failure. */ static int install_thread_keyring(void) { @@ -154,8 +161,6 @@ static int install_thread_keyring(void) if (!new) return -ENOMEM; =20 - BUG_ON(new->thread_keyring); - ret =3D install_thread_keyring_to_cred(new); if (ret < 0) { abort_creds(new); @@ -166,17 +171,17 @@ static int install_thread_keyring(void) } =20 /* - * Install a process keyring directly to a credentials struct. + * Install a process keyring to the given credentials struct if it didn't = have + * one already. This is allowed to overrun the quota. * - * Returns -EEXIST if there was already a process keyring, 0 if one instal= led, - * and other value on any other error + * Return: 0 if a process keyring is now present; -errno on failure. */ int install_process_keyring_to_cred(struct cred *new) { struct key *keyring; =20 if (new->process_keyring) - return -EEXIST; + return 0; =20 keyring =3D keyring_alloc("_pid", new->uid, new->gid, new, KEY_POS_ALL | KEY_USR_VIEW, @@ -189,11 +194,9 @@ int install_process_keyring_to_cred(struct cred *new) } =20 /* - * Make sure a process keyring is installed for the current process. The - * existing process keyring is not replaced. + * Install a process keyring to the current task if it didn't have one alr= eady. * - * Returns 0 if there is a process keyring by the end of this function, so= me - * error otherwise. + * Return: 0 if a process keyring is now present; -errno on failure. */ static int install_process_keyring(void) { @@ -207,14 +210,18 @@ static int install_process_keyring(void) ret =3D install_process_keyring_to_cred(new); if (ret < 0) { abort_creds(new); - return ret !=3D -EEXIST ? ret : 0; + return ret; } =20 return commit_creds(new); } =20 /* - * Install a session keyring directly to a credentials struct. + * Install the given keyring as the session keyring of the given credentia= ls + * struct, replacing the existing one if any. If the given keyring is NUL= L, + * then install a new anonymous session keyring. + * + * Return: 0 on success; -errno on failure. */ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) { @@ -249,8 +256,11 @@ int install_session_keyring_to_cred(struct cred *cred,= struct key *keyring) } =20 /* - * Install a session keyring, discarding the old one. If a keyring is not - * supplied, an empty one is invented. + * Install the given keyring as the session keyring of the current task, + * replacing the existing one if any. If the given keyring is NULL, then + * install a new anonymous session keyring. + * + * Return: 0 on success; -errno on failure. */ static int install_session_keyring(struct key *keyring) { diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 1d5acbe0c08b..86240d02b530 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c @@ -135,6 +135,7 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, f->tail =3D cell; if (f->head =3D=3D NULL) f->head =3D cell; + cell->next =3D NULL; f->cells++; spin_unlock_irqrestore(&f->lock, flags); =20 @@ -214,6 +215,8 @@ void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, spin_lock_irqsave(&f->lock, flags); cell->next =3D f->head; f->head =3D cell; + if (!f->tail) + f->tail =3D cell; f->cells++; spin_unlock_irqrestore(&f->lock, flags); } diff --git a/sound/core/timer.c b/sound/core/timer.c index d32c631cca6b..a249fac9c2d3 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1715,9 +1715,21 @@ static int snd_timer_user_params(struct file *file, return -EBADFD; if (copy_from_user(¶ms, _params, sizeof(params))) return -EFAULT; - if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) { - err =3D -EINVAL; - goto _end; + if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { + u64 resolution; + + if (params.ticks < 1) { + err =3D -EINVAL; + goto _end; + } + + /* Don't allow resolution less than 1ms */ + resolution =3D snd_timer_resolution(tu->timeri); + resolution *=3D params.ticks; + if (resolution < 1000000) { + err =3D -EINVAL; + goto _end; + } } if (params.queue_size > 0 && (params.queue_size < 32 || params.queue_size > 1024)) { diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 6ac40beb49da..abd0a2d0856c 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -27,12 +27,6 @@ #include "cthw20k1.h" #include "ct20k1reg.h" =20 -#if BITS_PER_LONG =3D=3D 32 -#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bit PTE */ -#else -#define CT_XFI_DMA_MASK DMA_BIT_MASK(64) /* 64 bit PTE */ -#endif - struct hw20k1 { struct hw hw; spinlock_t reg_20k1_lock; @@ -1903,19 +1897,18 @@ static int hw_card_start(struct hw *hw) { int err; struct pci_dev *pci =3D hw->pci; + const unsigned int dma_bits =3D BITS_PER_LONG; =20 err =3D pci_enable_device(pci); if (err < 0) return err; =20 /* Set DMA transfer mask */ - if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || - pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { - printk(KERN_ERR "architecture does not support PCI " - "busmaster DMA with mask 0x%llx\n", - CT_XFI_DMA_MASK); - err =3D -ENXIO; - goto error1; + if (dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); + } else { + dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); } =20 if (!hw->io_base) { diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index b1438861d38a..5828a3ec58bb 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -26,12 +26,6 @@ #include "cthw20k2.h" #include "ct20k2reg.h" =20 -#if BITS_PER_LONG =3D=3D 32 -#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bit PTE */ -#else -#define CT_XFI_DMA_MASK DMA_BIT_MASK(64) /* 64 bit PTE */ -#endif - struct hw20k2 { struct hw hw; /* for i2c */ @@ -2026,18 +2020,18 @@ static int hw_card_start(struct hw *hw) int err =3D 0; struct pci_dev *pci =3D hw->pci; unsigned int gctl; + const unsigned int dma_bits =3D BITS_PER_LONG; =20 err =3D pci_enable_device(pci); if (err < 0) return err; =20 /* Set DMA transfer mask */ - if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || - pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { - printk(KERN_ERR "ctxfi: architecture does not support PCI " - "busmaster DMA with mask 0x%llx\n", CT_XFI_DMA_MASK); - err =3D -ENXIO; - goto error1; + if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); + } else { + dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); + dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); } =20 if (!hw->io_base) { diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 7aeb69bace7a..c2cd770ec749 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -974,7 +974,7 @@ static int rt5640_hp_event(struct snd_soc_dapm_widget *= w, =20 case SND_SOC_DAPM_PRE_PMD: rt5640->hp_mute =3D 1; - usleep_range(70000, 75000); + msleep(70); break; =20 default: @@ -1038,7 +1038,7 @@ static int rt5640_hp_post_event(struct snd_soc_dapm_w= idget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: if (!rt5640->hp_mute) - usleep_range(80000, 85000); + msleep(80); =20 break; =20 diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Document= ation/perf-script.txt index 05f9a0a6784c..80b4268e84b5 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -36,7 +36,7 @@ There are several variants of perf script: =20 'perf script report