4.19.84-stable review
Greg Kroah-Hartman
maintainercover 4.19.84-stable review
This is the start of the stable review cycle for the 4.19.84 release. There are 125 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 13 Nov 2019 18:08:44 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.19.84-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.19.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 4.19.84-rc1
Tejun Heo <[email protected]>
cgroup,writeback: don't switch wbs immediately on dead wbs if the memcg is dead
Konstantin Khlebnikov <[email protected]>
mm/filemap.c: don't initiate writeback if mapping has no dirty pages
Jean-Baptiste Maneyrol <[email protected]>
iio: imu: inv_mpu6050: fix no data on MPU6050
Randolph Maaßen <[email protected]>
iio: imu: mpu6050: Add support for the ICM 20602 IMU
Tejun Heo <[email protected]>
blkcg: make blkcg_print_stat() print stats only for online blkgs
Hans de Goede <[email protected]>
pinctrl: cherryview: Fix irq_valid_mask calculation
Shuning Zhang <[email protected]>
ocfs2: protect extent tree in ocfs2_prepare_inode_for_write()
Andy Shevchenko <[email protected]>
pinctrl: intel: Avoid potential glitches if pin is in GPIO mode
Wenwen Wang <[email protected]>
e1000: fix memory leaks
Manfred Rudigier <[email protected]>
igb: Fix constant media auto sense switching when no cable is connected
Chuhong Yuan <[email protected]>
net: ethernet: arc: add the missed clk_disable_unprepare
Trond Myklebust <[email protected]>
NFSv4: Don't allow a cached open with a revoked delegation
Felipe Balbi <[email protected]>
usb: dwc3: gadget: fix race when disabling ep with cancelled xfers
Haiyang Zhang <[email protected]>
hv_netvsc: Fix error handling in netvsc_attach()
Michael Strauss <[email protected]>
drm/amd/display: Passive DP->HDMI dongle detection fix
Andrey Grodzovsky <[email protected]>
drm/amdgpu: If amdgpu_ib_schedule fails return back the error.
Takashi Iwai <[email protected]>
iommu/amd: Apply the same IVRS IOAPIC workaround to Acer Aspire A315-41
Vladimir Oltean <[email protected]>
net: mscc: ocelot: refuse to overwrite the port's native vlan
Vladimir Oltean <[email protected]>
net: mscc: ocelot: fix vlan_filtering when enslaving to bridge before link is up
Jiangfeng Xiao <[email protected]>
net: hisilicon: Fix "Trying to free already-free IRQ"
Will Deacon <[email protected]>
fjes: Handle workqueue allocation failure
Anton Eidelman <[email protected]>
nvme-multipath: fix possible io hang after ctrl reconnect
Nicholas Piggin <[email protected]>
scsi: qla2xxx: stop timer in shutdown path
Lijun Ou <[email protected]>
RDMA/hns: Prevent memory leaks of eq->buf_list
Potnuri Bharat Teja <[email protected]>
RDMA/iw_cxgb4: Avoid freeing skb twice in arp failure case
GwanYeong Kim <[email protected]>
usbip: tools: Fix read_usb_vudc_device() error path handling
Johan Hovold <[email protected]>
USB: ldusb: use unsigned size format specifiers
Alan Stern <[email protected]>
USB: Skip endpoints with 0 maxpacket length
Kan Liang <[email protected]>
perf/x86/uncore: Fix event group support
Kim Phillips <[email protected]>
perf/x86/amd/ibs: Handle erratum #420 only on the affected CPU family (10h)
Kim Phillips <[email protected]>
perf/x86/amd/ibs: Fix reading of the IBS OpData register and thus precise RIP validity
Yinbo Zhu <[email protected]>
usb: dwc3: remove the call trace of USBx_GFLADJ
Peter Chen <[email protected]>
usb: gadget: configfs: fix concurrent issue between composite APIs
Navid Emamdoost <[email protected]>
usb: dwc3: pci: prevent memory leak in dwc3_pci_probe
Chandana Kishori Chiluveru <[email protected]>
usb: gadget: composite: Fix possible double free memory bug
Cristian Birsan <[email protected]>
usb: gadget: udc: atmel: Fix interrupt storm in FIFO mode.
Nikhil Badola <[email protected]>
usb: fsl: Check memory resource before releasing it
Taehee Yoo <[email protected]>
macsec: fix refcnt leak in module exit routine
Taehee Yoo <[email protected]>
bonding: fix unexpected IFF_BONDING bit unset
Eric Dumazet <[email protected]>
ipvs: move old_secure_tcp into struct netns_ipvs
Davide Caratti <[email protected]>
ipvs: don't ignore errors in case refcounting ip_vs module fails
Pablo Neira Ayuso <[email protected]>
netfilter: nf_flow_table: set timeout before insertion into hashes
Himanshu Madhani <[email protected]>
scsi: qla2xxx: Initialized mailbox to prevent driver load failure
Daniel Wagner <[email protected]>
scsi: lpfc: Honor module parameter lpfc_use_adisc
Hillf Danton <[email protected]>
net: openvswitch: free vport unless register_netdevice() succeeds
Dan Carpenter <[email protected]>
RDMA/uverbs: Prevent potential underflow
Hannes Reinecke <[email protected]>
scsi: qla2xxx: fixup incorrect usage of host_byte
Navid Emamdoost <[email protected]>
net/mlx5: prevent memory leak in mlx5_fpga_conn_create_cq
Tariq Toukan <[email protected]>
net/mlx5e: TX, Fix consumer index of error cqe dump
Kamal Heib <[email protected]>
RDMA/qedr: Fix reported firmware version
Potnuri Bharat Teja <[email protected]>
iw_cxgb4: fix ECN check on the passive accept
Rafi Wiener <[email protected]>
RDMA/mlx5: Clear old rate limit when closing QP
Zhang Lixu <[email protected]>
HID: intel-ish-hid: fix wrong error handling in ishtp_cl_alloc_tx_ring()
Baolin Wang <[email protected]>
dmaengine: sprd: Fix the possible memory leak issue
Radhey Shyam Pandey <[email protected]>
dmaengine: xilinx_dma: Fix control reg update in vdma_channel_set_config
Nicolas Boichat <[email protected]>
HID: google: add magnemite/masterball USB ids
Vidya Sagar <[email protected]>
PCI: tegra: Enable Relaxed Ordering only for Tegra20 & Tegra30
Suwan Kim <[email protected]>
usbip: Implement SG support to vhci-hcd and stub driver
Shuah Khan <[email protected]>
usbip: Fix vhci_urb_enqueue() URB null transfer buffer error path
Qian Cai <[email protected]>
sched/fair: Fix -Wunused-but-set-variable warnings
Dave Chiluk <[email protected]>
sched/fair: Fix low cpu usage with high throttling by removing expiration of cpu-local slices
Takashi Iwai <[email protected]>
ALSA: usb-audio: Fix copy&paste error in the validator
Dan Carpenter <[email protected]>
ALSA: usb-audio: remove some dead code
Takashi Iwai <[email protected]>
ALSA: usb-audio: Fix possible NULL dereference at create_yamaha_midi_quirk()
Takashi Iwai <[email protected]>
ALSA: usb-audio: Clean up check_input_term()
Takashi Iwai <[email protected]>
ALSA: usb-audio: Remove superfluous bLength checks
Takashi Iwai <[email protected]>
ALSA: usb-audio: Unify the release of usb_mixer_elem_info objects
Takashi Iwai <[email protected]>
ALSA: usb-audio: Simplify parse_audio_unit()
Takashi Iwai <[email protected]>
ALSA: usb-audio: More validations of descriptor units
Al Viro <[email protected]>
configfs: fix a deadlock in configfs_symlink()
Al Viro <[email protected]>
configfs: provide exclusion between IO and removals
Al Viro <[email protected]>
configfs: new object reprsenting tree fragments
Al Viro <[email protected]>
configfs_register_group() shouldn't be (and isn't) called in rmdirable parts
Al Viro <[email protected]>
configfs: stash the data we need into configfs_buffer at open time
Johan Hovold <[email protected]>
can: peak_usb: fix slab info leak
Johan Hovold <[email protected]>
can: mcba_usb: fix use-after-free on disconnect
Wen Yang <[email protected]>
can: dev: add missing of_node_put() after calling of_get_child_by_name()
Navid Emamdoost <[email protected]>
can: gs_usb: gs_can_open(): prevent memory leak
Marc Kleine-Budde <[email protected]>
can: rx-offload: can_rx_offload_queue_sorted(): fix error handling, avoid skb mem leak
Stephane Grosjean <[email protected]>
can: peak_usb: fix a potential out-of-sync while decoding packets
Kurt Van Dijck <[email protected]>
can: c_can: c_can_poll(): only read status register after status IRQ
Joakim Zhang <[email protected]>
can: flexcan: disable completely the ECC mechanism
Johan Hovold <[email protected]>
can: usb_8dev: fix use-after-free on disconnect
Pavel Shilovsky <[email protected]>
SMB3: Fix persistent handles reconnect
Jan Beulich <[email protected]>
x86/apic/32: Avoid bogus LDR warnings
Alexander Shishkin <[email protected]>
intel_th: pci: Add Jasper Lake PCH support
Alexander Shishkin <[email protected]>
intel_th: pci: Add Comet Lake PCH support
Dan Carpenter <[email protected]>
netfilter: ipset: Fix an error code in ip_set_sockfn_get()
Lukas Wunner <[email protected]>
netfilter: nf_tables: Align nft_expr private data to 64-bit
Ondrej Jirman <[email protected]>
ARM: sunxi: Fix CPU powerdown on A83T
Andreas Klinger <[email protected]>
iio: srf04: fix wrong limitation in distance measuring
Alexandru Ardelean <[email protected]>
iio: imu: adis16480: make sure provided frequency is positive
Fabrice Gasnier <[email protected]>
iio: adc: stm32-adc: fix stopping dma
Al Viro <[email protected]>
ceph: add missing check in d_revalidate snapdir handling
Luis Henriques <[email protected]>
ceph: fix use-after-free in __ceph_remove_cap()
Catalin Marinas <[email protected]>
arm64: Do not mask out PTE_RDONLY in pte_same()
Bard Liao <[email protected]>
soundwire: bus: set initial value to port_status
Michal Suchanek <[email protected]>
soundwire: depend on ACPI
Jason Gerecke <[email protected]>
HID: wacom: generic: Treat serial number and related fields as unsigned
Alex Deucher <[email protected]>
drm/radeon: fix si_enable_smc_cac() failed issue
Jiri Olsa <[email protected]>
perf tools: Fix time sorting
Shuah Khan <[email protected]>
tools: gpio: Use !building_out_of_srctree to determine srctree
Kevin Hao <[email protected]>
dump_stack: avoid the livelock of the dump_lock
Michal Hocko <[email protected]>
mm, vmstat: hide /proc/pagetypeinfo from normal users
Yang Shi <[email protected]>
mm: thp: handle page cache THP correctly in PageTransCompoundMap
Mel Gorman <[email protected]>
mm, meminit: recalculate pcpu batch and high limits after init completes
Johannes Weiner <[email protected]>
mm: memcontrol: fix network errors from failing __GFP_ATOMIC charges
Takashi Iwai <[email protected]>
ALSA: hda/ca0132 - Fix possible workqueue stall
Takashi Sakamoto <[email protected]>
ALSA: bebob: fix to detect configured source of sampling clock for Focusrite Saffire Pro i/o series
Takashi Iwai <[email protected]>
ALSA: timer: Fix incorrectly assigned timer instance
Salil Mehta <[email protected]>
net: hns: Fix the stray netpoll locks causing deadlock in NAPI path
Eric Dumazet <[email protected]>
ipv6: fixes rt6_probe() and fib6_nh->last_probe init
Claudiu Manoil <[email protected]>
net: mscc: ocelot: fix NULL pointer on LAG slave removal
Claudiu Manoil <[email protected]>
net: mscc: ocelot: don't handle netdev events for other netdevs
Manish Chopra <[email protected]>
qede: fix NULL pointer deref in __qede_remove()
Pan Bian <[email protected]>
NFC: st21nfca: fix double free
Pan Bian <[email protected]>
nfc: netlink: fix double device reference drop
Pan Bian <[email protected]>
NFC: fdp: fix incorrect free object
Aleksander Morgado <[email protected]>
net: usb: qmi_wwan: add support for DW5821e with eSIM support
Sean Tranchetti <[email protected]>
net: qualcomm: rmnet: Fix potential UAF when unregistering
Eric Dumazet <[email protected]>
net: fix data-race in neigh_event_send()
Alexander Sverdlin <[email protected]>
net: ethernet: octeon_mgmt: Account for second possible VLAN header
David Ahern <[email protected]>
ipv4: Fix table id reference in fib_sync_down_addr
Oliver Neukum <[email protected]>
CDC-NCM: handle incomplete transfer of MTU
Jay Vosburgh <[email protected]>
bonding: fix state transition issue in link monitoring
-------------
Diffstat:
Documentation/scheduler/sched-bwc.txt | 45 ++ Makefile | 4 +- arch/arm/mach-sunxi/mc_smp.c | 6 +- arch/arm64/include/asm/pgtable.h | 17 - arch/x86/events/amd/ibs.c | 8 +- arch/x86/events/intel/uncore.c | 44 +- arch/x86/events/intel/uncore.h | 12 - arch/x86/kernel/apic/apic.c | 28 +- block/blk-cgroup.c | 13 +- drivers/dma/sprd-dma.c | 15 + drivers/dma/xilinx/xilinx_dma.c | 7 + drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 24 +- drivers/gpu/drm/radeon/si_dpm.c | 1 + drivers/hid/hid-google-hammer.c | 4 + drivers/hid/hid-ids.h | 2 + drivers/hid/intel-ish-hid/ishtp/client-buffers.c | 2 +- drivers/hid/wacom.h | 15 + drivers/hid/wacom_wac.c | 10 +- drivers/hwtracing/intel_th/pci.c | 10 + drivers/iio/adc/stm32-adc.c | 4 +- drivers/iio/imu/adis16480.c | 5 +- drivers/iio/imu/inv_mpu6050/Kconfig | 8 +- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 40 ++ drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 6 + drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 10 + drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 15 +- drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 12 +- drivers/iio/proximity/srf04.c | 29 +- drivers/infiniband/core/uverbs.h | 2 +- drivers/infiniband/hw/cxgb4/cm.c | 30 +- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 6 +- drivers/infiniband/hw/mlx5/qp.c | 8 +- drivers/infiniband/hw/qedr/main.c | 2 +- drivers/iommu/amd_iommu_quirks.c | 13 + drivers/net/bonding/bond_main.c | 47 +- drivers/net/can/c_can/c_can.c | 25 +- drivers/net/can/c_can/c_can.h | 1 + drivers/net/can/dev.c | 1 + drivers/net/can/flexcan.c | 1 + drivers/net/can/rx-offload.c | 6 +- drivers/net/can/usb/gs_usb.c | 1 + drivers/net/can/usb/mcba_usb.c | 3 +- drivers/net/can/usb/peak_usb/pcan_usb.c | 17 +- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 2 +- drivers/net/can/usb/usb_8dev.c | 3 +- drivers/net/ethernet/arc/emac_rockchip.c | 3 + drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 2 +- drivers/net/ethernet/hisilicon/hip04_eth.c | 1 - drivers/net/ethernet/hisilicon/hns/hnae.c | 1 - drivers/net/ethernet/hisilicon/hns/hnae.h | 3 - drivers/net/ethernet/hisilicon/hns/hns_enet.c | 22 +- drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 7 +- drivers/net/ethernet/intel/igb/igb_main.c | 3 +- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 5 +- .../net/ethernet/mellanox/mlx5/core/fpga/conn.c | 4 +- drivers/net/ethernet/mscc/ocelot.c | 20 +- drivers/net/ethernet/qlogic/qede/qede_main.c | 12 +- drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 4 +- drivers/net/fjes/fjes_main.c | 15 +- drivers/net/hyperv/netvsc_drv.c | 9 +- drivers/net/macsec.c | 4 - drivers/net/usb/cdc_ncm.c | 6 +- drivers/net/usb/qmi_wwan.c | 1 + drivers/nfc/fdp/i2c.c | 2 +- drivers/nfc/st21nfca/core.c | 1 + drivers/nvme/host/multipath.c | 2 +- drivers/pci/controller/pci-tegra.c | 7 +- drivers/pinctrl/intel/pinctrl-cherryview.c | 2 +- drivers/pinctrl/intel/pinctrl-intel.c | 21 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 4 +- drivers/scsi/qla2xxx/qla_bsg.c | 6 +- drivers/scsi/qla2xxx/qla_mbx.c | 3 +- drivers/scsi/qla2xxx/qla_os.c | 4 + drivers/soundwire/Kconfig | 1 + drivers/soundwire/bus.c | 2 +- drivers/usb/core/config.c | 5 + drivers/usb/dwc3/core.c | 3 +- drivers/usb/dwc3/dwc3-pci.c | 2 +- drivers/usb/dwc3/gadget.c | 6 + drivers/usb/gadget/composite.c | 4 + drivers/usb/gadget/configfs.c | 110 +++- drivers/usb/gadget/udc/atmel_usba_udc.c | 6 +- drivers/usb/gadget/udc/fsl_udc_core.c | 2 +- drivers/usb/misc/ldusb.c | 7 +- drivers/usb/usbip/stub.h | 7 +- drivers/usb/usbip/stub_main.c | 57 +- drivers/usb/usbip/stub_rx.c | 204 +++++-- drivers/usb/usbip/stub_tx.c | 99 +++- drivers/usb/usbip/usbip_common.c | 59 +- drivers/usb/usbip/vhci_hcd.c | 16 +- drivers/usb/usbip/vhci_rx.c | 3 + drivers/usb/usbip/vhci_tx.c | 66 ++- fs/ceph/caps.c | 10 +- fs/ceph/inode.c | 1 + fs/cifs/smb2pdu.h | 1 + fs/configfs/configfs_internal.h | 15 +- fs/configfs/dir.c | 137 +++-- fs/configfs/file.c | 280 ++++----- fs/configfs/symlink.c | 33 +- fs/fs-writeback.c | 9 +- fs/nfs/delegation.c | 10 + fs/nfs/delegation.h | 1 + fs/nfs/nfs4proc.c | 7 +- fs/ocfs2/file.c | 134 +++-- include/linux/mm.h | 5 - include/linux/mm_types.h | 5 + include/linux/page-flags.h | 20 +- include/net/bonding.h | 3 +- include/net/ip_vs.h | 1 + include/net/neighbour.h | 4 +- include/net/netfilter/nf_tables.h | 3 +- include/rdma/ib_verbs.h | 2 +- kernel/sched/fair.c | 91 +-- kernel/sched/sched.h | 4 - lib/dump_stack.c | 7 +- mm/filemap.c | 3 +- mm/memcontrol.c | 9 + mm/page_alloc.c | 10 +- mm/vmstat.c | 2 +- net/ipv4/fib_semantics.c | 2 +- net/ipv6/route.c | 13 +- net/netfilter/ipset/ip_set_core.c | 8 +- net/netfilter/ipvs/ip_vs_app.c | 12 +- net/netfilter/ipvs/ip_vs_ctl.c | 29 +- net/netfilter/ipvs/ip_vs_pe.c | 3 +- net/netfilter/ipvs/ip_vs_sched.c | 3 +- net/netfilter/ipvs/ip_vs_sync.c | 13 +- net/netfilter/nf_flow_table_core.c | 3 +- net/nfc/netlink.c | 2 - net/openvswitch/vport-internal_dev.c | 11 +- sound/core/timer.c | 6 +- sound/firewire/bebob/bebob_focusrite.c | 3 + sound/pci/hda/patch_ca0132.c | 2 +- sound/usb/Makefile | 3 +- sound/usb/clock.c | 14 +- sound/usb/helper.h | 4 + sound/usb/mixer.c | 633 +++++++++------------ sound/usb/power.c | 2 + sound/usb/quirks.c | 3 + sound/usb/stream.c | 25 +- sound/usb/validate.c | 332 +++++++++++ tools/gpio/Makefile | 6 +- tools/perf/util/hist.c | 2 +- tools/usb/usbip/libsrc/usbip_device_driver.c | 6 +- 145 files changed, 2224 insertions(+), 1124 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/125 bonding: fix state transition issue in link monitoring
From: Jay Vosburgh <[email protected]>
[ Upstream commit 1899bb325149e481de31a4f32b59ea6f24e176ea ]
Since de77ecd4ef02 ("bonding: improve link-status update in mii-monitoring"), the bonding driver has utilized two separate variables to indicate the next link state a particular slave should transition to. Each is used to communicate to a different portion of the link state change commit logic; one to the bond_miimon_commit function itself, and another to the state transition logic.
Unfortunately, the two variables can become unsynchronized,
resulting in incorrect link state transitions within bonding. This can cause slaves to become stuck in an incorrect link state until a subsequent carrier state transition.
The issue occurs when a special case in bond_slave_netdev_event
sets slave->link directly to BOND_LINK_FAIL. On the next pass through bond_miimon_inspect after the slave goes carrier up, the BOND_LINK_FAIL case will set the proposed next state (link_new_state) to BOND_LINK_UP, but the new_link to BOND_LINK_DOWN. The setting of the final link state from new_link comes after that from link_new_state, and so the slave will end up incorrectly in _DOWN state.
Resolve this by combining the two variables into one.
--- drivers/net/bonding/bond_main.c | 41 +++++++++++++++++++--------------------- include/net/bonding.h | 3 -- 2 files changed, 21 insertions(+), 23 deletions(-)
drivers/net/bonding/bond_main.c +20 -21
@@ -2074,8 +2074,7 @@ static int bond_miimon_inspect(struct bo ignore_updelay = !rcu_dereference (bond->curr_active_slave);bond_for_each_slave_rcu (bond, slave, iter) { - slave->new_link =BOND_LINK_NOCHANGE ; - slave->link_new_state = slave->link; +bond_propose_link_state (slave,BOND_LINK_NOCHANGE ); link_state =bond_check_dev_link (bond, slave->dev,0 );
@@ -2111,7 +2110,7 @@ static int bond_miimon_inspect(struct bo }if (slave->delay <=0 ) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); commit++;continue ; }
@@ -2150,7 +2149,7 @@ static int bond_miimon_inspect(struct bo slave->delay =0 ;if (slave->delay <=0 ) { - slave->new_link =BOND_LINK_UP ; +bond_propose_link_state (slave,BOND_LINK_UP ); commit++; ignore_updelay = false;continue ;
@@ -2188,7 +2187,7 @@ static void bond_miimon_commit(struct bostruct slave *slave, *primary;bond_for_each_slave (bond, slave, iter) { -switch (slave->new_link) { +switch (slave->link_new_state) {case BOND_LINK_NOCHANGE :/* For 802.3ad mode, check current slave speed and * duplex again in case its port was disabled after
@@ -2263,8 +2262,8 @@ static void bond_miimon_commit(struct bodefault :netdev_err (bond->dev,"invalid new link %d on slave %s\n" , - slave->new_link, slave->dev->name); - slave->new_link =BOND_LINK_NOCHANGE ; + slave->link_new_state, slave->dev->name); +bond_propose_link_state (slave,BOND_LINK_NOCHANGE );continue ; }
@@ -2664,13 +2663,13 @@ static void bond_loadbalance_arp_mon(strbond_for_each_slave_rcu (bond, slave, iter) {unsigned long trans_start =dev_trans_start (slave->dev); - slave->new_link =BOND_LINK_NOCHANGE ; +bond_propose_link_state (slave,BOND_LINK_NOCHANGE );if (slave->link !=BOND_LINK_UP ) {if (bond_time_in_interval (bond, trans_start,1 ) &&bond_time_in_interval (bond, slave->last_rx,1 )) { - slave->new_link =BOND_LINK_UP ; +bond_propose_link_state (slave,BOND_LINK_UP ); slave_state_changed =1 ;/* primary_slave has no meaning in round-robin
@@ -2697,7 +2696,7 @@ static void bond_loadbalance_arp_mon(strif (!bond_time_in_interval (bond, trans_start,2 ) || !bond_time_in_interval (bond, slave->last_rx,2 )) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); slave_state_changed =1 ;if (slave->link_failure_count <UINT_MAX )
@@ -2729,8 +2728,8 @@ static void bond_loadbalance_arp_mon(str goto re_arm;bond_for_each_slave (bond, slave, iter) { -if (slave->new_link !=BOND_LINK_NOCHANGE ) - slave->link = slave->new_link; +if (slave->link_new_state !=BOND_LINK_NOCHANGE ) + slave->link = slave->link_new_state; }if (slave_state_changed) {
@@ -2753,9 +2752,9 @@ re_arm: }/* Called to inspect slaves for active-backup mode ARP monitor link state -* changes. Sets new_link in slaves to specify what action should take -* place for the slave. Returns 0 if no changes are found, >0 if changes -* to link states must be committed. +* changes. Sets proposed link state in slaves to specify what action +* should take place for the slave. Returns 0 if no changes are found, >0 +* if changes to link states must be committed. * * Called with rcu_read_lock held. */
@@ -2767,12 +2766,12 @@ static int bond_ab_arp_inspect(struct boint commit =0 ;bond_for_each_slave_rcu (bond, slave, iter) { - slave->new_link =BOND_LINK_NOCHANGE ; +bond_propose_link_state (slave,BOND_LINK_NOCHANGE ); last_rx =slave_last_rx (bond, slave);if (slave->link !=BOND_LINK_UP ) {if (bond_time_in_interval (bond, last_rx,1 )) { - slave->new_link =BOND_LINK_UP ; +bond_propose_link_state (slave,BOND_LINK_UP ); commit++; }continue ;
@@ -2800,7 +2799,7 @@ static int bond_ab_arp_inspect(struct boif (!bond_is_active_slave (slave) && !rcu_access_pointer (bond->current_arp_slave) && !bond_time_in_interval (bond, last_rx,3 )) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); commit++; }
@@ -2813,7 +2812,7 @@ static int bond_ab_arp_inspect(struct boif (bond_is_active_slave (slave) && (!bond_time_in_interval (bond, trans_start,2 ) || !bond_time_in_interval (bond, last_rx,2 ))) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); commit++; } }
@@ -2833,7 +2832,7 @@ static void bond_ab_arp_commit(struct bostruct slave *slave;bond_for_each_slave (bond, slave, iter) { -switch (slave->new_link) { +switch (slave->link_new_state) {case BOND_LINK_NOCHANGE :continue ;
@@ -2886,7 +2885,7 @@ static void bond_ab_arp_commit(struct bodefault :netdev_err (bond->dev,"impossible: new_link %d on slave %s\n" , - slave->new_link, slave->dev->name); + slave->link_new_state, slave->dev->name);continue ; }
include/net/bonding.h +1 -2
@@ -149,7 +149,6 @@ struct slave {unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS ];s8 link;/* one of BOND_LINK_XXXX */ s8 link_new_state;/* one of BOND_LINK_XXXX */ -s8 new_link; u8 backup:1, /* indicates backup slave. Value corresponds with BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ inactive:1, /* indicates inactive slave */
@@ -539,7 +538,7 @@ static inline void bond_propose_link_stastatic inline void bond_commit_link_state (struct slave *slave,bool notify) { -if (slave->link == slave->link_new_state) +if (slave->link_new_state ==BOND_LINK_NOCHANGE )return ; slave->link = slave->link_new_state;
Re: [PATCH 4.19 001/125] bonding: fix state transition issue in link monitoring
Quoted 181 lines · Greg Kroah-Hartman
From: Jay Vosburgh <[email protected]>
[ Upstream commit
1899bb325149e481de31a4f32b59ea6f24e176ea]Since
de77ecd4ef02("bonding: improve link-status update in mii-monitoring"), the bonding driver has utilized two separate variables to indicate the next link state a particular slave should transition to. Each is used to communicate to a different portion of the link state change commit logic; one to thebond_miimon_commitfunction itself, and another to the state transition logic.Unfortunately, the two variables can become unsynchronized,
resulting in incorrect link state transitions within bonding. This can cause slaves to become stuck in an incorrect link state until a subsequent carrier state transition.The issue occurs when a special case in
bond_slave_netdev_event
setsslave->linkdirectly toBOND_LINK_FAIL. On the next pass throughbond_miimon_inspectafter the slave goes carrier up, theBOND_LINK_FAILcase will set the proposed next state (link_new_state) toBOND_LINK_UP, but thenew_linktoBOND_LINK_DOWN. The setting of the final link state fromnew_linkcomes after that fromlink_new_state, and so the slave will end up incorrectly in_DOWNstate.Resolve this by combining the two variables into one.
Reported-by Aleksei Zakharov <[email protected]>Reported-by Sha Zhang <[email protected]>Cc Mahesh Bandewar <[email protected]>Fixes de77ecd4ef02 ("bonding: improve link-status update in mii-monitoring")Signed-off-by Jay Vosburgh <[email protected]>Signed-off-by David S. Miller <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- drivers/net/bonding/bond_main.c | 41 +++++++++++++++++++--------------------- include/net/bonding.h | 3 -- 2 files changed, 21 insertions(+), 23 deletions(-)drivers/net/bonding/bond_main.c +19
-20@@ -2074,8 +2074,7 @@ static int bond_miimon_inspect(struct bo ignore_updelay = !rcu_dereference (bond->curr_active_slave);bond_for_each_slave_rcu (bond, slave, iter) { - slave->new_link =BOND_LINK_NOCHANGE ; - slave->link_new_state = slave->link; +bond_propose_link_state (slave,BOND_LINK_NOCHANGE ); link_state =bond_check_dev_link (bond, slave->dev,0 );@@ -2111,7 +2110,7 @@ static int bond_miimon_inspect(struct bo }if (slave->delay <=0 ) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); commit++;continue ; }@@ -2150,7 +2149,7 @@ static int bond_miimon_inspect(struct bo slave->delay =0 ;if (slave->delay <=0 ) { - slave->new_link =BOND_LINK_UP ; +bond_propose_link_state (slave,BOND_LINK_UP ); commit++; ignore_updelay = false;continue ;@@ -2188,7 +2187,7 @@ static void bond_miimon_commit(struct bostruct slave *slave, *primary;bond_for_each_slave (bond, slave, iter) { -switch (slave->new_link) { +switch (slave->link_new_state) {case BOND_LINK_NOCHANGE :/* For 802.3ad mode, check current slave speed and * duplex again in case its port was disabled after @@ -2263,8 +2262,8 @@ static void bond_miimon_commit(struct bodefault :netdev_err (bond->dev,"invalid new link %d on slave %s\n" , - slave->new_link, slave->dev->name); - slave->new_link =BOND_LINK_NOCHANGE ; + slave->link_new_state, slave->dev->name); +bond_propose_link_state (slave,BOND_LINK_NOCHANGE );continue ; }@@ -2664,13 +2663,13 @@ static void bond_loadbalance_arp_mon(strbond_for_each_slave_rcu (bond, slave, iter) {unsigned long trans_start =dev_trans_start (slave->dev); - slave->new_link =BOND_LINK_NOCHANGE ; +bond_propose_link_state (slave,BOND_LINK_NOCHANGE );if (slave->link !=BOND_LINK_UP ) {if (bond_time_in_interval (bond, trans_start,1 ) &&bond_time_in_interval (bond, slave->last_rx,1 )) { - slave->new_link =BOND_LINK_UP ; +bond_propose_link_state (slave,BOND_LINK_UP ); slave_state_changed =1 ;/* primary_slave has no meaning in round-robin @@ -2697,7 +2696,7 @@ static void bond_loadbalance_arp_mon(strif (!bond_time_in_interval (bond, trans_start,2 ) || !bond_time_in_interval (bond, slave->last_rx,2 )) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); slave_state_changed =1 ;if (slave->link_failure_count <UINT_MAX )@@ -2729,8 +2728,8 @@ static void bond_loadbalance_arp_mon(str goto re_arm;bond_for_each_slave (bond, slave, iter) { -if (slave->new_link !=BOND_LINK_NOCHANGE ) - slave->link = slave->new_link; +if (slave->link_new_state !=BOND_LINK_NOCHANGE ) + slave->link = slave->link_new_state; }if (slave_state_changed) {@@ -2753,9 +2752,9 @@ re_arm: }/* Called to inspect slaves for active-backup mode ARP monitor link state -* changes. Sets new_link in slaves to specify what action should take -* place for the slave. Returns 0 if no changes are found, >0 if changes -* to link states must be committed. +* changes. Sets proposed link state in slaves to specify what action +* should take place for the slave. Returns 0 if no changes are found, >0 +* if changes to link states must be committed. * * Called with rcu_read_lock held. */ @@ -2767,12 +2766,12 @@ static int bond_ab_arp_inspect(struct boint commit =0 ;bond_for_each_slave_rcu (bond, slave, iter) { - slave->new_link =BOND_LINK_NOCHANGE ; +bond_propose_link_state (slave,BOND_LINK_NOCHANGE ); last_rx =slave_last_rx (bond, slave);if (slave->link !=BOND_LINK_UP ) {if (bond_time_in_interval (bond, last_rx,1 )) { - slave->new_link =BOND_LINK_UP ; +bond_propose_link_state (slave,BOND_LINK_UP ); commit++; }continue ;@@ -2800,7 +2799,7 @@ static int bond_ab_arp_inspect(struct boif (!bond_is_active_slave (slave) && !rcu_access_pointer (bond->current_arp_slave) && !bond_time_in_interval (bond, last_rx,3 )) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); commit++; }@@ -2813,7 +2812,7 @@ static int bond_ab_arp_inspect(struct boif (bond_is_active_slave (slave) && (!bond_time_in_interval (bond, trans_start,2 ) || !bond_time_in_interval (bond, last_rx,2 ))) { - slave->new_link =BOND_LINK_DOWN ; +bond_propose_link_state (slave,BOND_LINK_DOWN ); commit++; } }@@ -2833,7 +2832,7 @@ static void bond_ab_arp_commit(struct bostruct slave *slave;bond_for_each_slave (bond, slave, iter) { -switch (slave->new_link) { +switch (slave->link_new_state) {case BOND_LINK_NOCHANGE :continue ;
drivers/net/bonding/bond_main.c static void bond_ab_arp_commit(struct bo · line 2887
Quoted 3 lines
drivers/net/bonding/bond_main.c +0
-0@@ -2886,7 +2885,7 @@ static void bond_ab_arp_commit(struct bodefault : netdev_err(bond->dev, "impossible: new_link %d on slave %s\n",
Hello,
I think the error message here should be: "impossible: link_new_state %d on slave %s\n" instead?
As in the upstream commit it's:
slave_err(bond->dev, slave->dev,
"impossible: link_new_state %d on slave\n",
slave->link_new_state);Thanks
Quoted 26 lines
drivers/net/bonding/bond_main.c +1
-1- slave->new_link, slave->dev->name); + slave->link_new_state, slave->dev->name);continue ; }include/net/bonding.h +1
-2@@ -149,7 +149,6 @@ struct slave {unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS ];s8 link;/* one of BOND_LINK_XXXX */ s8 link_new_state;/* one of BOND_LINK_XXXX */ -s8 new_link; u8 backup:1, /* indicates backup slave. Value corresponds withBOND_STATE_ACTIVE and BOND_STATE_BACKUP */ inactive:1, /* indicates inactive slave */@@ -539,7 +538,7 @@ static inline void bond_propose_link_stastatic inline void bond_commit_link_state (struct slave *slave,bool notify) { -if (slave->link == slave->link_new_state) +if (slave->link_new_state ==BOND_LINK_NOCHANGE )return ; slave->link = slave->link_new_state;
Greg Kroah-Hartman
maintainerPATCH 2/125 CDC-NCM: handle incomplete transfer of MTU
In reply to Greg Kroah-HartmanFrom: Oliver Neukum <[email protected]>
[ Upstream commit 332f989a3b0041b810836c5c3747e59aad7e9d0b ]
A malicious device may give half an answer when asked for its MTU. The driver will proceed after this with a garbage MTU. Anything but a complete answer must be treated as an error.
V2: used sizeof as request by Alexander
--- drivers/net/usb/cdc_ncm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/usb/cdc_ncm.c +3 -3
@@ -578,8 +578,8 @@ static void cdc_ncm_set_dgram_size(struc/* read current mtu value from device */ err =usbnet_read_cmd (dev,USB_CDC_GET_MAX_DATAGRAM_SIZE ,USB_TYPE_CLASS |USB_DIR_IN |USB_RECIP_INTERFACE , -0 , iface_no, &max_datagram_size,2 ); -if (err <0 ) { +0 , iface_no, &max_datagram_size,sizeof (max_datagram_size)); +if (err <sizeof (max_datagram_size)) {dev_dbg (&dev->intf->dev,"GET_MAX_DATAGRAM_SIZE failed\n" ); goto out; }
@@ -590,7 +590,7 @@ static void cdc_ncm_set_dgram_size(struc max_datagram_size =cpu_to_le16 (ctx->max_datagram_size); err =usbnet_write_cmd (dev,USB_CDC_SET_MAX_DATAGRAM_SIZE ,USB_TYPE_CLASS |USB_DIR_OUT |USB_RECIP_INTERFACE , -0 , iface_no, &max_datagram_size,2 ); +0 , iface_no, &max_datagram_size,sizeof (max_datagram_size));if (err <0 )dev_dbg (&dev->intf->dev,"SET_MAX_DATAGRAM_SIZE failed\n" );
Greg Kroah-Hartman
maintainerPATCH 3/125 ipv4: Fix table id reference in fib_sync_down_addr
In reply to Greg Kroah-HartmanFrom: David Ahern <[email protected]>
[ Upstream commit e0a312629fefa943534fc46f7bfbe6de3fdaf463 ]
Hendrik reported routes in the main table using source address are not removed when the address is removed. The problem is that fib_sync_down_addr does not account for devices in the default VRF which are associated with the main table. Fix by updating the table id reference.
--- net/ipv4/fib_semantics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/fib_semantics.c +1 -1
@@ -1421,8 +1421,8 @@ int fib_sync_down_addr(struct net_deviceint ret =0 ;unsigned int hash =fib_laddr_hashfn (local);struct hlist_head *head = &fib_info_laddrhash[hash]; +int tb_id =l3mdev_fib_table (dev) ? :RT_TABLE_MAIN ;struct net *net =dev_net (dev); -int tb_id =l3mdev_fib_table (dev);struct fib_info *fi;if (!fib_info_laddrhash || local ==0 )
Greg Kroah-Hartman
maintainerPATCH 4/125 net: ethernet: octeon_mgmt: Account for second possible VLAN header
In reply to Greg Kroah-HartmanFrom: Alexander Sverdlin <[email protected]>
[ Upstream commit e4dd5608033efe7b6030cde359bfdbaeb73bc22d ]
Octeon's input ring-buffer entry has 14 bits-wide size field, so to account for second possible VLAN header max_mtu must be further reduced.
--- drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +1 -1
@@ -1495,7 +1495,7 @@ static int octeon_mgmt_probe(struct plat netdev->ethtool_ops = &octeon_mgmt_ethtool_ops; netdev->min_mtu =64 -OCTEON_MGMT_RX_HEADROOM ; - netdev->max_mtu =16383 -OCTEON_MGMT_RX_HEADROOM ; + netdev->max_mtu =16383 -OCTEON_MGMT_RX_HEADROOM -VLAN_HLEN ; mac =of_get_mac_address (pdev->dev.of_node);
Greg Kroah-Hartman
maintainerPATCH 5/125 net: fix data-race in neigh_event_send()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 1b53d64435d56902fc234ff2507142d971a09687 ]
KCSAN reported the following data-race [1]
The fix will also prevent the compiler from optimizing out the condition.
[1]
BUG: KCSAN: data-race in neigh_resolve_output / neigh_resolve_output
write to 0xffff8880a41dba78 of 8 bytes by interrupt on cpu 1:
neigh_event_send include/net/neighbour.h:443 [inline] neigh_resolve_output+0x78/0x480 net/core/neighbour.c:1474 neigh_output include/net/neighbour.h:511 [inline] ip_finish_output2+0x4af/0xe40 net/ipv4/ip_output.c:228 __ip_finish_output net/ipv4/ip_output.c:308 [inline] __ip_finish_output+0x23a/0x490 net/ipv4/ip_output.c:290 ip_finish_output+0x41/0x160 net/ipv4/ip_output.c:318 NF_HOOK_COND include/linux/netfilter.h:294 [inline] ip_output+0xdf/0x210 net/ipv4/ip_output.c:432 dst_output include/net/dst.h:436 [inline] ip_local_out+0x74/0x90 net/ipv4/ip_output.c:125 __ip_queue_xmit+0x3a8/0xa40 net/ipv4/ip_output.c:532 ip_queue_xmit+0x45/0x60 include/net/ip.h:237 __tcp_transmit_skb+0xe81/0x1d60 net/ipv4/tcp_output.c:1169 tcp_transmit_skb net/ipv4/tcp_output.c:1185 [inline] __tcp_retransmit_skb+0x4bd/0x15f0 net/ipv4/tcp_output.c:2976 tcp_retransmit_skb+0x36/0x1a0 net/ipv4/tcp_output.c:2999 tcp_retransmit_timer+0x719/0x16d0 net/ipv4/tcp_timer.c:515 tcp_write_timer_handler+0x42d/0x510 net/ipv4/tcp_timer.c:598 tcp_write_timer+0xd1/0xf0 net/ipv4/tcp_timer.c:618
read to 0xffff8880a41dba78 of 8 bytes by interrupt on cpu 0:
neigh_event_send include/net/neighbour.h:442 [inline] neigh_resolve_output+0x57/0x480 net/core/neighbour.c:1474 neigh_output include/net/neighbour.h:511 [inline] ip_finish_output2+0x4af/0xe40 net/ipv4/ip_output.c:228 __ip_finish_output net/ipv4/ip_output.c:308 [inline] __ip_finish_output+0x23a/0x490 net/ipv4/ip_output.c:290 ip_finish_output+0x41/0x160 net/ipv4/ip_output.c:318 NF_HOOK_COND include/linux/netfilter.h:294 [inline] ip_output+0xdf/0x210 net/ipv4/ip_output.c:432 dst_output include/net/dst.h:436 [inline] ip_local_out+0x74/0x90 net/ipv4/ip_output.c:125 __ip_queue_xmit+0x3a8/0xa40 net/ipv4/ip_output.c:532 ip_queue_xmit+0x45/0x60 include/net/ip.h:237 __tcp_transmit_skb+0xe81/0x1d60 net/ipv4/tcp_output.c:1169 tcp_transmit_skb net/ipv4/tcp_output.c:1185 [inline] __tcp_retransmit_skb+0x4bd/0x15f0 net/ipv4/tcp_output.c:2976 tcp_retransmit_skb+0x36/0x1a0 net/ipv4/tcp_output.c:2999 tcp_retransmit_timer+0x719/0x16d0 net/ipv4/tcp_timer.c:515 tcp_write_timer_handler+0x42d/0x510 net/ipv4/tcp_timer.c:598
Reported by Kernel Concurrency Sanitizer on:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.0-rc3+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
--- include/net/neighbour.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/net/neighbour.h +2 -2
@@ -430,8 +430,8 @@ static inline int neigh_event_send(struc {unsigned long now = jiffies; -if (neigh->used != now) - neigh->used = now; +if (READ_ONCE (neigh->used) != now) +WRITE_ONCE (neigh->used, now);if (!(neigh->nud_state&(NUD_CONNECTED |NUD_DELAY |NUD_PROBE )))return __neigh_event_send (neigh, skb);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 6/125 net: qualcomm: rmnet: Fix potential UAF when unregistering
In reply to Greg Kroah-HartmanFrom: Sean Tranchetti <[email protected]>
[ Upstream commit e7a86c687e64ab24f88330ad24ecc9442ce40c5a ]
During the exit/unregistration process of the RmNet driver, the function rmnet_unregister_real_device() is called to handle freeing the driver's internal state and removing the RX handler on the underlying physical device. However, the order of operations this function performs is wrong and can lead to a use after free of the rmnet_port structure.
Before calling netdev_rx_handler_unregister(), this port structure is freed with kfree(). If packets are received on any RmNet devices before synchronize_net() completes, they will attempt to use this already-freed port structure when processing the packet. As such, before cleaning up any other internal state, the RX handler must be unregistered in order to guarantee that no further packets will arrive on the device.
--- drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +2 -2
@@ -66,10 +66,10 @@ static int rmnet_unregister_real_device(if (port->nr_rmnet_devs)return -EINVAL ; -kfree (port); -netdev_rx_handler_unregister (real_dev); +kfree (port); +/* release reference on real_dev */ dev_put (real_dev);
Greg Kroah-Hartman
maintainerPATCH 7/125 net: usb: qmi_wwan: add support for DW5821e with eSIM support
In reply to Greg Kroah-HartmanFrom: Aleksander Morgado <[email protected]>
[ Upstream commit e497df686e8fed8c1dd69179010656362858edb3 ]
Exactly same layout as the default DW5821e module, just a different vid/pid.
The QMI interface is exposed in USB configuration #1:
P: Vendor=413c ProdID=81e0 Rev=03.18 S: Manufacturer=Dell Inc. S: Product=DW5821e-eSIM Snapdragon X20 LTE S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#=0x0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan I: If#=0x1 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#=0x5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
--- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/usb/qmi_wwan.c +1 -0
@@ -1297,6 +1297,7 @@ static const struct usb_device_id produc {QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */ {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ + {QMI_FIXED_INTF(0x413c, 0x81e0, 0)}, /* Dell Wireless 5821e with eSIM support*/ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */
Greg Kroah-Hartman
maintainerPATCH 8/125 NFC: fdp: fix incorrect free object
In reply to Greg Kroah-HartmanFrom: Pan Bian <[email protected]>
[ Upstream commit 517ce4e93368938b204451285e53014549804868 ]
The address of fw_vsc_cfg is on stack. Releasing it with devm_kfree() is incorrect, which may result in a system crash or other security impacts. The expected object to free is *fw_vsc_cfg.
--- drivers/nfc/fdp/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nfc/fdp/i2c.c +1 -1
@@ -267,7 +267,7 @@ static void fdp_nci_i2c_read_device_prop *fw_vsc_cfg, len);if (r) { -devm_kfree (dev, fw_vsc_cfg); +devm_kfree (dev, *fw_vsc_cfg); goto vsc_read_err; } }else {
Greg Kroah-Hartman
maintainerPATCH 9/125 nfc: netlink: fix double device reference drop
In reply to Greg Kroah-HartmanFrom: Pan Bian <[email protected]>
[ Upstream commit 025ec40b81d785a98f76b8bdb509ac10773b4f12 ]
The function nfc_put_device(dev) is called twice to drop the reference to dev when there is no associated local llcp. Remove one of them to fix the bug.
--- net/nfc/netlink.c | 2 -- 1 file changed, 2 deletions(-)
net/nfc/netlink.c +0 -2
@@ -1110,7 +1110,6 @@ static int nfc_genl_llc_set_params(struc local =nfc_llcp_find_local (dev);if (!local) { -nfc_put_device (dev); rc = -ENODEV ; goto exit; }
@@ -1170,7 +1169,6 @@ static int nfc_genl_llc_sdreq(struct sk_ local =nfc_llcp_find_local (dev);if (!local) { -nfc_put_device (dev); rc = -ENODEV ; goto exit; }
Greg Kroah-Hartman
maintainerPATCH 10/125 NFC: st21nfca: fix double free
In reply to Greg Kroah-HartmanFrom: Pan Bian <[email protected]>
[ Upstream commit 99a8efbb6e30b72ac98cecf81103f847abffb1e5 ]
The variable nfcid_skb is not changed in the callee nfc_hci_get_param() if error occurs. Consequently, the freed variable nfcid_skb will be freed again, resulting in a double free bug. Set nfcid_skb to NULL after releasing it to fix the bug.
--- drivers/nfc/st21nfca/core.c | 1 + 1 file changed, 1 insertion(+)
drivers/nfc/st21nfca/core.c +1 -0
@@ -719,6 +719,7 @@ static int st21nfca_hci_complete_target_NFC_PROTO_FELICA_MASK ; }else {kfree_skb (nfcid_skb); + nfcid_skb =NULL ;/* P2P in type A */ r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, ST21NFCA_RF_READER_F_NFCID1,
Greg Kroah-Hartman
maintainerPATCH 11/125 qede: fix NULL pointer deref in __qede_remove()
In reply to Greg Kroah-HartmanFrom: Manish Chopra <[email protected]>
[ Upstream commit deabc87111c690097c03765ea017cd500f7376fc ]
While rebooting the system with SR-IOV vfs enabled leads to below crash due to recurrence of __qede_remove() on the VF devices (first from .shutdown() flow of the VF itself and another from PF's .shutdown() flow executing pci_disable_sriov())
This patch adds a safeguard in __qede_remove() flow to fix this, so that driver doesn't attempt to remove "already removed" devices.
[ 194.360134] BUG: unable to handle kernel NULL pointer dereference at 00000000000008dc [ 194.360227] IP: [<ffffffffc03553c4>] __qede_remove+0x24/0x130 [qede] [ 194.360304] PGD 0 [ 194.360325] Oops: 0000 [#1] SMP [ 194.360360] Modules linked in: tcp_lp fuse tun bridge stp llc devlink bonding ip_set nfnetlink ib_isert iscsi_target_mod ib_srpt target_core_mod ib_srp scsi_transport_srp scsi_tgt ib_ipoib ib_umad rpcrdma sunrpc rdma_ucm ib_uverbs ib_iser rdma_cm iw_cm ib_cm libiscsi scsi_transport_iscsi dell_smbios iTCO_wdt iTCO_vendor_support dell_wmi_descriptor dcdbas vfat fat pcc_cpufreq skx_edac intel_powerclamp coretemp intel_rapl iosf_mbi kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd qedr ib_core pcspkr ses enclosure joydev ipmi_ssif sg i2c_i801 lpc_ich mei_me mei wmi ipmi_si ipmi_devintf ipmi_msghandler tpm_crb acpi_pad acpi_power_meter xfs libcrc32c sd_mod crc_t10dif crct10dif_generic crct10dif_pclmul crct10dif_common crc32c_intel mgag200 [ 194.361044] qede i2c_algo_bit drm_kms_helper qed syscopyarea sysfillrect nvme sysimgblt fb_sys_fops ttm nvme_core mpt3sas crc8 ptp drm pps_core ahci raid_class scsi_transport_sas libahci libata drm_panel_orientation_quirks nfit libnvdimm dm_mirror dm_region_hash dm_log dm_mod [last unloaded: ip_tables] [ 194.361297] CPU: 51 PID: 7996 Comm: reboot Kdump: loaded Not tainted 3.10.0-1062.el7.x86_64 #1 [ 194.361359] Hardware name: Dell Inc. PowerEdge MX840c/0740HW, BIOS 2.4.6 10/15/2019 [ 194.361412] task: ffff9cea9b360000 ti: ffff9ceabebdc000 task.ti: ffff9ceabebdc000 [ 194.361463] RIP: 0010:[<ffffffffc03553c4>] [<ffffffffc03553c4>] __qede_remove+0x24/0x130 [qede] [ 194.361534] RSP: 0018:ffff9ceabebdfac0 EFLAGS: 00010282 [ 194.361570] RAX: 0000000000000000 RBX: ffff9cd013846098 RCX: 0000000000000000 [ 194.361621] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff9cd013846098 [ 194.361668] RBP: ffff9ceabebdfae8 R08: 0000000000000000 R09: 0000000000000000 [ 194.361715] R10: 00000000bfe14201 R11: ffff9ceabfe141e0 R12: 0000000000000000 [ 194.361762] R13: ffff9cd013846098 R14: 0000000000000000 R15: ffff9ceab5e48000 [ 194.361810] FS: 00007f799c02d880(0000) GS:ffff9ceacb0c0000(0000) knlGS:0000000000000000 [ 194.361865] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 194.361903] CR2: 00000000000008dc CR3: 0000001bdac76000 CR4: 00000000007607e0 [ 194.361953] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 194.362002] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 194.362051] PKRU: 55555554 [ 194.362073] Call Trace: [ 194.362109] [<ffffffffc0355500>] qede_remove+0x10/0x20 [qede] [ 194.362180] [<ffffffffb97d0f3e>] pci_device_remove+0x3e/0xc0 [ 194.362240] [<ffffffffb98b3c52>] __device_release_driver+0x82/0xf0 [ 194.362285] [<ffffffffb98b3ce3>] device_release_driver+0x23/0x30 [ 194.362343] [<ffffffffb97c86d4>] pci_stop_bus_device+0x84/0xa0 [ 194.362388] [<ffffffffb97c87e2>] pci_stop_and_remove_bus_device+0x12/0x20 [ 194.362450] [<ffffffffb97f153f>] pci_iov_remove_virtfn+0xaf/0x160 [ 194.362496] [<ffffffffb97f1aec>] sriov_disable+0x3c/0xf0 [ 194.362534] [<ffffffffb97f1bc3>] pci_disable_sriov+0x23/0x30 [ 194.362599] [<ffffffffc02f83c3>] qed_sriov_disable+0x5e3/0x650 [qed] [ 194.362658] [<ffffffffb9622df6>] ? kfree+0x106/0x140 [ 194.362709] [<ffffffffc02cc0c0>] ? qed_free_stream_mem+0x70/0x90 [qed] [ 194.362754] [<ffffffffb9622df6>] ? kfree+0x106/0x140 [ 194.362803] [<ffffffffc02cd659>] qed_slowpath_stop+0x1a9/0x1d0 [qed] [ 194.362854] [<ffffffffc035544e>] __qede_remove+0xae/0x130 [qede] [ 194.362904] [<ffffffffc03554e0>] qede_shutdown+0x10/0x20 [qede] [ 194.362956] [<ffffffffb97cf90a>] pci_device_shutdown+0x3a/0x60 [ 194.363010] [<ffffffffb98b180b>] device_shutdown+0xfb/0x1f0 [ 194.363066] [<ffffffffb94b66c6>] kernel_restart_prepare+0x36/0x40 [ 194.363107] [<ffffffffb94b66e2>] kernel_restart+0x12/0x60 [ 194.363146] [<ffffffffb94b6959>] SYSC_reboot+0x229/0x260 [ 194.363196] [<ffffffffb95f200d>] ? handle_mm_fault+0x39d/0x9b0 [ 194.363253] [<ffffffffb942b621>] ? __switch_to+0x151/0x580 [ 194.363304] [<ffffffffb9b7ec28>] ? __schedule+0x448/0x9c0 [ 194.363343] [<ffffffffb94b69fe>] SyS_reboot+0xe/0x10 [ 194.363387] [<ffffffffb9b8bede>] system_call_fastpath+0x25/0x2a [ 194.363430] Code: f9 e9 37 ff ff ff 90 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 4c 8d af 98 00 00 00 41 54 4c 89 ef 41 89 f4 53 e8 4c e4 55 f9 <80> b8 dc 08 00 00 01 48 89 c3 4c 8d b8 c0 08 00 00 4c 8b b0 c0 [ 194.363712] RIP [<ffffffffc03553c4>] __qede_remove+0x24/0x130 [qede] [ 194.363764] RSP <ffff9ceabebdfac0> [ 194.363791] CR2: 00000000000008dc
--- drivers/net/ethernet/qlogic/qede/qede_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/net/ethernet/qlogic/qede/qede_main.c +10 -2
@@ -1170,8 +1170,16 @@ enum qede_remove_mode {static void __qede_remove (struct pci_dev *pdev,enum qede_remove_mode mode) {struct net_device *ndev =pci_get_drvdata (pdev); -struct qede_dev *edev =netdev_priv (ndev); -struct qed_dev *cdev = edev->cdev; +struct qede_dev *edev; +struct qed_dev *cdev; + +if (!ndev) { +dev_info (&pdev->dev,"Device has already been removed\n" ); +return ; + } + + edev =netdev_priv (ndev); + cdev = edev->cdev;DP_INFO (edev,"Starting qede_remove\n" );
Greg Kroah-Hartman
maintainerPATCH 12/125 net: mscc: ocelot: dont handle netdev events for other netdevs
In reply to Greg Kroah-HartmanFrom: Claudiu Manoil <[email protected]>
[ Upstream commit 7afb3e575e5aa9f5a200a3eb3f45d8130f6d6601 ]
The check that the event is actually for this device should be moved from the "port" handler to the net device handler.
Otherwise the port handler will deny bonding configuration for other net devices in the same system (like enetc in the LS1028A) that don't have the lag_upper_info->tx_type restriction that ocelot has.
--- drivers/net/ethernet/mscc/ocelot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/mscc/ocelot.c +3 -3
@@ -1506,9 +1506,6 @@ static int ocelot_netdevice_port_event(sstruct ocelot_port *ocelot_port =netdev_priv (dev);int err =0 ; -if (!ocelot_netdevice_dev_check (dev)) -return 0 ; -switch (event) {case NETDEV_CHANGEUPPER :if (netif_is_bridge_master (info->upper_dev)) {
@@ -1545,6 +1542,9 @@ static int ocelot_netdevice_event(structstruct net_device *dev =netdev_notifier_info_to_dev (ptr);int ret =0 ; +if (!ocelot_netdevice_dev_check (dev)) +return 0 ; +if (event ==NETDEV_PRECHANGEUPPER &&netif_is_lag_master (info->upper_dev)) {struct netdev_lag_upper_info *lag_upper_info = info->upper_info;
Greg Kroah-Hartman
maintainerPATCH 13/125 net: mscc: ocelot: fix NULL pointer on LAG slave removal
In reply to Greg Kroah-HartmanFrom: Claudiu Manoil <[email protected]>
[ Upstream commit 3b3eed8eec47259939ee6c3d58aea1c311ddee3b ]
lag_upper_info may be NULL on slave removal.
--- drivers/net/ethernet/mscc/ocelot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mscc/ocelot.c +2 -1
@@ -1550,7 +1550,8 @@ static int ocelot_netdevice_event(structstruct netdev_lag_upper_info *lag_upper_info = info->upper_info;struct netlink_ext_ack *extack; -if (lag_upper_info->tx_type !=NETDEV_LAG_TX_TYPE_HASH ) { +if (lag_upper_info && + lag_upper_info->tx_type !=NETDEV_LAG_TX_TYPE_HASH ) { extack =netdev_notifier_info_to_extack (&info->info);NL_SET_ERR_MSG_MOD (extack,"LAG device using unsupported Tx type" );
Greg Kroah-Hartman
maintainerPATCH 14/125 ipv6: fixes rt6_probe() and fib6_nh->last_probe init
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 1bef4c223b8588cf50433bdc2c6953d82949b3b3 ]
While looking at a syzbot KCSAN report [1], I found multiple issues in this code :
1) fib6_nh->last_probe has an initial value of 0.
While probably okay on 64bit kernels, this causes an issue on 32bit kernels since the time_after(jiffies, 0 + interval) might be false ~24 days after boot (for HZ=1000)
2) The data-race found by KCSAN
I could use READ_ONCE() and WRITE_ONCE(), but we also can take the opportunity of not piling-up too many rt6_probe_deferred() works by using instead cmpxchg() so that only one cpu wins the race.
[1]
BUG: KCSAN: data-race in find_match / find_match
write to 0xffff8880bb7aabe8 of 8 bytes by interrupt on cpu 1:
rt6_probe net/ipv6/route.c:663 [inline] find_match net/ipv6/route.c:757 [inline] find_match+0x5bd/0x790 net/ipv6/route.c:733 __find_rr_leaf+0xe3/0x780 net/ipv6/route.c:831 find_rr_leaf net/ipv6/route.c:852 [inline] rt6_select net/ipv6/route.c:896 [inline] fib6_table_lookup+0x383/0x650 net/ipv6/route.c:2164 ip6_pol_route+0xee/0x5c0 net/ipv6/route.c:2200 ip6_pol_route_output+0x48/0x60 net/ipv6/route.c:2452 fib6_rule_lookup+0x3d6/0x470 net/ipv6/fib6_rules.c:117 ip6_route_output_flags_noref+0x16b/0x230 net/ipv6/route.c:2484 ip6_route_output_flags+0x50/0x1a0 net/ipv6/route.c:2497 ip6_dst_lookup_tail+0x25d/0xc30 net/ipv6/ip6_output.c:1049 ip6_dst_lookup_flow+0x68/0x120 net/ipv6/ip6_output.c:1150 inet6_csk_route_socket+0x2f7/0x420 net/ipv6/inet6_connection_sock.c:106 inet6_csk_xmit+0x91/0x1f0 net/ipv6/inet6_connection_sock.c:121 __tcp_transmit_skb+0xe81/0x1d60 net/ipv4/tcp_output.c:1169 tcp_transmit_skb net/ipv4/tcp_output.c:1185 [inline] tcp_xmit_probe_skb+0x19b/0x1d0 net/ipv4/tcp_output.c:3735
read to 0xffff8880bb7aabe8 of 8 bytes by interrupt on cpu 0:
rt6_probe net/ipv6/route.c:657 [inline] find_match net/ipv6/route.c:757 [inline] find_match+0x521/0x790 net/ipv6/route.c:733 __find_rr_leaf+0xe3/0x780 net/ipv6/route.c:831 find_rr_leaf net/ipv6/route.c:852 [inline] rt6_select net/ipv6/route.c:896 [inline] fib6_table_lookup+0x383/0x650 net/ipv6/route.c:2164 ip6_pol_route+0xee/0x5c0 net/ipv6/route.c:2200 ip6_pol_route_output+0x48/0x60 net/ipv6/route.c:2452 fib6_rule_lookup+0x3d6/0x470 net/ipv6/fib6_rules.c:117 ip6_route_output_flags_noref+0x16b/0x230 net/ipv6/route.c:2484 ip6_route_output_flags+0x50/0x1a0 net/ipv6/route.c:2497 ip6_dst_lookup_tail+0x25d/0xc30 net/ipv6/ip6_output.c:1049 ip6_dst_lookup_flow+0x68/0x120 net/ipv6/ip6_output.c:1150 inet6_csk_route_socket+0x2f7/0x420 net/ipv6/inet6_connection_sock.c:106 inet6_csk_xmit+0x91/0x1f0 net/ipv6/inet6_connection_sock.c:121 __tcp_transmit_skb+0xe81/0x1d60 net/ipv4/tcp_output.c:1169
Reported by Kernel Concurrency Sanitizer on:
CPU: 0 PID: 18894 Comm: udevd Not tainted 5.4.0-rc3+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
--- net/ipv6/route.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
net/ipv6/route.c +10 -3
@@ -521,6 +521,7 @@ static void rt6_probe(struct fib6_info * {struct __rt6_probe_work *work =NULL ;const struct in6_addr *nh_gw; +unsigned long last_probe;struct neighbour *neigh;struct net_device *dev;struct inet6_dev *idev;
@@ -539,6 +540,7 @@ static void rt6_probe(struct fib6_info * nh_gw = &rt->fib6_nh.nh_gw; dev = rt->fib6_nh.nh_dev;rcu_read_lock_bh (); + last_probe =READ_ONCE (rt->last_probe); idev =__in6_dev_get (dev); neigh =__ipv6_neigh_lookup_noref (dev, nh_gw);if (neigh) {
@@ -554,13 +556,15 @@ static void rt6_probe(struct fib6_info *__neigh_set_probe_once (neigh); }write_unlock (&neigh->lock); - }else if (time_after (jiffies, rt->last_probe + + }else if (time_after (jiffies, last_probe + idev->cnf.rtr_probe_interval)) { work =kmalloc (sizeof (*work),GFP_ATOMIC ); } -if (work) { - rt->last_probe = jiffies; +if (!work ||cmpxchg (&rt->last_probe, + last_probe, jiffies) != last_probe) { +kfree (work); + }else {INIT_WORK (&work->work, rt6_probe_deferred); work->target = *nh_gw;dev_hold (dev);
@@ -3066,6 +3070,9 @@ static struct fib6_info *ip6_route_info_if (!rt) goto out; +#ifdef CONFIG_IPV6_ROUTER_PREF + rt->last_probe = jiffies; +#endif if (cfg->fc_flags &RTF_ADDRCONF ) rt->dst_nocount = true;
Greg Kroah-Hartman
maintainerPATCH 15/125 net: hns: Fix the stray netpoll locks causing deadlock in NAPI path
In reply to Greg Kroah-HartmanFrom: Salil Mehta <[email protected]>
[ Upstream commit bf5a6b4c474c589244dc25ee1af2c3c829228ef8 ]
This patch fixes the problem of the spin locks, originally meant for the netpoll path of hns driver, causing deadlock in the normal NAPI poll path. The issue happened due to the presence of the stray leftover spin lock code related to the netpoll, whose support was earlier removed from the HNS[1], got activated due to enabling of NET_POLL_CONTROLLER switch.
Earlier background:
The netpoll handling code originally had this bug(as identified by Marc Zyngier[2]) of wrong spin lock API being used which did not disable the interrupts and hence could cause locking issues. i.e. if the lock were first acquired in context to thread like 'ip' util and this lock if ever got later acquired again in context to the interrupt context like TX/RX (Interrupts could always pre-empt the lock holding task and acquire the lock again) and hence could cause deadlock.
Proposed Solution:
1. If the netpoll was enabled in the HNS driver, which is not right now, we could have simply used spin_[un]lock_irqsave()
2. But as netpoll is disabled, therefore, it is best to get rid of the existing locks and stray code for now. This should solve the problem reported by Marc.
[1] https://git.kernel.org/torvalds/c/4bd2c03be7
[2] https://patchwork.ozlabs.org/patch/1189139/
--- drivers/net/ethernet/hisilicon/hns/hnae.c | 1 - drivers/net/ethernet/hisilicon/hns/hnae.h | 3 --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 22 +--------------------- 3 files changed, 1 insertion(+), 25 deletions(-)
drivers/net/ethernet/hisilicon/hns/hnae.c +0 -1
@@ -203,7 +203,6 @@ hnae_init_ring(struct hnae_queue *q, str ring->q = q; ring->flags = flags; -spin_lock_init (&ring->lock); ring->coal_param = q->handle->coal_param;assert (!ring->desc && !ring->desc_cb && !ring->desc_dma_addr);
drivers/net/ethernet/hisilicon/hns/hnae.h +0 -3
@@ -278,9 +278,6 @@ struct hnae_ring {/* statistic */ struct ring_stats stats; -/* ring lock for poll one */ -spinlock_t lock; -dma_addr_t desc_dma_addr;u32 buf_size;/* size for hnae_desc->addr, preset by AE */ u16 desc_num;/* total number of desc */
drivers/net/ethernet/hisilicon/hns/hns_enet.c +1 -21
@@ -947,15 +947,6 @@ static int is_valid_clean_head(struct hnreturn u > c ? (h > c && h <= u) : (h > c || h <= u); } -/* netif_tx_lock will turn down the performance, set only when necessary */ -#ifdef CONFIG_NET_POLL_CONTROLLER -#define NETIF_TX_LOCK (ring) spin_lock(&(ring)->lock) -#define NETIF_TX_UNLOCK (ring) spin_unlock(&(ring)->lock) -#else -#define NETIF_TX_LOCK (ring) -#define NETIF_TX_UNLOCK (ring) -#endif -/* reclaim all desc in one budget * return error or number of desc left */
@@ -969,21 +960,16 @@ static int hns_nic_tx_poll_one(struct hnint head;int bytes, pkts; -NETIF_TX_LOCK (ring); - head =readl_relaxed (ring->io_base +RCB_REG_HEAD );rmb ();/* make sure head is ready before touch any data */ -if (is_ring_empty (ring) || head == ring->next_to_clean) { -NETIF_TX_UNLOCK (ring); +if (is_ring_empty (ring) || head == ring->next_to_clean)return 0 ;/* no data to poll */ - }if (!is_valid_clean_head (ring, head)) {netdev_err (ndev,"wrong head (%d, %d-%d)\n" , head, ring->next_to_use, ring->next_to_clean); ring->stats.io_err_cnt++; -NETIF_TX_UNLOCK (ring);return -EIO ; }
@@ -998,8 +984,6 @@ static int hns_nic_tx_poll_one(struct hn ring->stats.tx_pkts += pkts; ring->stats.tx_bytes += bytes; -NETIF_TX_UNLOCK (ring); - dev_queue =netdev_get_tx_queue (ndev, ring_data->queue_index);netdev_tx_completed_queue (dev_queue, pkts, bytes);
@@ -1059,16 +1043,12 @@ static void hns_nic_tx_clr_all_bufs(struint head;int bytes, pkts; -NETIF_TX_LOCK (ring); - head = ring->next_to_use;/* ntu :soft setted ring position*/ bytes =0 ; pkts =0 ;while (head != ring->next_to_clean)hns_nic_reclaim_one_desc (ring, &bytes, &pkts); -NETIF_TX_UNLOCK (ring); - dev_queue =netdev_get_tx_queue (ndev, ring_data->queue_index);netdev_tx_reset_queue (dev_queue); }
Greg Kroah-Hartman
maintainerPATCH 16/125 ALSA: timer: Fix incorrectly assigned timer instance
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit e7af6307a8a54f0b873960b32b6a644f2d0fbd97 upstream.
The clean up commit 41672c0c24a6 ("ALSA: timer: Simplify error path in snd_timer_open()") unified the error handling code paths with the standard goto, but it introduced a subtle bug: the timer instance is stored in snd_timer_open() incorrectly even if it returns an error. This may eventually lead to UAF, as spotted by fuzzer.
The culprit is the snd_timer_open() code checks the SNDRV_TIMER_IFLG_EXCLUSIVE flag with the common variable timeri. This variable is supposed to be the newly created instance, but we (ab-)used it for a temporary check before the actual creation of a timer instance. After that point, there is another check for the max number of instances, and it bails out if over the threshold. Before the refactoring above, it worked fine because the code returned directly from that point. After the refactoring, however, it jumps to the unified error path that stores the timeri variable in return -- even if it returns an error. Unfortunately this stored value is kept in the caller side (snd_timer_user_tselect()) in tu->timeri. This causes inconsistency later, as if the timer was successfully assigned.
In this patch, we fix it by not re-using timeri variable but a temporary variable for testing the exclusive connection, so timeri remains NULL at that point.
--- sound/core/timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
sound/core/timer.c +3 -3
@@ -298,11 +298,11 @@ int snd_timer_open(struct snd_timer_inst goto unlock; }if (!list_empty (&timer->open_list_head)) { - timeri =list_entry (timer->open_list_head.next, +struct snd_timer_instance *t = +list_entry (timer->open_list_head.next, struct snd_timer_instance, open_list); -if (timeri->flags &SNDRV_TIMER_IFLG_EXCLUSIVE ) { +if (t->flags &SNDRV_TIMER_IFLG_EXCLUSIVE ) { err = -EBUSY ; - timeri =NULL ; goto unlock; } }
Greg Kroah-Hartman
maintainerPATCH 17/125 ALSA: bebob: fix to detect configured source of sampling clock for Focusrite Saffire Pro i/o series
In reply to Greg Kroah-HartmanFrom: Takashi Sakamoto <[email protected]>
commit 706ad6746a66546daf96d4e4a95e46faf6cf689a upstream.
For Focusrite Saffire Pro i/o, the lowest 8 bits of register represents configured source of sampling clock. The next lowest 8 bits represents whether the configured source is actually detected or not just after the register is changed for the source.
Current implementation evaluates whole the register to detect configured source. This results in failure due to the next lowest 8 bits when the source is connected in advance.
This commit fixes the bug.
--- sound/firewire/bebob/bebob_focusrite.c | 3 +++ 1 file changed, 3 insertions(+)
sound/firewire/bebob/bebob_focusrite.c +3 -0
@@ -28,6 +28,8 @@#define SAFFIRE_CLOCK_SOURCE_SPDIF 1/* clock sources as returned from register of Saffire Pro 10 and 26 */ +#define SAFFIREPRO_CLOCK_SOURCE_SELECT_MASK 0x000000ff +#define SAFFIREPRO_CLOCK_SOURCE_DETECT_MASK 0x0000ff00#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0#define SAFFIREPRO_CLOCK_SOURCE_SKIP 1/* never used on hardware */ #define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
@@ -190,6 +192,7 @@ saffirepro_both_clk_src_get(struct snd_b map = saffirepro_clk_maps[1 ];/* In a case that this driver cannot handle the value of register. */ + value &=SAFFIREPRO_CLOCK_SOURCE_SELECT_MASK ;if (value >=SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] <0 ) { err = -EIO ; goto end;
Greg Kroah-Hartman
maintainerPATCH 18/125 ALSA: hda/ca0132 - Fix possible workqueue stall
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 15c2b3cc09a31620914955cb2a89c277c18ee999 upstream.
The unsolicited event handler for the headphone jack on CA0132 codec driver tries to reschedule the another delayed work with cancel_delayed_work_sync(). It's no good idea, unfortunately, especially after we changed the work queue to the standard global one; this may lead to a stall because both works are using the same global queue.
Fix it by dropping the _sync but does call cancel_delayed_work() instead.
--- sound/pci/hda/patch_ca0132.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/hda/patch_ca0132.c +1 -1
@@ -6769,7 +6769,7 @@ static void hp_callback(struct hda_codec/* Delay enabling the HP amp, to let the mic-detection * state machine run. */ -cancel_delayed_work_sync (&spec->unsol_hp_work); +cancel_delayed_work (&spec->unsol_hp_work);schedule_delayed_work (&spec->unsol_hp_work,msecs_to_jiffies (500 )); tbl =snd_hda_jack_tbl_get (codec, cb->nid);if (tbl)
Greg Kroah-Hartman
maintainerPATCH 19/125 mm: memcontrol: fix network errors from failing __GFP_ATOMIC charges
In reply to Greg Kroah-HartmanFrom: Johannes Weiner <[email protected]>
commit 869712fd3de5a90b7ba23ae1272278cddc66b37b upstream.
While upgrading from 4.16 to 5.2, we noticed these allocation errors in the log of the new kernel:
SLUB: Unable to allocate memory on node -1, gfp=0xa20(GFP_ATOMIC)
cache: tw_sock_TCPv6(960:helper-logs), object size: 232, buffer size: 240, default order: 1, min order: 0
node 0: slabs: 5, objs: 170, free: 0
slab_out_of_memory+1
___slab_alloc+969
__slab_alloc+14
kmem_cache_alloc+346
inet_twsk_alloc+60
tcp_time_wait+46
tcp_fin+206
tcp_data_queue+2034
tcp_rcv_state_process+784
tcp_v6_do_rcv+405
__release_sock+118
tcp_close+385
inet_release+46
__sock_release+55
sock_close+17
__fput+170
task_work_run+127
exit_to_usermode_loop+191
do_syscall_64+212
entry_SYSCALL_64_after_hwframe+68accompanied by an increase in machines going completely radio silent under memory pressure.
One thing that changed since 4.16 is e699e2c6a654 ("net, mm: account sock objects to kmemcg"), which made these slab caches subject to cgroup memory accounting and control.
The problem with that is that cgroups, unlike the page allocator, do not maintain dedicated atomic reserves. As a cgroup's usage hovers at its limit, atomic allocations - such as done during network rx - can fail consistently for extended periods of time. The kernel is not able to operate under these conditions.
We don't want to revert the culprit patch, because it indeed tracks a potentially substantial amount of memory used by a cgroup.
We also don't want to implement dedicated atomic reserves for cgroups. There is no point in keeping a fixed margin of unused bytes in the cgroup's memory budget to accomodate a consumer that is impossible to predict - we'd be wasting memory and get into configuration headaches, not unlike what we have going with min_free_kbytes. We do this for physical mem because we have to, but cgroups are an accounting game.
Instead, account these privileged allocations to the cgroup, but let them bypass the configured limit if they have to. This way, we get the benefits of accounting the consumed memory and have it exert pressure on the rest of the cgroup, but like with the page allocator, we shift the burden of reclaimining on behalf of atomic allocations onto the regular allocations that can block.
--- mm/memcontrol.c | 9 +++++++++ 1 file changed, 9 insertions(+)
mm/memcontrol.c +9 -0
@@ -2225,6 +2225,15 @@ retry: }/* +* Memcg doesn't have a dedicated reserve for atomic +* allocations. But like the global atomic pool, we need to +* put the burden of reclaim on regular allocation requests +* and let these go through as privileged allocations. +*/ +if (gfp_mask & __GFP_ATOMIC) + goto force; + +/* * Unlike in global OOM situations, memcg is not in a physical * memory shortage. Allow dying and OOM-killed tasks to * bypass the last charges so that they can exit quickly and
Greg Kroah-Hartman
maintainerPATCH 20/125 mm, meminit: recalculate pcpu batch and high limits after init completes
In reply to Greg Kroah-HartmanFrom: Mel Gorman <[email protected]>
commit 3e8fc0075e24338b1117cdff6a79477427b8dbed upstream.
Deferred memory initialisation updates zone->managed_pages during the initialisation phase but before that finishes, the per-cpu page allocator (pcpu) calculates the number of pages allocated/freed in batches as well as the maximum number of pages allowed on a per-cpu list. As zone->managed_pages is not up to date yet, the pcpu initialisation calculates inappropriately low batch and high values.
This increases zone lock contention quite severely in some cases with the degree of severity depending on how many CPUs share a local zone and the size of the zone. A private report indicated that kernel build times were excessive with extremely high system CPU usage. A perf profile indicated that a large chunk of time was lost on zone->lock contention.
This patch recalculates the pcpu batch and high values after deferred initialisation completes for every populated zone in the system. It was tested on a 2-socket AMD EPYC 2 machine using a kernel compilation workload -- allmodconfig and all available CPUs.
mmtests configuration: config-workload-kernbench-max Configuration was modified to build on a fresh XFS partition.
kernbench
5.4.0-rc3 5.4.0-rc3
vanilla resetpcpu-v2
Amean user-256 13249.50 ( 0.00%) 16401.31 * -23.79%*
Amean syst-256 14760.30 ( 0.00%) 4448.39 * 69.86%*
Amean elsp-256 162.42 ( 0.00%) 119.13 * 26.65%*
Stddev user-256 42.97 ( 0.00%) 19.15 ( 55.43%)
Stddev syst-256 336.87 ( 0.00%) 6.71 ( 98.01%)
Stddev elsp-256 2.46 ( 0.00%) 0.39 ( 84.03%) 5.4.0-rc3 5.4.0-rc3
vanilla resetpcpu-v2
Duration User 39766.24 49221.79
Duration System 44298.10 13361.67Duration Elapsed 519.11 388.87
The patch reduces system CPU usage by 69.86% and total build time by 26.65%. The variance of system CPU usage is also much reduced.
Before, this was the breakdown of batch and high values over all zones was:
256 batch: 1
256 batch: 63
512 batch: 7
256 high: 0
256 high: 378
512 high: 42512 pcpu pagesets had a batch limit of 7 and a high limit of 42. After the patch:
256 batch: 1
768 batch: 63
256 high: 0
768 high: 378--- mm/page_alloc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
mm/page_alloc.c +8 -2
@@ -1743,6 +1743,14 @@ void __init page_alloc_init_late(void)wait_for_completion (&pgdat_init_all_done_comp);/* +* The number of managed pages has changed due to the initialisation +* so the pcpu batch and high limits needs to be updated or the limits +* will be artificially small. +*/ +for_each_populated_zone (zone) +zone_pcp_update (zone); + +/* * We initialized the rest of the deferred pages. Permanently disable * on-demand struct page initialization. */
@@ -8011,7 +8019,6 @@ void free_contig_range(unsigned long pfn }#endif -#ifdef CONFIG_MEMORY_HOTPLUG /* * The zone indicated has a new number of managed_pages; batch sizes and percpu * page high values need to be recalulated.
@@ -8025,7 +8032,6 @@ void __meminit zone_pcp_update(struct zo per_cpu_ptr(zone->pageset, cpu));mutex_unlock (&pcp_batch_high_lock); } -#endif void zone_pcp_reset (struct zone *zone) {
Greg Kroah-Hartman
maintainerPATCH 21/125 mm: thp: handle page cache THP correctly in PageTransCompoundMap
In reply to Greg Kroah-HartmanFrom: Yang Shi <[email protected]>
commit 169226f7e0d275c1879551f37484ef6683579a5c upstream.
We have a usecase to use tmpfs as QEMU memory backend and we would like to take the advantage of THP as well. But, our test shows the EPT is not PMD mapped even though the underlying THP are PMD mapped on host. The number showed by /sys/kernel/debug/kvm/largepage is much less than the number of PMD mapped shmem pages as the below:
7f2778200000-7f2878200000 rw-s 00000000 00:14 262232 /dev/shm/qemu_back_mem.mem.Hz2hSf (deleted)
Size: 4194304 kB
[snip]
AnonHugePages: 0 kB
ShmemPmdMapped: 579584 kB
[snip]
Locked: 0 kB
cat /sys/kernel/debug/kvm/largepages
12
And some benchmarks do worse than with anonymous THPs.
By digging into the code we figured out that commit 127393fbe597 ("mm:
thp: kvm: fix memory corruption in KVM with THP enabled") checks if there is a single PTE mapping on the page for anonymous THP when setting up EPT map. But the _mapcount < 0 check doesn't work for page cache THP since every subpage of page cache THP would get _mapcount inc'ed once it is PMD mapped, so PageTransCompoundMap() always returns false for page cache THP. This would prevent KVM from setting up PMD mapped EPT entry.
So we need handle page cache THP correctly. However, when page cache THP's PMD gets split, kernel just remove the map instead of setting up PTE map like what anonymous THP does. Before KVM calls get_user_pages() the subpages may get PTE mapped even though it is still a THP since the page cache THP may be mapped by other processes at the mean time.
Checking its _mapcount and whether the THP has PTE mapped or not. Although this may report some false negative cases (PTE mapped by other processes), it looks not trivial to make this accurate.
With this fix /sys/kernel/debug/kvm/largepage would show reasonable pages are PMD mapped by EPT as the below:
7fbeaee00000-7fbfaee00000 rw-s 00000000 00:14 275464 /dev/shm/qemu_back_mem.mem.SKUvat (deleted)
Size: 4194304 kB
[snip]
AnonHugePages: 0 kB
ShmemPmdMapped: 557056 kB
[snip]
Locked: 0 kB
cat /sys/kernel/debug/kvm/largepages
271
And the benchmarks are as same as anonymous THPs.
--- include/linux/mm.h | 5 ----- include/linux/mm_types.h | 5 +++++ include/linux/page-flags.h | 20 ++++++++++++++++++-- 3 files changed, 23 insertions(+), 7 deletions(-)
include/linux/mm.h +0 -5
@@ -602,11 +602,6 @@ static inline void *kvcalloc(size_t n, sextern void kvfree (const void *addr); -static inline atomic_t *compound_mapcount_ptr (struct page *page) -{ -return &page[1 ].compound_mapcount; -} -static inline int compound_mapcount (struct page *page) {VM_BUG_ON_PAGE (!PageCompound (page), page);
include/linux/mm_types.h +5 -0
@@ -226,6 +226,11 @@ struct page_frag_cache {typedef unsigned long vm_flags_t ; +static inline atomic_t *compound_mapcount_ptr (struct page *page) +{ +return &page[1 ].compound_mapcount; +} +/* * A region containing a mapping of a non-memory backed file under NOMMU * conditions. These are held in a global tree and are pinned by the VMAs that
include/linux/page-flags.h +18 -2
@@ -577,12 +577,28 @@ static inline int PageTransCompound(stru* * Unlike PageTransCompound, this is safe to be called only while * split_huge_pmd() cannot run from under us, like if protected by the -* MMU notifier, otherwise it may result in page->_mapcount < 0 false +* MMU notifier, otherwise it may result in page->_mapcount check false * positives. +* +* We have to treat page cache THP differently since every subpage of it +* would get _mapcount inc'ed once it is PMD mapped. But, it may be PTE +* mapped in the current process so comparing subpage's _mapcount to +* compound_mapcount to filter out PTE mapped case. */ static inline int PageTransCompoundMap (struct page *page) { -return PageTransCompound (page) &&atomic_read (&page->_mapcount) <0 ; +struct page *head; + +if (!PageTransCompound (page)) +return 0 ; + +if (PageAnon (page)) +return atomic_read (&page->_mapcount) <0 ; + + head =compound_head (page); +/* File THP is PMD mapped and not PTE mapped */ +return atomic_read (&page->_mapcount) == +atomic_read (compound_mapcount_ptr (head)); }/*
Greg Kroah-Hartman
maintainerPATCH 22/125 mm, vmstat: hide /proc/pagetypeinfo from normal users
In reply to Greg Kroah-HartmanFrom: Michal Hocko <[email protected]>
commit abaed0112c1db08be15a784a2c5c8a8b3063cdd3 upstream.
/proc/pagetypeinfo is a debugging tool to examine internal page allocator state wrt to fragmentation. It is not very useful for any other use so normal users really do not need to read this file.
Waiman Long has noticed that reading this file can have negative side effects because zone->lock is necessary for gathering data and that a) interferes with the page allocator and its users and b) can lead to hard lockups on large machines which have very long free_list.
Reduce both issues by simply not exporting the file to regular users.
--- mm/vmstat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmstat.c +1 -1
@@ -1972,7 +1972,7 @@ void __init init_mm_internals(void)#endif #ifdef CONFIG_PROC_FS proc_create_seq ("buddyinfo" ,0444 ,NULL , &fragmentation_op); -proc_create_seq ("pagetypeinfo" ,0444 ,NULL , &pagetypeinfo_op); +proc_create_seq ("pagetypeinfo" ,0400 ,NULL , &pagetypeinfo_op);proc_create_seq ("vmstat" ,0444 ,NULL , &vmstat_op);proc_create_seq ("zoneinfo" ,0444 ,NULL , &zoneinfo_op);#endif
Greg Kroah-Hartman
maintainerPATCH 23/125 dump_stack: avoid the livelock of the dump_lock
In reply to Greg Kroah-HartmanFrom: Kevin Hao <[email protected]>
commit 5cbf2fff3bba8d3c6a4d47c1754de1cf57e2b01f upstream.
In the current code, we use the atomic_cmpxchg() to serialize the output of the dump_stack(), but this implementation suffers the thundering herd problem. We have observed such kind of livelock on a Marvell cn96xx board(24 cpus) when heavily using the dump_stack() in a kprobe handler. Actually we can let the competitors to wait for the releasing of the lock before jumping to atomic_cmpxchg(). This will definitely mitigate the thundering herd problem. Thanks Linus for the suggestion.
--- lib/dump_stack.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
lib/dump_stack.c +6 -1
@@ -106,7 +106,12 @@ retry: was_locked =1 ; }else {local_irq_restore (flags); -cpu_relax (); +/* +* Wait for the lock to release before jumping to +* atomic_cmpxchg() in order to mitigate the thundering herd +* problem. +*/ +do {cpu_relax (); }while (atomic_read (&dump_lock) !=-1 ); goto retry; }
Greg Kroah-Hartman
maintainerPATCH 24/125 tools: gpio: Use !building_out_of_srctree to determine srctree
In reply to Greg Kroah-HartmanFrom: Shuah Khan <[email protected]>
commit 4a6a6f5c4aeedb72db871d60bfcca89835f317aa upstream.
make TARGETS=gpio kselftest fails with:
Makefile:23: tools/build/Makefile.include: No such file or directory
When the gpio tool make is invoked from tools Makefile, srctree is cleared and the current logic check for srctree equals to empty string to determine srctree location from CURDIR.
When the build in invoked from selftests/gpio Makefile, the srctree is set to "." and the same logic used for srctree equals to empty is needed to determine srctree.
Check building_out_of_srctree undefined as the condition for both cases to fix "make TARGETS=gpio kselftest" build failure.
--- tools/gpio/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
tools/gpio/Makefile +5 -1
@@ -3,7 +3,11 @@ include ../scripts/Makefile.include bindir ?= /usr/bin -ifeq ($(srctree),) +# This will work when gpio is built in tools env. where srctree +# isn't set and when invoked from selftests build, where srctree +# is set to ".". building_out_of_srctree is undefined for in srctree +# builds +ifndef building_out_of_srctree srctree := $(patsubst %/,%,$(dir $(CURDIR))) srctree := $(patsubst %/,%,$(dir $(srctree))) endif
Greg Kroah-Hartman
maintainerPATCH 25/125 perf tools: Fix time sorting
In reply to Greg Kroah-HartmanFrom: Jiri Olsa <[email protected]>
commit 722ddfde366fd46205456a9c5ff9b3359dc9a75e upstream.
The final sort might get confused when the comparison is done over bigger numbers than int like for -s time.
Check the following report for longer workloads:
$ perf report -s time -F time,overhead --stdio
Fix hist_entry__sort() to properly return int64_t and not possible cut int.
--- tools/perf/util/hist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/hist.c +1 -1
@@ -1508,7 +1508,7 @@ int hists__collapse_resort(struct histsreturn 0 ; } -static int hist_entry__sort (struct hist_entry *a,struct hist_entry *b) +static int64_t hist_entry__sort (struct hist_entry *a,struct hist_entry *b) {struct hists *hists = a->hists;struct perf_hpp_fmt *fmt;
Greg Kroah-Hartman
maintainerPATCH 26/125 drm/radeon: fix si_enable_smc_cac() failed issue
In reply to Greg Kroah-HartmanFrom: Alex Deucher <[email protected]>
commit 2c409ba81be25516afe05ae27a4a15da01740b01 upstream.
Need to set the dte flag on this asic.
Port the fix from amdgpu:5cb818b861be114 ("drm/amd/amdgpu: fix si_enable_smc_cac() failed issue")
--- drivers/gpu/drm/radeon/si_dpm.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/radeon/si_dpm.c +1 -0
@@ -1956,6 +1956,7 @@ static void si_initialize_powertune_defacase 0x682C : si_pi->cac_weights = cac_weights_cape_verde_pro; si_pi->dte_data = dte_data_sun_xt; + update_dte_from_pl2 = true;break ;case 0x6825 :case 0x6827 :
Greg Kroah-Hartman
maintainerPATCH 27/125 HID: wacom: generic: Treat serial number and related fields as unsigned
In reply to Greg Kroah-HartmanFrom: Jason Gerecke <[email protected]>
commit ff479731c3859609530416a18ddb3db5db019b66 upstream.
The HID descriptors for most Wacom devices oddly declare the serial number and other related fields as signed integers. When these numbers are ingested by the HID subsystem, they are automatically sign-extended into 32-bit integers. We treat the fields as unsigned elsewhere in the kernel and userspace, however, so this sign-extension causes problems. In particular, the sign-extended tool ID sent to userspace as ABS_MISC does not properly match unsigned IDs used by xf86-input-wacom and libwacom.
We introduce a function 'wacom_s32tou' that can undo the automatic sign extension performed by 'hid_snto32'. We call this function when processing the serial number and related fields to ensure that we are dealing with and reporting the unsigned form. We opt to use this method rather than adding a descriptor fixup in 'wacom_hid_usage_quirk' since it should be more robust in the face of future devices.
Ref: https://github.com/linuxwacom/input-wacom/issues/134
--- drivers/hid/wacom.h | 15 +++++++++++++++ drivers/hid/wacom_wac.c | 10 ++++++---- 2 files changed, 21 insertions(+), 4 deletions(-)
drivers/hid/wacom.h +15 -0
@@ -205,6 +205,21 @@ static inline void wacom_schedule_work(s } } +/* +* Convert a signed 32-bit integer to an unsigned n-bit integer. Undoes +* the normally-helpful work of 'hid_snto32' for fields that use signed +* ranges for questionable reasons. +*/ +static inline __u32 wacom_s32tou (s32 value,__u8 n) +{ +switch (n) { +case 8 :return ((__u8 )value); +case 16 :return ((__u16 )value); +case 32 :return ((__u32 )value); + } +return value & (1 << (n -1 )) ? value & (~(~0U << n)) : value; +} +extern const struct hid_device_id wacom_ids[];void wacom_wac_irq (struct wacom_wac *wacom_wac,size_t len);
drivers/hid/wacom_wac.c +6 -4
@@ -2271,7 +2271,7 @@ static void wacom_wac_pen_event(struct hcase HID_DG_TOOLSERIALNUMBER :if (value) { wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] & ~0xFFFFFFFFULL ); - wacom_wac->serial[0 ] |= (__u32 )value; + wacom_wac->serial[0 ] |=wacom_s32tou (value, field->report_size); }return ;case HID_DG_TWIST :
@@ -2287,15 +2287,17 @@ static void wacom_wac_pen_event(struct hreturn ;case WACOM_HID_WD_SERIALHI :if (value) { +__u32 raw_value =wacom_s32tou (value, field->report_size); + wacom_wac->serial[0 ] = (wacom_wac->serial[0 ] &0xFFFFFFFF ); - wacom_wac->serial[0 ] |= ((__u64 )value) <<32 ; + wacom_wac->serial[0 ] |= ((__u64 )raw_value) <<32 ;/* * Non-USI EMR devices may contain additional tool type * information here. See WACOM_HID_WD_TOOLTYPE case for * more details. */ if (value >>20 ==1 ) { - wacom_wac->id[0 ] |= value &0xFFFFF ; + wacom_wac->id[0 ] |= raw_value &0xFFFFF ; } }return ;
@@ -2307,7 +2309,7 @@ static void wacom_wac_pen_event(struct h* bitwise OR so the complete value can be built * up over time :( */ - wacom_wac->id[0 ] |= value; + wacom_wac->id[0 ] |=wacom_s32tou (value, field->report_size);return ;case WACOM_HID_WD_OFFSETLEFT :if (features->offset_left && value != features->offset_left)
Re: [PATCH 4.19 027/125] HID: wacom: generic: Treat serial number and related fields as unsigned
Hi!
Quoted 28 lines
From: Jason Gerecke <[email protected]>
commit
ff479731c3859609530416a18ddb3db5db019b66upstream.The HID descriptors for most Wacom devices oddly declare the serial number and other related fields as signed integers. When these numbers are ingested by the HID subsystem, they are automatically sign-extended into 32-bit integers. We treat the fields as unsigned elsewhere in the kernel and userspace, however, so this sign-extension causes problems. In particular, the sign-extended tool ID sent to userspace as
ABS_MISCdoes not properly match unsigned IDs used by xf86-input-wacom and libwacom.We introduce a function '
wacom_s32tou' that can undo the automatic sign extension performed by 'hid_snto32'. We call this function when processing the serial number and related fields to ensure that we are dealing with and reporting the unsigned form. We opt to use this method rather than adding a descriptor fixup in 'wacom_hid_usage_quirk' since it should be more robust in the face of future devices.+++
b/drivers/hid/wacom.hdrivers/hid/wacom.h +4
-0@@ -205,6 +205,21 @@ static inline void wacom_schedule_work(s } } +/* +* Convert a signed 32-bit integer to an unsigned n-bit integer. Undoes +* the normally-helpful work of 'hid_snto32' for fields that use signed +* ranges for questionable reasons.
drivers/hid/wacom.h static inline void wacom_schedule_work(s · line 221
Quoted 10 lines
drivers/hid/wacom.h +10
-0+*/ +static inline __u32 wacom_s32tou (s32 value,__u8 n) +{ +switch (n) { +case 8 :return ((__u8 )value); +case 16 :return ((__u16 )value); +case 32 :return ((__u32 )value); + } +return value & (1 << (n -1 )) ? value & (~(~0U << n)) : value; +}
Can we do something like:
BUG_ON(n>32);
if (n==32) return ((__u32)value);
return value & ((1 << n) - 1);instead?
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Re: [PATCH 4.19 027/125] HID: wacom: generic: Treat serial number and related fields as unsigned
Quoted 41 lines · Pavel Machek
Quoted 28 lines
From: Jason Gerecke <[email protected]>
commit
ff479731c3859609530416a18ddb3db5db019b66upstream.The HID descriptors for most Wacom devices oddly declare the serial number and other related fields as signed integers. When these numbers are ingested by the HID subsystem, they are automatically sign-extended into 32-bit integers. We treat the fields as unsigned elsewhere in the kernel and userspace, however, so this sign-extension causes problems. In particular, the sign-extended tool ID sent to userspace as
ABS_MISCdoes not properly match unsigned IDs used by xf86-input-wacom and libwacom.We introduce a function '
wacom_s32tou' that can undo the automatic sign extension performed by 'hid_snto32'. We call this function when processing the serial number and related fields to ensure that we are dealing with and reporting the unsigned form. We opt to use this method rather than adding a descriptor fixup in 'wacom_hid_usage_quirk' since it should be more robust in the face of future devices.+++
b/drivers/hid/wacom.hdrivers/hid/wacom.h +4
-0@@ -205,6 +205,21 @@ static inline void wacom_schedule_work(s } } +/* +* Convert a signed 32-bit integer to an unsigned n-bit integer. Undoes +* the normally-helpful work of 'hid_snto32' for fields that use signed +* ranges for questionable reasons. drivers/hid/wacom.h static inline void wacom_schedule_work(s · line 221
Quoted 10 lines
drivers/hid/wacom.h +10
-0+*/ +static inline __u32 wacom_s32tou (s32 value,__u8 n) +{ +switch (n) { +case 8 :return ((__u8 )value); +case 16 :return ((__u16 )value); +case 32 :return ((__u32 )value); + } +return value & (1 << (n -1 )) ? value & (~(~0U << n)) : value; +}Can we do something like:
Quoted 1 line
BUG_ON(n>32);
Please no BUG_ON()s in bitop helpers.
Thanks,
Signature · 2 lines
Jiri Kosina SUSE Labs
Re: [PATCH 4.19 027/125] HID: wacom: generic: Treat serial number and related fields as unsigned
Quoted 7 lines
From: Jiri Kosina <[email protected]>
Sent: Wednesday, November 13, 2019 3:02 AM
To: Pavel Machek <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>; [email protected] <[email protected]>; [email protected] <[email protected]>; Gerecke, Jason <[email protected]>; Skomra, Aaron <[email protected]>
Subject: Re: [PATCH 4.19 027/125] HID: wacom: generic: Treat serial number and related fields as unsigned
Quoted 45 lines
[EXTERNAL]
Quoted 41 lines · Pavel Machek
Quoted 28 lines
From: Jason Gerecke <[email protected]>
commit
ff479731c3859609530416a18ddb3db5db019b66upstream.The HID descriptors for most Wacom devices oddly declare the serial number and other related fields as signed integers. When these numbers are ingested by the HID subsystem, they are automatically sign-extended into 32-bit integers. We treat the fields as unsigned elsewhere in the kernel and userspace, however, so this sign-extension causes problems. In particular, the sign-extended tool ID sent to userspace as
ABS_MISCdoes not properly match unsigned IDs used by xf86-input-wacom and libwacom.We introduce a function '
wacom_s32tou' that can undo the automatic sign extension performed by 'hid_snto32'. We call this function when processing the serial number and related fields to ensure that we are dealing with and reporting the unsigned form. We opt to use this method rather than adding a descriptor fixup in 'wacom_hid_usage_quirk' since it should be more robust in the face of future devices.+++
b/drivers/hid/wacom.hdrivers/hid/wacom.h +4
-0@@ -205,6 +205,21 @@ static inline void wacom_schedule_work(s } } +/* +* Convert a signed 32-bit integer to an unsigned n-bit integer. Undoes +* the normally-helpful work of 'hid_snto32' for fields that use signed +* ranges for questionable reasons. drivers/hid/wacom.h static inline void wacom_schedule_work(s · line 221
Quoted 10 lines
drivers/hid/wacom.h +10
-0+*/ +static inline __u32 wacom_s32tou (s32 value,__u8 n) +{ +switch (n) { +case 8 :return ((__u8 )value); +case 16 :return ((__u16 )value); +case 32 :return ((__u32 )value); + } +return value & (1 << (n -1 )) ? value & (~(~0U << n)) : value; +}Can we do something like:
The implementation here was copied from 'hid_snto32' (except, of course, to make it convert signed to unsigned). That function provides justification for how it is written, but if changes make sense then we should probably do them to both this and 'hid_snto32'.
Jason
Quoted 10 lines
Quoted 1 line
BUG_ON(n>32);Please no BUG_ON()s in bitop helpers.
Thanks,
--
Jiri Kosina
SUSE Labs
Greg Kroah-Hartman
maintainerPATCH 28/125 soundwire: depend on ACPI
In reply to Greg Kroah-HartmanFrom: Michal Suchanek <[email protected]>
commit 52eb063d153ac310058fbaa91577a72c0e7a7169 upstream.
The device cannot be probed on !ACPI and gives this warning:
drivers/soundwire/slave.c:16:12: warning: ‘sdw_slave_add’ defined but not used [-Wunused-function]
static int sdw_slave_add(struct sdw_bus *bus,
^~~~~~~~~~~~~
--- drivers/soundwire/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/soundwire/Kconfig +1 -0
@@ -4,6 +4,7 @@ menuconfig SOUNDWIRE tristate "SoundWire support" + depends on ACPI help SoundWire is a 2-Pin interface with data and clock line ratified by the MIPI Alliance. SoundWire is used for transporting data
Greg Kroah-Hartman
maintainerPATCH 29/125 soundwire: bus: set initial value to port_status
In reply to Greg Kroah-HartmanFrom: Bard Liao <[email protected]>
commit f1fac63af678b2fc1044ca71fedf1f2ae8bf7c3b upstream.
port_status[port_num] are assigned for each port_num in some if conditions. So some of the port_status may not be initialized.
--- drivers/soundwire/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/soundwire/bus.c +1 -1
@@ -805,7 +805,7 @@ static int sdw_handle_port_interrupt(strstatic int sdw_handle_slave_alerts (struct sdw_slave *slave) {struct sdw_slave_intr_status slave_intr; -u8 clear =0 , bit, port_status[15 ]; +u8 clear =0 , bit, port_status[15 ] = {0 };int port_num, stat, ret, count =0 ;unsigned long port;bool slave_notify = false;
Greg Kroah-Hartman
maintainerPATCH 30/125 arm64: Do not mask out PTE_RDONLY in pte_same()
In reply to Greg Kroah-HartmanFrom: Catalin Marinas <[email protected]>
commit 6767df245f4736d0cf0c6fb7cf9cf94b27414245 upstream.
Following commit 73e86cb03cf2 ("arm64: Move PTE_RDONLY bit handling out of set_pte_at()"), the PTE_RDONLY bit is no longer managed by set_pte_at() but built into the PAGE_* attribute definitions. Consequently, pte_same() must include this bit when checking two PTEs for equality.
Remove the arm64-specific pte_same() function, practically reverting commit 747a70e60b72 ("arm64: Fix copy-on-write referencing in HugeTLB")
--- arch/arm64/include/asm/pgtable.h | 17 ----------------- 1 file changed, 17 deletions(-)
arch/arm64/include/asm/pgtable.h +0 -17
@@ -274,23 +274,6 @@ static inline void set_pte_at(struct mm_set_pte (ptep, pte); } -#define __HAVE_ARCH_PTE_SAME -static inline int pte_same (pte_t pte_a,pte_t pte_b) -{ -pteval_t lhs, rhs; - - lhs =pte_val (pte_a); - rhs =pte_val (pte_b); - -if (pte_present (pte_a)) - lhs &= ~PTE_RDONLY ; - -if (pte_present (pte_b)) - rhs &= ~PTE_RDONLY ; - -return (lhs == rhs); -} -/* * Huge pte definitions. */
Greg Kroah-Hartman
maintainerPATCH 31/125 ceph: fix use-after-free in __ceph_remove_cap()
In reply to Greg Kroah-HartmanFrom: Luis Henriques <[email protected]>
commit ea60ed6fcf29eebc78f2ce91491e6309ee005a01 upstream.
KASAN reports a use-after-free when running xfstest generic/531, with the following trace:
[ 293.903362] kasan_report+0xe/0x20 [ 293.903365] rb_erase+0x1f/0x790 [ 293.903370] __ceph_remove_cap+0x201/0x370 [ 293.903375] __ceph_remove_caps+0x4b/0x70 [ 293.903380] ceph_evict_inode+0x4e/0x360 [ 293.903386] evict+0x169/0x290 [ 293.903390] __dentry_kill+0x16f/0x250 [ 293.903394] dput+0x1c6/0x440 [ 293.903398] __fput+0x184/0x330 [ 293.903404] task_work_run+0xb9/0xe0 [ 293.903410] exit_to_usermode_loop+0xd3/0xe0 [ 293.903413] do_syscall_64+0x1a0/0x1c0 [ 293.903417] entry_SYSCALL_64_after_hwframe+0x44/0xa9
This happens because __ceph_remove_cap() may queue a cap release (__ceph_queue_cap_release) which can be scheduled before that cap is removed from the inode list with
rb_erase(&cap->ci_node, &ci->i_caps);
And, when this finally happens, the use-after-free will occur.
This can be fixed by removing the cap from the inode list before being removed from the session list, and thus eliminating the risk of an UAF.
--- fs/ceph/caps.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
fs/ceph/caps.c +5 -5
@@ -1053,6 +1053,11 @@ void __ceph_remove_cap(struct ceph_cap *dout ("__ceph_remove_cap %p from %p\n" , cap, &ci->vfs_inode); +/* remove from inode's cap rbtree, and clear auth cap */ +rb_erase (&cap->ci_node, &ci->i_caps); +if (ci->i_auth_cap == cap) + ci->i_auth_cap =NULL ; +/* remove from session list */ spin_lock (&session->s_cap_lock);if (session->s_cap_iterator == cap) {
@@ -1088,11 +1093,6 @@ void __ceph_remove_cap(struct ceph_cap *spin_unlock (&session->s_cap_lock); -/* remove from inode list */ -rb_erase (&cap->ci_node, &ci->i_caps); -if (ci->i_auth_cap == cap) - ci->i_auth_cap =NULL ; -if (removed)ceph_put_cap (mdsc, cap);
Greg Kroah-Hartman
maintainerPATCH 32/125 ceph: add missing check in d_revalidate snapdir handling
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit 1f08529c84cfecaf1261ed9b7e17fab18541c58f upstream.
We should not play with dcache without parent locked...
--- fs/ceph/inode.c | 1 + 1 file changed, 1 insertion(+)
fs/ceph/inode.c +1 -0
@@ -1399,6 +1399,7 @@ retry_lookup:dout (" final dn %p\n" , dn); }else if ((req->r_op ==CEPH_MDS_OP_LOOKUPSNAP || req->r_op ==CEPH_MDS_OP_MKSNAP ) && +test_bit (CEPH_MDS_R_PARENT_LOCKED , &req->r_req_flags) && !test_bit (CEPH_MDS_R_ABORTED , &req->r_req_flags)) {struct dentry *dn = req->r_dentry;struct inode *dir = req->r_parent;
Greg Kroah-Hartman
maintainerPATCH 33/125 iio: adc: stm32-adc: fix stopping dma
In reply to Greg Kroah-HartmanFrom: Fabrice Gasnier <[email protected]>
commit e6afcf6c598d6f3a0c9c408bfeddb3f5730608b0 upstream.
There maybe a race when using dmaengine_terminate_all(). The predisable routine may call iio_triggered_buffer_predisable() prior to a pending DMA callback.
Adopt dmaengine_terminate_sync() to ensure there's no pending DMA request before calling iio_triggered_buffer_predisable().
--- drivers/iio/adc/stm32-adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iio/adc/stm32-adc.c +2 -2
@@ -1340,7 +1340,7 @@ static int stm32_adc_dma_start(struct ii cookie =dmaengine_submit (desc); ret =dma_submit_error (cookie);if (ret) { -dmaengine_terminate_all (adc->dma_chan); +dmaengine_terminate_sync (adc->dma_chan);return ret; }
@@ -1413,7 +1413,7 @@ static int stm32_adc_buffer_predisable(sdev_err (&indio_dev->dev,"predisable failed\n" );if (adc->dma_chan) -dmaengine_terminate_all (adc->dma_chan); +dmaengine_terminate_sync (adc->dma_chan);if (stm32_adc_set_trig (indio_dev,NULL ))dev_err (&indio_dev->dev,"Can't clear trigger\n" );
Greg Kroah-Hartman
maintainerPATCH 34/125 iio: imu: adis16480: make sure provided frequency is positive
In reply to Greg Kroah-HartmanFrom: Alexandru Ardelean <[email protected]>
commit 24e1eb5c0d78cfb9750b690bbe997d4d59170258 upstream.
It could happen that either val or val2 [provided from userspace] is negative. In that case the computed frequency could get a weird value.
Fix this by checking that neither of the 2 variables is negative, and check that the computed result is not-zero.
--- drivers/iio/imu/adis16480.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/iio/imu/adis16480.c +4 -1
@@ -270,8 +270,11 @@ static int adis16480_set_freq(struct iiostruct adis16480 *st =iio_priv (indio_dev);unsigned int t; +if (val <0 || val2 <0 ) +return -EINVAL ; + t = val *1000 + val2 /1000 ; -if (t <=0 ) +if (t ==0 )return -EINVAL ; t =2460000 / t;
Greg Kroah-Hartman
maintainerPATCH 35/125 iio: srf04: fix wrong limitation in distance measuring
In reply to Greg Kroah-HartmanFrom: Andreas Klinger <[email protected]>
commit 431f7667bd6889a274913162dfd19cce9d84848e upstream.
The measured time value in the driver is limited to the maximum distance which can be read by the sensor. This limitation was wrong and is fixed by this patch.
It also takes into account that we are supporting a variety of sensors today and that the recently added sensors have a higher maximum distance range.
Changes in v2:
- Added a Tested-by
--- drivers/iio/proximity/srf04.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-)
drivers/iio/proximity/srf04.c +15 -14
@@ -105,7 +105,7 @@ static int srf04_read(struct srf04_dataudelay (10 );gpiod_set_value (data->gpiod_trig,0 ); -/* it cannot take more than 20 ms */ +/* it should not take more than 20 ms until echo is rising */ ret =wait_for_completion_killable_timeout (&data->rising,HZ /50 );if (ret <0 ) {mutex_unlock (&data->lock);
@@ -115,7 +115,8 @@ static int srf04_read(struct srf04_datareturn -ETIMEDOUT ; } - ret =wait_for_completion_killable_timeout (&data->falling,HZ /50 ); +/* it cannot take more than 50 ms until echo is falling */ + ret =wait_for_completion_killable_timeout (&data->falling,HZ /20 );if (ret <0 ) {mutex_unlock (&data->lock);return ret;
@@ -130,19 +131,19 @@ static int srf04_read(struct srf04_data dt_ns =ktime_to_ns (ktime_dt);/* -* measuring more than 3 meters is beyond the capabilities of -* the sensor +* measuring more than 6,45 meters is beyond the capabilities of +* the supported sensors * ==> filter out invalid results for not measuring echos of * another us sensor * * formula: -* distance 3 m -* time = ---------- = --------- = 9404389 ns -* speed 319 m/s +* distance 6,45 * 2 m +* time = ---------- = ------------ = 40438871 ns +* speed 319 m/s * * using a minimum speed at -20 °C of 319 m/s */ -if (dt_ns >9404389 ) +if (dt_ns >40438871 )return -EIO ; time_ns = dt_ns;
@@ -154,20 +155,20 @@ static int srf04_read(struct srf04_data* with Temp in °C * and speed in m/s * -* use 343 m/s as ultrasonic speed at 20 °C here in absence of the +* use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the * temperature * * therefore: -* time 343 -* distance = ------ * ----- -* 10^6 2 +* time 343,5 time * 106 +* distance = ------ * ------- = ------------ +* 10^6 2 617176 * with time in ns * and distance in mm (one way) * -* because we limit to 3 meters the multiplication with 343 just +* because we limit to 6,45 meters the multiplication with 106 just * fits into 32 bit */ - distance_mm = time_ns *343 /2000000 ; + distance_mm = time_ns *106 /617176 ;return distance_mm; }
Greg Kroah-Hartman
maintainerPATCH 36/125 ARM: sunxi: Fix CPU powerdown on A83T
In reply to Greg Kroah-HartmanFrom: Ondrej Jirman <[email protected]>
commit e690053e97e7a9c968df9a97cef9089dfa8e6a44 upstream.
PRCM_PWROFF_GATING_REG has CPU0 at bit 4 on A83T. So without this patch, instead of gating the CPU0, the whole cluster was power gated, when shutting down first CPU in the cluster.
--- arch/arm/mach-sunxi/mc_smp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/arm/mach-sunxi/mc_smp.c +5 -1
@@ -478,14 +478,18 @@ static void sunxi_mc_smp_cpu_die(unsignestatic int sunxi_cpu_powerdown (unsigned int cpu,unsigned int cluster) {u32 reg; +int gating_bit = cpu;pr_debug ("%s: cluster %u cpu %u\n" , __func__, cluster, cpu);if (cpu >=SUNXI_CPUS_PER_CLUSTER || cluster >=SUNXI_NR_CLUSTERS )return -EINVAL ; +if (is_a83t && cpu ==0 ) + gating_bit =4 ; +/* gate processor power */ reg =readl (prcm_base +PRCM_PWROFF_GATING_REG (cluster)); - reg |=PRCM_PWROFF_GATING_REG_CORE (cpu); + reg |=PRCM_PWROFF_GATING_REG_CORE (gating_bit);writel (reg, prcm_base +PRCM_PWROFF_GATING_REG (cluster));udelay (20 );
Greg Kroah-Hartman
maintainerPATCH 37/125 netfilter: nf_tables: Align nft_expr private data to 64-bit
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit 250367c59e6ba0d79d702a059712d66edacd4a1a upstream.
Invoking the following commands on a 32-bit architecture with strict alignment requirements (such as an ARMv7-based Raspberry Pi) results in an alignment exception:
# nft add table ip test-ip4
# nft add chain ip test-ip4 output { type filter hook output priority 0; }
# nft add rule ip test-ip4 output quota 1025 bytesAlignment trap: not handling instruction e1b26f9f at [<7f4473f8>] Unhandled fault: alignment exception (0x001) at 0xb832e824
Internal error: : 1 [#1] PREEMPT SMP ARM Hardware name: BCM2835
[<7f4473fc>] (nft_quota_do_init [nft_quota])
[<7f447448>] (nft_quota_init [nft_quota])
[<7f4260d0>] (nf_tables_newrule [nf_tables])
[<7f4168dc>] (nfnetlink_rcv_batch [nfnetlink])
[<7f416bd0>] (nfnetlink_rcv [nfnetlink])
[<8078b334>] (netlink_unicast)
[<8078b664>] (netlink_sendmsg)
[<8071b47c>] (sock_sendmsg)
[<8071bd18>] (___sys_sendmsg)
[<8071ce3c>] (__sys_sendmsg)
[<8071ce94>] (sys_sendmsg)
The reason is that nft_quota_do_init() calls atomic64_set() on an atomic64_t which is only aligned to 32-bit, not 64-bit, because it succeeds struct nft_expr in memory which only contains a 32-bit pointer. Fix by aligning the nft_expr private data to 64-bit.
--- include/net/netfilter/nf_tables.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
include/net/netfilter/nf_tables.h +2 -1
@@ -793,7 +793,8 @@ struct nft_expr_ops {*/ struct nft_expr {const struct nft_expr_ops *ops; -unsigned char data[]; +unsigned char data[] + __attribute__((aligned (__alignof__(u64 )))); };static inline void *nft_expr_priv (const struct nft_expr *expr)
Greg Kroah-Hartman
maintainerPATCH 38/125 netfilter: ipset: Fix an error code in ip_set_sockfn_get()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit 30b7244d79651460ff114ba8f7987ed94c86b99a upstream.
The copy_to_user() function returns the number of bytes remaining to be copied. In this code, that positive return is checked at the end of the function and we return zero/success. What we should do instead is return -EFAULT.
--- net/netfilter/ipset/ip_set_core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/netfilter/ipset/ip_set_core.c +5 -3
@@ -1977,8 +1977,9 @@ ip_set_sockfn_get(struct sock *sk, int o } req_version->version =IPSET_PROTOCOL ; - ret =copy_to_user (user, req_version, -sizeof (struct ip_set_req_version )); +if (copy_to_user (user, req_version, +sizeof (struct ip_set_req_version ))) + ret = -EFAULT ; goto done; }case IP_SET_OP_GET_BYNAME : {
@@ -2035,7 +2036,8 @@ ip_set_sockfn_get(struct sock *sk, int o }/* end of switch(op) */ copy: - ret =copy_to_user (user, data, copylen); +if (copy_to_user (user, data, copylen)) + ret = -EFAULT ; done:vfree (data);
Greg Kroah-Hartman
maintainerPATCH 39/125 intel_th: pci: Add Comet Lake PCH support
In reply to Greg Kroah-HartmanFrom: Alexander Shishkin <[email protected]>
commit 3adbb5718dd5264666ddbc2b9b43799d292e9cb6 upstream.
This adds support for Intel TH on Comet Lake PCH.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -176,6 +176,11 @@ static const struct pci_device_id intel_ .driver_data = (kernel_ulong_t)&intel_th_2x, }, { +/* Comet Lake PCH */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x06a6), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, + {/* Ice Lake NNPI */ PCI_DEVICE (PCI_VENDOR_ID_INTEL ,0x45c5 ), .driver_data = (kernel_ulong_t)&intel_th_2x,
Greg Kroah-Hartman
maintainerPATCH 40/125 intel_th: pci: Add Jasper Lake PCH support
In reply to Greg Kroah-HartmanFrom: Alexander Shishkin <[email protected]>
commit 9d55499d8da49e9261e95a490f3fda41d955f505 upstream.
This adds support for Intel TH on Jasper Lake PCH.
--- drivers/hwtracing/intel_th/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/hwtracing/intel_th/pci.c +5 -0
@@ -190,6 +190,11 @@ static const struct pci_device_id intel_ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6), .driver_data = (kernel_ulong_t)&intel_th_2x, }, + { +/* Jasper Lake PCH */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, { 0 }, };
Greg Kroah-Hartman
maintainerPATCH 41/125 x86/apic/32: Avoid bogus LDR warnings
In reply to Greg Kroah-HartmanFrom: Jan Beulich <[email protected]>
commit fe6f85ca121e9c74e7490fe66b0c5aae38e332c3 upstream.
The removal of the LDR initialization in the bigsmp_32 APIC code unearthed a problem in setup_local_APIC().
The code checks unconditionally for a mismatch of the logical APIC id by comparing the early APIC id which was initialized in get_smp_config() with the actual LDR value in the APIC.
Due to the removal of the bogus LDR initialization the check now can trigger on bigsmp_32 APIC systems emitting a warning for every booting CPU. This is of course a false positive because the APIC is not using logical destination mode.
Restrict the check and the possibly resulting fixup to systems which are actually using the APIC in logical destination mode.
[ tglx: Massaged changelog and added Cc stable ]
--- arch/x86/kernel/apic/apic.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
arch/x86/kernel/apic/apic.c +15 -13
@@ -1528,9 +1528,6 @@ static void setup_local_APIC(void) {int cpu =smp_processor_id ();unsigned int value; -#ifdef CONFIG_X86_32 -int logical_apicid, ldr_apicid; -#endif if (disable_apic) {
@@ -1571,16 +1568,21 @@ static void setup_local_APIC(void) apic->init_apic_ldr ();#ifdef CONFIG_X86_32 -/* -* APIC LDR is initialized. If logical_apicid mapping was -* initialized during get_smp_config(), make sure it matches the -* actual value. -*/ - logical_apicid =early_per_cpu (x86_cpu_to_logical_apicid, cpu); - ldr_apicid =GET_APIC_LOGICAL_ID (apic_read (APIC_LDR )); -WARN_ON (logical_apicid !=BAD_APICID && logical_apicid != ldr_apicid); -/* always use the value from LDR */ -early_per_cpu (x86_cpu_to_logical_apicid, cpu) = ldr_apicid; +if (apic->dest_logical) { +int logical_apicid, ldr_apicid; + +/* +* APIC LDR is initialized. If logical_apicid mapping was +* initialized during get_smp_config(), make sure it matches +* the actual value. +*/ + logical_apicid =early_per_cpu (x86_cpu_to_logical_apicid, cpu); + ldr_apicid =GET_APIC_LOGICAL_ID (apic_read (APIC_LDR )); +if (logical_apicid !=BAD_APICID ) +WARN_ON (logical_apicid != ldr_apicid); +/* Always use the value from LDR. */ +early_per_cpu (x86_cpu_to_logical_apicid, cpu) = ldr_apicid; + }#endif /*
Greg Kroah-Hartman
maintainerPATCH 42/125 SMB3: Fix persistent handles reconnect
In reply to Greg Kroah-HartmanFrom: Pavel Shilovsky <[email protected]>
commit d243af7ab9feb49f11f2c0050d2077e2d9556f9b upstream.
When the client hits a network reconnect, it re-opens every open file with a create context to reconnect a persistent handle. All create context types should be 8-bytes aligned but the padding was missed for that one. As a result, some servers don't allow us to reconnect handles and return an error. The problem occurs when the problematic context is not at the end of the create request packet. Fix this by adding a proper padding at the end of the reconnect persistent handle context.
--- fs/cifs/smb2pdu.h | 1 + 1 file changed, 1 insertion(+)
fs/cifs/smb2pdu.h +1 -0
@@ -777,6 +777,7 @@ struct create_durable_handle_reconnect_vstruct create_context ccontext;__u8 Name[8 ];struct durable_reconnect_context_v2 dcontext; +__u8 Pad[4 ]; } __packed;/* See MS-SMB2 2.2.13.2.5 */
Greg Kroah-Hartman
maintainerPATCH 43/125 can: usb_8dev: fix use-after-free on disconnect
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 3759739426186a924675651b388d1c3963c5710e upstream.
The driver was accessing its driver data after having freed it.
--- drivers/net/can/usb/usb_8dev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/can/usb/usb_8dev.c +1 -2
@@ -1007,9 +1007,8 @@ static void usb_8dev_disconnect(struct unetdev_info (priv->netdev,"device disconnected\n" );unregister_netdev (priv->netdev); -free_candev (priv->netdev); -unlink_all_urbs (priv); +free_candev (priv->netdev); } }
Greg Kroah-Hartman
maintainerPATCH 44/125 can: flexcan: disable completely the ECC mechanism
In reply to Greg Kroah-HartmanFrom: Joakim Zhang <[email protected]>
commit 5e269324db5adb2f5f6ec9a93a9c7b0672932b47 upstream.
The ECC (memory error detection and correction) mechanism can be activated or not, controlled by the ECCDIS bit in CAN_MECR. When disabled, updates on indications and reporting registers are stopped. So if want to disable ECC completely, had better assert ECCDIS bit, not just mask the related interrupts.
--- drivers/net/can/flexcan.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/can/flexcan.c +1 -0
@@ -1048,6 +1048,7 @@ static int flexcan_chip_start(struct net reg_mecr = priv->read (®s->mecr); reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS ; priv->write (reg_mecr, ®s->mecr); + reg_mecr |=FLEXCAN_MECR_ECCDIS ; reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ |FLEXCAN_MECR_HANCEI_MSK |FLEXCAN_MECR_FANCEI_MSK ); priv->write (reg_mecr, ®s->mecr);
Greg Kroah-Hartman
maintainerPATCH 45/125 can: c_can: c_can_poll(): only read status register after status IRQ
In reply to Greg Kroah-HartmanFrom: Kurt Van Dijck <[email protected]>
commit 3cb3eaac52c0f145d895f4b6c22834d5f02b8569 upstream.
When the status register is read without the status IRQ pending, the chip may not raise the interrupt line for an upcoming status interrupt and the driver may miss a status interrupt.
It is critical that the BUSOFF status interrupt is forwarded to the higher layers, since no more interrupts will follow without intervention.
Thanks to Wolfgang and Joe for bringing up the first idea.
--- drivers/net/can/c_can/c_can.c | 25 ++++++++++++++++++++----- drivers/net/can/c_can/c_can.h | 1 + 2 files changed, 21 insertions(+), 5 deletions(-)
drivers/net/can/c_can/c_can.c +20 -5
@@ -97,6 +97,9 @@#define BTR_TSEG2_SHIFT 12#define BTR_TSEG2_MASK (0x7 << BTR_TSEG2_SHIFT) +/* interrupt register */ +#define INT_STS_PENDING 0x8000 +/* brp extension register */ #define BRP_EXT_BRPE_MASK 0x0f#define BRP_EXT_BRPE_SHIFT 0
@@ -1029,10 +1032,16 @@ static int c_can_poll(struct napi_structu16 curr, last = priv->last_status;int work_done =0 ; - priv->last_status = curr = priv->read_reg (priv,C_CAN_STS_REG ); -/* Ack status on C_CAN. D_CAN is self clearing */ -if (priv->type !=BOSCH_D_CAN ) - priv->write_reg (priv,C_CAN_STS_REG ,LEC_UNUSED ); +/* Only read the status register if a status interrupt was pending */ +if (atomic_xchg (&priv->sie_pending,0 )) { + priv->last_status = curr = priv->read_reg (priv,C_CAN_STS_REG ); +/* Ack status on C_CAN. D_CAN is self clearing */ +if (priv->type !=BOSCH_D_CAN ) + priv->write_reg (priv,C_CAN_STS_REG ,LEC_UNUSED ); + }else { +/* no change detected ... */ + curr = last; + }/* handle state changes */ if ((curr &STATUS_EWARN ) && (!(last &STATUS_EWARN ))) {
@@ -1083,10 +1092,16 @@ static irqreturn_t c_can_isr(int irq, vo {struct net_device *dev = (struct net_device *)dev_id;struct c_can_priv *priv =netdev_priv (dev); +int reg_int; -if (!priv->read_reg (priv,C_CAN_INT_REG )) + reg_int = priv->read_reg (priv,C_CAN_INT_REG ); +if (!reg_int)return IRQ_NONE ; +/* save for later use */ +if (reg_int &INT_STS_PENDING ) +atomic_set (&priv->sie_pending,1 ); +/* disable all interrupts and schedule the NAPI */ c_can_irq_control (priv, false);napi_schedule (&priv->napi);
drivers/net/can/c_can/c_can.h +1 -0
@@ -198,6 +198,7 @@ struct c_can_priv {struct net_device *dev;struct device *device;atomic_t tx_active; +atomic_t sie_pending;unsigned long tx_dir;int last_status;u16 (*read_reg) (const struct c_can_priv *priv,enum reg index);
Greg Kroah-Hartman
maintainerPATCH 46/125 can: peak_usb: fix a potential out-of-sync while decoding packets
In reply to Greg Kroah-HartmanFrom: Stephane Grosjean <[email protected]>
commit de280f403f2996679e2607384980703710576fed upstream.
When decoding a buffer received from PCAN-USB, the first timestamp read in a packet is a 16-bit coded time base, and the next ones are an 8-bit offset to this base, regardless of the type of packet read.
This patch corrects a potential loss of synchronization by using a timestamp index read from the buffer, rather than an index of received data packets, to determine on the sizeof the timestamp to be read from the packet being decoded.
--- drivers/net/can/usb/peak_usb/pcan_usb.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/net/can/usb/peak_usb/pcan_usb.c +12 -5
@@ -108,7 +108,7 @@ struct pcan_usb_msg_context {u8 *end;u8 rec_cnt;u8 rec_idx; -u8 rec_data_idx; +u8 rec_ts_idx;struct net_device *netdev;struct pcan_usb *pdev; };
@@ -555,10 +555,15 @@ static int pcan_usb_decode_status(struct mc->ptr +=PCAN_USB_CMD_ARGS ;if (status_len &PCAN_USB_STATUSLEN_TIMESTAMP ) { -int err =pcan_usb_decode_ts (mc, !mc->rec_idx); +int err =pcan_usb_decode_ts (mc, !mc->rec_ts_idx);if (err)return err; + +/* Next packet in the buffer will have a timestamp on a single +* byte +*/ + mc->rec_ts_idx++; }switch (f) {
@@ -640,10 +645,13 @@ static int pcan_usb_decode_data(struct p cf->can_dlc =get_can_dlc (rec_len); -/* first data packet timestamp is a word */ -if (pcan_usb_decode_ts (mc, !mc->rec_data_idx)) +/* Only first packet timestamp is a word */ +if (pcan_usb_decode_ts (mc, !mc->rec_ts_idx)) goto decode_failed; +/* Next packet in the buffer will have a timestamp on a single byte */ + mc->rec_ts_idx++; +/* read data */ memset (cf->data,0x0 ,sizeof (cf->data));if (status_len &PCAN_USB_STATUSLEN_RTR ) {
@@ -696,7 +704,6 @@ static int pcan_usb_decode_msg(struct pe/* handle normal can frames here */ }else { err =pcan_usb_decode_data (&mc, sl); - mc.rec_data_idx++; } }
Greg Kroah-Hartman
maintainerPATCH 47/125 can: rx-offload: can_rx_offload_queue_sorted(): fix error handling, avoid skb mem leak
In reply to Greg Kroah-HartmanFrom: Marc Kleine-Budde <[email protected]>
commit ca913f1ac024559ebc17f0b599af262f0ad997c9 upstream.
If the rx-offload skb_queue is full can_rx_offload_queue_sorted() will not queue the skb and return with an error.
None of the callers of this function, issue a kfree_skb() to free the not queued skb. This results in a memory leak.
This patch fixes the problem by freeing the skb in case of a full queue. The return value is adjusted to -ENOBUFS to better reflect the actual problem.
The device stats handling is left to the callers, as this function might be used in both the rx and tx path.
--- drivers/net/can/rx-offload.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/can/rx-offload.c +4 -2
@@ -216,8 +216,10 @@ int can_rx_offload_queue_sorted(struct cunsigned long flags;if (skb_queue_len (&offload->skb_queue) > - offload->skb_queue_len_max) -return -ENOMEM ; + offload->skb_queue_len_max) { +kfree_skb (skb); +return -ENOBUFS ; + } cb =can_rx_offload_get_cb (skb); cb->timestamp = timestamp;
Greg Kroah-Hartman
maintainerPATCH 48/125 can: gs_usb: gs_can_open(): prevent memory leak
In reply to Greg Kroah-HartmanFrom: Navid Emamdoost <[email protected]>
commit fb5be6a7b4863ecc44963bb80ca614584b6c7817 upstream.
In gs_can_open() if usb_submit_urb() fails the allocated urb should be released.
--- drivers/net/can/usb/gs_usb.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/can/usb/gs_usb.c +1 -0
@@ -631,6 +631,7 @@ static int gs_can_open(struct net_device rc);usb_unanchor_urb (urb); +usb_free_urb (urb);break ; }
Greg Kroah-Hartman
maintainerPATCH 49/125 can: dev: add missing of_node_put() after calling of_get_child_by_name()
In reply to Greg Kroah-HartmanFrom: Wen Yang <[email protected]>
commit db9ee384f6f71f7c5296ce85b7c1a2a2527e7c72 upstream.
of_node_put() needs to be called when the device node which is got from of_get_child_by_name() finished using.
--- drivers/net/can/dev.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/can/dev.c +1 -0
@@ -853,6 +853,7 @@ void of_can_transceiver(struct net_devicreturn ; ret =of_property_read_u32 (dn,"max-bitrate" , &priv->bitrate_max); +of_node_put (dn);if ((ret && ret != -EINVAL ) || (!ret && !priv->bitrate_max))netdev_warn (dev,"Invalid value for transceiver max bitrate. Ignoring bitrate limit.\n" ); }
Greg Kroah-Hartman
maintainerPATCH 50/125 can: mcba_usb: fix use-after-free on disconnect
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 4d6636498c41891d0482a914dd570343a838ad79 upstream.
The driver was accessing its driver data after having freed it.
--- drivers/net/can/usb/mcba_usb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/can/usb/mcba_usb.c +1 -2
@@ -887,9 +887,8 @@ static void mcba_usb_disconnect(struct unetdev_info (priv->netdev,"device disconnected\n" );unregister_candev (priv->netdev); -free_candev (priv->netdev); -mcba_urb_unlink (priv); +free_candev (priv->netdev); }static struct usb_driver mcba_usb_driver = {
Greg Kroah-Hartman
maintainerPATCH 51/125 can: peak_usb: fix slab info leak
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit f7a1337f0d29b98733c8824e165fca3371d7d4fd upstream.
Fix a small slab info leak due to a failure to clear the command buffer at allocation.
The first 16 bytes of the command buffer are always sent to the device in pcan_usb_send_cmd() even though only the first two may have been initialised in case no argument payload is provided (e.g. when waiting for a response).
--- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/can/usb/peak_usb/pcan_usb_core.c +1 -1
@@ -758,7 +758,7 @@ static int peak_usb_create_dev(const str dev =netdev_priv (netdev);/* allocate a buffer large enough to send commands */ - dev->cmd_buf =kmalloc (PCAN_USB_MAX_CMD_LEN ,GFP_KERNEL ); + dev->cmd_buf =kzalloc (PCAN_USB_MAX_CMD_LEN ,GFP_KERNEL );if (!dev->cmd_buf) { err = -ENOMEM ; goto lbl_free_candev;
Greg Kroah-Hartman
maintainerPATCH 52/125 configfs: stash the data we need into configfs_buffer at open time
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit ff4dd081977da56566a848f071aed8fa92d604a1 upstream.
simplifies the ->read()/->write()/->release() instances nicely
--- fs/configfs/file.c | 229 +++++++++++++++++++++-------------------------------- 1 file changed, 95 insertions(+), 134 deletions(-)
fs/configfs/file.c +95 -134
@@ -53,24 +53,18 @@ struct configfs_buffer {bool write_in_progress;char *bin_buffer;int bin_buffer_size; +int cb_max_size; +struct config_item *item; +struct module *owner; +union { +struct configfs_attribute *attr; +struct configfs_bin_attribute *bin_attr; + }; }; -/** -* fill_read_buffer - allocate and fill buffer from item. -* @dentry: dentry pointer. -* @buffer: data buffer for file. -* -* Allocate @buffer->page, if it hasn't been already, then call the -* config_item's show() method to fill the buffer with this attribute's -* data. -* This is called only once, on the file's first read. -*/ -static int fill_read_buffer (struct dentry * dentry,struct configfs_buffer * buffer) +static int fill_read_buffer (struct configfs_buffer * buffer) { -struct configfs_attribute * attr =to_attr (dentry); -struct config_item * item =to_item (dentry->d_parent); -int ret =0 ;ssize_t count;if (!buffer->page)
@@ -78,15 +72,15 @@ static int fill_read_buffer(struct dentrif (!buffer->page)return -ENOMEM ; - count = attr->show (item, buffer->page); + count = buffer->attr->show (buffer->item, buffer->page); +if (count <0 ) +return count; +if (WARN_ON_ONCE (count > (ssize_t )SIMPLE_ATTR_SIZE )) +return -EIO ; -BUG_ON (count > (ssize_t )SIMPLE_ATTR_SIZE ); -if (count >=0 ) { - buffer->needs_read_fill =0 ; - buffer->count = count; - }else - ret = count; -return ret; + buffer->needs_read_fill =0 ; + buffer->count = count; +return 0 ; }/**
@@ -111,12 +105,13 @@ static int fill_read_buffer(struct dentrstatic ssize_t configfs_read_file (struct file *file,char __user *buf,size_t count,loff_t *ppos) { -struct configfs_buffer * buffer = file->private_data; +struct configfs_buffer *buffer = file->private_data;ssize_t retval =0 ;mutex_lock (&buffer->mutex);if (buffer->needs_read_fill) { -if ((retval =fill_read_buffer (file->f_path.dentry,buffer))) + retval =fill_read_buffer (buffer); +if (retval) goto out; } pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
@@ -153,9 +148,6 @@ configfs_read_bin_file(struct file *file size_t count, loff_t *ppos) { struct configfs_buffer *buffer = file->private_data; -struct dentry *dentry = file->f_path.dentry; -struct config_item *item =to_item (dentry->d_parent); -struct configfs_bin_attribute *bin_attr =to_bin_attr (dentry);ssize_t retval =0 ;ssize_t len =min_t (size_t, count,PAGE_SIZE );
@@ -170,14 +162,14 @@ configfs_read_bin_file(struct file *fileif (buffer->needs_read_fill) {/* perform first read with buf == NULL to get extent */ - len = bin_attr->read (item,NULL ,0 ); + len = buffer->bin_attr->read (buffer->item,NULL ,0 );if (len <=0 ) { retval = len; goto out; }/* do not exceed the maximum value */ -if (bin_attr->cb_max_size && len > bin_attr->cb_max_size) { +if (buffer->cb_max_size && len > buffer->cb_max_size) { retval = -EFBIG ; goto out; }
@@ -190,7 +182,8 @@ configfs_read_bin_file(struct file *file buffer->bin_buffer_size = len;/* perform second read to fill buffer */ - len = bin_attr->read (item, buffer->bin_buffer, len); + len = buffer->bin_attr->read (buffer->item, + buffer->bin_buffer, len);if (len <0 ) { retval = len;vfree (buffer->bin_buffer);
@@ -240,25 +233,10 @@ fill_write_buffer(struct configfs_bufferreturn error ? -EFAULT : count; } - -/** -* flush_write_buffer - push buffer to config_item. -* @dentry: dentry to the attribute -* @buffer: data buffer for file. -* @count: number of bytes -* -* Get the correct pointers for the config_item and the attribute we're -* dealing with, then call the store() method for the attribute, -* passing the buffer that we acquired in fill_write_buffer(). -*/ -static int -flush_write_buffer (struct dentry * dentry,struct configfs_buffer * buffer,size_t count) +flush_write_buffer (struct configfs_buffer *buffer,size_t count) { -struct configfs_attribute * attr =to_attr (dentry); -struct config_item * item =to_item (dentry->d_parent); - -return attr->store (item, buffer->page, count); +return buffer->attr->store (buffer->item, buffer->page, count); }
@@ -282,13 +260,13 @@ flush_write_buffer(struct dentry * dentrstatic ssize_t configfs_write_file (struct file *file,const char __user *buf,size_t count,loff_t *ppos) { -struct configfs_buffer * buffer = file->private_data; +struct configfs_buffer *buffer = file->private_data;ssize_t len;mutex_lock (&buffer->mutex); len =fill_write_buffer (buffer, buf, count);if (len >0 ) - len =flush_write_buffer (file->f_path.dentry, buffer, len); + len =flush_write_buffer (buffer, len);if (len >0 ) *ppos += len;mutex_unlock (&buffer->mutex);
@@ -313,8 +291,6 @@ configfs_write_bin_file(struct file *fil size_t count, loff_t *ppos) { struct configfs_buffer *buffer = file->private_data; -struct dentry *dentry = file->f_path.dentry; -struct configfs_bin_attribute *bin_attr =to_bin_attr (dentry);void *tbuf =NULL ;ssize_t len;
@@ -330,8 +306,8 @@ configfs_write_bin_file(struct file *fil/* buffer grows? */ if (*ppos + count > buffer->bin_buffer_size) { -if (bin_attr->cb_max_size && - *ppos + count > bin_attr->cb_max_size) { +if (buffer->cb_max_size && + *ppos + count > buffer->cb_max_size) { len = -EFBIG ; goto out; }
@@ -363,31 +339,45 @@ out:return len; } -static int check_perm (struct inode * inode,struct file * file,int type) +static int __configfs_open_file (struct inode *inode,struct file *file,int type) { -struct config_item *item =configfs_get_config_item (file->f_path.dentry->d_parent); -struct configfs_attribute * attr =to_attr (file->f_path.dentry); -struct configfs_bin_attribute *bin_attr =NULL ; -struct configfs_buffer * buffer; -struct configfs_item_operations * ops =NULL ; -int error =0 ; +struct dentry *dentry = file->f_path.dentry; +struct configfs_attribute *attr; +struct configfs_buffer *buffer; +int error; -if (!item || !attr) - goto Einval; + error = -ENOMEM ; + buffer =kzalloc (sizeof (struct configfs_buffer ),GFP_KERNEL ); +if (!buffer) + goto out; -if (type &CONFIGFS_ITEM_BIN_ATTR ) - bin_attr =to_bin_attr (file->f_path.dentry); + error = -EINVAL ; + buffer->item =configfs_get_config_item (dentry->d_parent); +if (!buffer->item) + goto out_free_buffer; + + attr =to_attr (dentry); +if (!attr) + goto out_put_item; + +if (type &CONFIGFS_ITEM_BIN_ATTR ) { + buffer->bin_attr =to_bin_attr (dentry); + buffer->cb_max_size = buffer->bin_attr->cb_max_size; + }else { + buffer->attr = attr; + } + buffer->owner = attr->ca_owner;/* Grab the module reference for this attribute if we have one */ -if (!try_module_get (attr->ca_owner)) { - error = -ENODEV ; - goto Done; - } + error = -ENODEV ; +if (!try_module_get (buffer->owner)) + goto out_put_item; -if (item->ci_type) - ops = item->ci_type->ct_item_ops; -else - goto Eaccess; + error = -EACCES ; +if (!buffer->item->ci_type) + goto out_put_module; + + buffer->ops = buffer->item->ci_type->ct_item_ops;/* File needs write support. * The inode's perms must say it's ok,
@@ -395,13 +385,11 @@ static int check_perm(struct inode * ino*/ if (file->f_mode &FMODE_WRITE ) {if (!(inode->i_mode &S_IWUGO )) - goto Eaccess; - + goto out_put_module;if ((type &CONFIGFS_ITEM_ATTR ) && !attr->store) - goto Eaccess; - -if ((type &CONFIGFS_ITEM_BIN_ATTR ) && !bin_attr->write) - goto Eaccess; + goto out_put_module; +if ((type &CONFIGFS_ITEM_BIN_ATTR ) && !buffer->bin_attr->write) + goto out_put_module; }/* File needs read support.
@@ -410,90 +398,65 @@ static int check_perm(struct inode * ino*/ if (file->f_mode &FMODE_READ ) {if (!(inode->i_mode &S_IRUGO )) - goto Eaccess; - + goto out_put_module;if ((type &CONFIGFS_ITEM_ATTR ) && !attr->show) - goto Eaccess; - -if ((type &CONFIGFS_ITEM_BIN_ATTR ) && !bin_attr->read) - goto Eaccess; + goto out_put_module; +if ((type &CONFIGFS_ITEM_BIN_ATTR ) && !buffer->bin_attr->read) + goto out_put_module; } -/* No error? Great, allocate a buffer for the file, and store it -* it in file->private_data for easy access. -*/ - buffer =kzalloc (sizeof (struct configfs_buffer ),GFP_KERNEL ); -if (!buffer) { - error = -ENOMEM ; - goto Enomem; - }mutex_init (&buffer->mutex); buffer->needs_read_fill =1 ; buffer->read_in_progress = false; buffer->write_in_progress = false; - buffer->ops = ops; file->private_data = buffer; - goto Done; +return 0 ; - Einval: - error = -EINVAL ; - goto Done; - Eaccess: - error = -EACCES ; - Enomem: -module_put (attr->ca_owner); - Done: -if (error && item) -config_item_put (item); +out_put_module: +module_put (buffer->owner); +out_put_item: +config_item_put (buffer->item); +out_free_buffer: +kfree (buffer); +out:return error; }static int configfs_release (struct inode *inode,struct file *filp) { -struct config_item * item =to_item (filp->f_path.dentry->d_parent); -struct configfs_attribute * attr =to_attr (filp->f_path.dentry); -struct module * owner = attr->ca_owner; -struct configfs_buffer * buffer = filp->private_data; - -if (item) -config_item_put (item); -/* After this point, attr should not be accessed. */ -module_put (owner); - -if (buffer) { -if (buffer->page) -free_page ((unsigned long )buffer->page); -mutex_destroy (&buffer->mutex); -kfree (buffer); - } +struct configfs_buffer *buffer = filp->private_data; + +if (buffer->item) +config_item_put (buffer->item); +module_put (buffer->owner); +if (buffer->page) +free_page ((unsigned long )buffer->page); +mutex_destroy (&buffer->mutex); +kfree (buffer);return 0 ; }static int configfs_open_file (struct inode *inode,struct file *filp) { -return check_perm (inode, filp,CONFIGFS_ITEM_ATTR ); +return __configfs_open_file (inode, filp,CONFIGFS_ITEM_ATTR ); }static int configfs_open_bin_file (struct inode *inode,struct file *filp) { -return check_perm (inode, filp,CONFIGFS_ITEM_BIN_ATTR ); +return __configfs_open_file (inode, filp,CONFIGFS_ITEM_BIN_ATTR ); } -static int configfs_release_bin_file (struct inode *inode,struct file *filp) +static int configfs_release_bin_file (struct inode *inode,struct file *file) { -struct configfs_buffer *buffer = filp->private_data; -struct dentry *dentry = filp->f_path.dentry; -struct config_item *item =to_item (dentry->d_parent); -struct configfs_bin_attribute *bin_attr =to_bin_attr (dentry); -ssize_t len =0 ; -int ret; +struct configfs_buffer *buffer = file->private_data; buffer->read_in_progress = false;if (buffer->write_in_progress) { buffer->write_in_progress = false; - len = bin_attr->write (item, buffer->bin_buffer, +/* result of ->release() is ignored */ + buffer->bin_attr->write (buffer->item, buffer->bin_buffer, buffer->bin_buffer_size);/* vfree on NULL is safe */
@@ -503,10 +466,8 @@ static int configfs_release_bin_file(str buffer->needs_read_fill =1 ; } - ret =configfs_release (inode, filp); -if (len <0 ) -return len; -return ret; +configfs_release (inode, file); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 53/125 configfs_register_group() shouldnt be (and isnt) called in rmdirable parts
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit f19e4ed1e1edbfa3c9ccb9fed17759b7d6db24c6 upstream.
revert cc57c07343bd "configfs: fix registered group removal" It was an attempt to handle something that fundamentally doesn't work - configfs_register_group() should never be done in a part of tree that can be rmdir'ed. And in mainline it never had been, so let's not borrow trouble; the fix was racy anyway, it would take a lot more to make that work and desired semantics is not clear.
--- fs/configfs/dir.c | 11 ----------- 1 file changed, 11 deletions(-)
fs/configfs/dir.c +0 -11
@@ -1782,16 +1782,6 @@ void configfs_unregister_group(struct costruct dentry *dentry = group->cg_item.ci_dentry;struct dentry *parent = group->cg_item.ci_parent->ci_dentry; -mutex_lock (&subsys->su_mutex); -if (!group->cg_item.ci_parent->ci_group) { -/* -* The parent has already been unlinked and detached -* due to a rmdir. -*/ - goto unlink_group; - } -mutex_unlock (&subsys->su_mutex); -inode_lock_nested (d_inode (parent),I_MUTEX_PARENT );spin_lock (&configfs_dirent_lock);configfs_detach_prep (dentry,NULL );
@@ -1806,7 +1796,6 @@ void configfs_unregister_group(struct codput (dentry);mutex_lock (&subsys->su_mutex); -unlink_group:unlink_group (group);mutex_unlock (&subsys->su_mutex); }
Greg Kroah-Hartman
maintainerPATCH 54/125 configfs: new object reprsenting tree fragments
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit 47320fbe11a6059ae502c9c16b668022fdb4cf76 upstream.
Refcounted, hangs of configfs_dirent, created by operations that add fragments to configfs tree (mkdir and configfs_register_{subsystem,group}). Will be used in the next commit to provide exclusion between fragment removal and ->show/->store calls.
--- fs/configfs/configfs_internal.h | 15 ++++- fs/configfs/dir.c | 105 +++++++++++++++++++++++++++++++--------- fs/configfs/file.c | 4 - 3 files changed, 97 insertions(+), 27 deletions(-)
fs/configfs/configfs_internal.h +13 -2
@@ -34,6 +34,15 @@#include <linux/list.h> #include <linux/spinlock.h> +struct configfs_fragment { +atomic_t frag_count; +struct rw_semaphore frag_sem; +bool frag_dead; +}; + +void put_fragment (struct configfs_fragment *); +struct configfs_fragment *get_fragment (struct configfs_fragment *); +struct configfs_dirent {atomic_t s_count;int s_dependent_count;
@@ -48,6 +57,7 @@ struct configfs_dirent {#ifdef CONFIG_LOCKDEP int s_depth;#endif +struct configfs_fragment *s_frag; };#define CONFIGFS_ROOT 0x0001
@@ -75,8 +85,8 @@ extern int configfs_create(struct dentryextern int configfs_create_file (struct config_item *,const struct configfs_attribute *);extern int configfs_create_bin_file (struct config_item *,const struct configfs_bin_attribute *); -extern int configfs_make_dirent (struct configfs_dirent *, -struct dentry *,void *,umode_t ,int ); +extern int configfs_make_dirent (struct configfs_dirent *,struct dentry *, +void *,umode_t ,int ,struct configfs_fragment *);extern int configfs_dirent_is_ready (struct configfs_dirent *);extern void configfs_hash_and_remove (struct dentry * dir,const char * name);
@@ -151,6 +161,7 @@ static inline void release_configfs_dire {if (!(sd->s_type &CONFIGFS_ROOT )) {kfree (sd->s_iattr); +put_fragment (sd->s_frag);kmem_cache_free (configfs_dir_cachep, sd); } }
fs/configfs/dir.c +82 -23
281 lines not on this page · raw message
fs/configfs/file.c +2 -2
@@ -502,7 +502,7 @@ int configfs_create_file(struct config_iinode_lock_nested (d_inode (dir),I_MUTEX_NORMAL ); error =configfs_make_dirent (parent_sd,NULL , (void *) attr, mode, -CONFIGFS_ITEM_ATTR ); +CONFIGFS_ITEM_ATTR , parent_sd->s_frag);inode_unlock (d_inode (dir));return error;
@@ -524,7 +524,7 @@ int configfs_create_bin_file(struct confinode_lock_nested (dir->d_inode,I_MUTEX_NORMAL ); error =configfs_make_dirent (parent_sd,NULL , (void *) bin_attr, mode, -CONFIGFS_ITEM_BIN_ATTR ); +CONFIGFS_ITEM_BIN_ATTR , parent_sd->s_frag);inode_unlock (dir->d_inode);return error;
Greg Kroah-Hartman
maintainerPATCH 55/125 configfs: provide exclusion between IO and removals
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit b0841eefd9693827afb9888235e26ddd098f9cef upstream.
Make sure that attribute methods are not called after the item has been removed from the tree. To do so, we
* at the point of no return in removals, grab ->frag_sem
exclusive and mark the fragment dead.
* call the methods of attributes with ->frag_sem taken
shared and only after having verified that the fragment is still alive.
The main benefit is for method instances - they are
guaranteed that the objects they are accessing *and* all ancestors are still there. Another win is that we don't need to bother with extra refcount on config_item when opening a file - the item will be alive for as long as it stays in the tree, and we won't touch it/attributes/any associated data after it's been removed from the tree.
--- fs/configfs/dir.c | 23 ++++++++++++++++ fs/configfs/file.c | 75 ++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 80 insertions(+), 18 deletions(-)
fs/configfs/dir.c +23 -0
@@ -1474,6 +1474,7 @@ static int configfs_rmdir(struct inode *struct config_item *item;struct configfs_subsystem *subsys;struct configfs_dirent *sd; +struct configfs_fragment *frag;struct module *subsys_owner =NULL , *dead_item_owner =NULL ;int ret;
@@ -1531,6 +1532,16 @@ static int configfs_rmdir(struct inode * } }while (ret == -EAGAIN ); + frag = sd->s_frag; +if (down_write_killable (&frag->frag_sem)) { +spin_lock (&configfs_dirent_lock); +configfs_detach_rollback (dentry); +spin_unlock (&configfs_dirent_lock); +return -EINTR ; + } + frag->frag_dead = true; +up_write (&frag->frag_sem); +/* Get a working ref for the duration of this function */ item =configfs_get_config_item (dentry);
@@ -1832,6 +1843,12 @@ void configfs_unregister_group(struct costruct configfs_subsystem *subsys = group->cg_subsys;struct dentry *dentry = group->cg_item.ci_dentry;struct dentry *parent = group->cg_item.ci_parent->ci_dentry; +struct configfs_dirent *sd = dentry->d_fsdata; +struct configfs_fragment *frag = sd->s_frag; + +down_write (&frag->frag_sem); + frag->frag_dead = true; +up_write (&frag->frag_sem);inode_lock_nested (d_inode (parent),I_MUTEX_PARENT );spin_lock (&configfs_dirent_lock);
@@ -1957,12 +1974,18 @@ void configfs_unregister_subsystem(strucstruct config_group *group = &subsys->su_group;struct dentry *dentry = group->cg_item.ci_dentry;struct dentry *root = dentry->d_sb->s_root; +struct configfs_dirent *sd = dentry->d_fsdata; +struct configfs_fragment *frag = sd->s_frag;if (dentry->d_parent != root) {pr_err ("Tried to unregister non-subsystem!\n" );return ; } +down_write (&frag->frag_sem); + frag->frag_dead = true; +up_write (&frag->frag_sem); +inode_lock_nested (d_inode (root),I_MUTEX_PARENT );inode_lock_nested (d_inode (dentry),I_MUTEX_CHILD );
fs/configfs/file.c +57 -18
169 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 56/125 configfs: fix a deadlock in configfs_symlink()
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
commit 351e5d869e5ac10cb40c78b5f2d7dfc816ad4587 upstream.
Configfs abuses symlink(2). Unlike the normal filesystems, it wants the target resolved at symlink(2) time, like link(2) would've done. The problem is that ->symlink() is called with the parent directory locked exclusive, so resolving the target inside the ->symlink() is easily deadlocked.
Short of really ugly games in sys_symlink() itself, all we can do is to unlock the parent before resolving the target and relock it after. However, that invalidates the checks done by the caller of ->symlink(), so we have to
* check that dentry is still where it used to be
(it couldn't have been moved, but it could've been unhashed)
* recheck that it's still negative (somebody else
might've successfully created a symlink with the same name while we were looking the target up)
* recheck the permissions on the parent directory.
--- fs/configfs/symlink.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-)
fs/configfs/symlink.c +32 -1
@@ -157,11 +157,42 @@ int configfs_symlink(struct inode *dir, !type->ct_item_ops->allow_link) goto out_put; +/* +* This is really sick. What they wanted was a hybrid of +* link(2) and symlink(2) - they wanted the target resolved +* at syscall time (as link(2) would've done), be a directory +* (which link(2) would've refused to do) *AND* be a deep +* fucking magic, making the target busy from rmdir POV. +* symlink(2) is nothing of that sort, and the locking it +* gets matches the normal symlink(2) semantics. Without +* attempts to resolve the target (which might very well +* not even exist yet) done prior to locking the parent +* directory. This perversion, OTOH, needs to resolve +* the target, which would lead to obvious deadlocks if +* attempted with any directories locked. +* +* Unfortunately, that garbage is userland ABI and we should've +* said "no" back in 2005. Too late now, so we get to +* play very ugly games with locking. +* +* Try *ANYTHING* of that sort in new code, and you will +* really regret it. Just ask yourself - what could a BOFH +* do to me and do I want to find it out first-hand? +* +* AV, a thoroughly annoyed bastard. +*/ +inode_unlock (dir); ret =get_target (symname, &path, &target_item, dentry->d_sb); +inode_lock (dir);if (ret) goto out_put; - ret = type->ct_item_ops->allow_link (parent_item, target_item); +if (dentry->d_inode ||d_unhashed (dentry)) + ret = -EEXIST ; +else + ret =inode_permission (dir,MAY_WRITE |MAY_EXEC ); +if (!ret) + ret = type->ct_item_ops->allow_link (parent_item, target_item);if (!ret) {mutex_lock (&configfs_symlink_mutex); ret =create_link (parent_item, target_item, dentry);
Greg Kroah-Hartman
maintainerPATCH 57/125 ALSA: usb-audio: More validations of descriptor units
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 57f8770620e9b51c61089751f0b5ad3dbe376ff2 upstream.
Introduce a new helper to validate each audio descriptor unit before and check the unit before actually accessing it. This should harden against the OOB access cases with malformed descriptors that have been recently frequently reported by fuzzers.
The existing descriptor checks are still kept although they become superfluous after this patch. They'll be cleaned up eventually later.
--- sound/usb/Makefile | 3 sound/usb/helper.h | 4 sound/usb/mixer.c | 10 + sound/usb/power.c | 2 sound/usb/quirks.c | 3 sound/usb/stream.c | 25 +-- sound/usb/validate.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 366 insertions(+), 13 deletions(-)
sound/usb/Makefile +2 -1
@@ -16,7 +16,8 @@ snd-usb-audio-objs := card.o \ power.o \ proc.o \ quirks.o \ - stream.o + stream.o \ + validate.o snd-usbmidi-lib-objs := midi.o
sound/usb/helper.h +4 -0
@@ -30,4 +30,8 @@ static inline int snd_usb_ctrl_intf(stru return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber; } +/* in validate.c */ +bool snd_usb_validate_audio_desc (void *p,int protocol); +bool snd_usb_validate_midi_desc (void *p); +#endif /* __USBAUDIO_HELPER_H */
sound/usb/mixer.c +10 -0
@@ -800,6 +800,8 @@ static int __check_input_term(struct mix p1 =find_audio_control_unit (state, id);if (!p1)break ; +if (!snd_usb_validate_audio_desc (p1, protocol)) +break ;/* bad descriptor */ hdr = p1; term->id = id;
@@ -2794,6 +2796,11 @@ static int parse_audio_unit(struct mixerreturn -EINVAL ; } +if (!snd_usb_validate_audio_desc (p1, protocol)) { +usb_audio_dbg (state->chip,"invalid unit %d\n" , unitid); +return 0 ;/* skip invalid unit */ + } +if (protocol ==UAC_VERSION_1 || protocol ==UAC_VERSION_2 ) {switch (p1[2 ]) {case UAC_INPUT_TERMINAL :
@@ -3164,6 +3171,9 @@ static int snd_usb_mixer_controls(structwhile ((p =snd_usb_find_csint_desc (mixer->hostif->extra, mixer->hostif->extralen, p,UAC_OUTPUT_TERMINAL )) !=NULL ) { +if (!snd_usb_validate_audio_desc (p, mixer->protocol)) +continue ;/* skip invalid descriptor */ +if (mixer->protocol ==UAC_VERSION_1 ) {struct uac1_output_terminal_descriptor *desc = p;
sound/usb/power.c +2 -0
@@ -31,6 +31,8 @@ snd_usb_find_power_domain(struct usb_hosstruct uac3_power_domain_descriptor *pd_desc = p;int i; +if (!snd_usb_validate_audio_desc (p,UAC_VERSION_3 )) +continue ;for (i =0 ; i < pd_desc->bNrEntities; i++) {if (pd_desc->baEntityID[i] == id) { pd->pd_id = pd_desc->bPowerDomainID;
sound/usb/quirks.c +3 -0
@@ -259,6 +259,9 @@ static int create_yamaha_midi_quirk(stru NULL, USB_MS_MIDI_OUT_JACK);if (!injd && !outjd)return -ENODEV ; +if (!snd_usb_validate_midi_desc (injd) || + !snd_usb_validate_midi_desc (outjd)) +return -ENODEV ;if (injd && (injd->bLength <5 || (injd->bJackType !=USB_MS_EMBEDDED && injd->bJackType !=USB_MS_EXTERNAL )))
sound/usb/stream.c +13 -12
@@ -637,16 +637,14 @@ static int parse_uac_endpoint_attributes*/ static void *snd_usb_find_input_terminal_descriptor (struct usb_host_interface *ctrl_iface, -int terminal_id,bool uac23) +int terminal_id,int protocol) {struct uac2_input_terminal_descriptor *term =NULL ; -size_t minlen = uac23 ?sizeof (struct uac2_input_terminal_descriptor ) : -sizeof (struct uac_input_terminal_descriptor );while ((term =snd_usb_find_csint_desc (ctrl_iface->extra, ctrl_iface->extralen, term,UAC_INPUT_TERMINAL ))) { -if (term->bLength < minlen) +if (!snd_usb_validate_audio_desc (term, protocol))continue ;if (term->bTerminalID == terminal_id)return term;
@@ -657,7 +655,7 @@ snd_usb_find_input_terminal_descriptor(sstatic void *snd_usb_find_output_terminal_descriptor (struct usb_host_interface *ctrl_iface, -int terminal_id) +int terminal_id,int protocol) {/* OK to use with both UAC2 and UAC3 */ struct uac2_output_terminal_descriptor *term =NULL ;
@@ -665,8 +663,9 @@ snd_usb_find_output_terminal_descriptor(while ((term =snd_usb_find_csint_desc (ctrl_iface->extra, ctrl_iface->extralen, term,UAC_OUTPUT_TERMINAL ))) { -if (term->bLength >=sizeof (*term) && - term->bTerminalID == terminal_id) +if (!snd_usb_validate_audio_desc (term, protocol)) +continue ; +if (term->bTerminalID == terminal_id)return term; }
@@ -741,7 +740,7 @@ snd_usb_get_audioformat_uac12(struct snd iterm =snd_usb_find_input_terminal_descriptor (chip->ctrl_intf, as->bTerminalLink, - false); + protocol);if (iterm) { num_channels = iterm->bNrChannels; chconfig =le16_to_cpu (iterm->wChannelConfig);
@@ -777,7 +776,7 @@ snd_usb_get_audioformat_uac12(struct snd*/ input_term =snd_usb_find_input_terminal_descriptor (chip->ctrl_intf, as->bTerminalLink, - true); + protocol);if (input_term) { clock = input_term->bCSourceID;if (!chconfig && (num_channels == input_term->bNrChannels))
@@ -786,7 +785,8 @@ snd_usb_get_audioformat_uac12(struct snd } output_term =snd_usb_find_output_terminal_descriptor (chip->ctrl_intf, - as->bTerminalLink); + as->bTerminalLink, + protocol);if (output_term) { clock = output_term->bCSourceID; goto found_clock;
@@ -1012,14 +1012,15 @@ snd_usb_get_audioformat_uac3(struct snd_*/ input_term =snd_usb_find_input_terminal_descriptor (chip->ctrl_intf, as->bTerminalLink, - true); +UAC_VERSION_3 );if (input_term) { clock = input_term->bCSourceID; goto found_clock; } output_term =snd_usb_find_output_terminal_descriptor (chip->ctrl_intf, - as->bTerminalLink); + as->bTerminalLink, +UAC_VERSION_3 );if (output_term) { clock = output_term->bCSourceID; goto found_clock;
sound/usb/validate.c new file +332 -0
332 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 58/125 ALSA: usb-audio: Simplify parse_audio_unit()
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 68e9fde245591d18200f8a9054cac22339437adb upstream.
Minor code refactoring by combining the UAC version and the type in the switch-case flow, so that we reduce the indentation and redundancy. One good bonus is that the duplicated definition of the same type value (e.g. UAC2_EFFECT_UNIT) can be handled more cleanly.
--- sound/usb/mixer.c | 95 ++++++++++++++++++++++-------------------------------- 1 file changed, 39 insertions(+), 56 deletions(-)
sound/usb/mixer.c +39 -56
@@ -2801,62 +2801,45 @@ static int parse_audio_unit(struct mixerreturn 0 ;/* skip invalid unit */ } -if (protocol ==UAC_VERSION_1 || protocol ==UAC_VERSION_2 ) { -switch (p1[2 ]) { -case UAC_INPUT_TERMINAL : -return parse_audio_input_terminal (state, unitid, p1); -case UAC_MIXER_UNIT : -return parse_audio_mixer_unit (state, unitid, p1); -case UAC2_CLOCK_SOURCE : -return parse_clock_source_unit (state, unitid, p1); -case UAC_SELECTOR_UNIT : -case UAC2_CLOCK_SELECTOR : -return parse_audio_selector_unit (state, unitid, p1); -case UAC_FEATURE_UNIT : -return parse_audio_feature_unit (state, unitid, p1); -case UAC1_PROCESSING_UNIT : -/* UAC2_EFFECT_UNIT has the same value */ -if (protocol ==UAC_VERSION_1 ) -return parse_audio_processing_unit (state, unitid, p1); -else -return 0 ;/* FIXME - effect units not implemented yet */ -case UAC1_EXTENSION_UNIT : -/* UAC2_PROCESSING_UNIT_V2 has the same value */ -if (protocol ==UAC_VERSION_1 ) -return parse_audio_extension_unit (state, unitid, p1); -else /* UAC_VERSION_2 */ -return parse_audio_processing_unit (state, unitid, p1); -case UAC2_EXTENSION_UNIT_V2 : -return parse_audio_extension_unit (state, unitid, p1); -default : -usb_audio_err (state->chip, -"unit %u: unexpected type 0x%02x\n" , unitid, p1[2 ]); -return -EINVAL ; - } - }else {/* UAC_VERSION_3 */ -switch (p1[2 ]) { -case UAC_INPUT_TERMINAL : -return parse_audio_input_terminal (state, unitid, p1); -case UAC3_MIXER_UNIT : -return parse_audio_mixer_unit (state, unitid, p1); -case UAC3_CLOCK_SOURCE : -return parse_clock_source_unit (state, unitid, p1); -case UAC3_SELECTOR_UNIT : -case UAC3_CLOCK_SELECTOR : -return parse_audio_selector_unit (state, unitid, p1); -case UAC3_FEATURE_UNIT : -return parse_audio_feature_unit (state, unitid, p1); -case UAC3_EFFECT_UNIT : -return 0 ;/* FIXME - effect units not implemented yet */ -case UAC3_PROCESSING_UNIT : -return parse_audio_processing_unit (state, unitid, p1); -case UAC3_EXTENSION_UNIT : -return parse_audio_extension_unit (state, unitid, p1); -default : -usb_audio_err (state->chip, -"unit %u: unexpected type 0x%02x\n" , unitid, p1[2 ]); -return -EINVAL ; - } +#define PTYPE (a, b) ((a) << 8 | (b)) +switch (PTYPE (protocol, p1[2 ])) { +case PTYPE (UAC_VERSION_1 ,UAC_INPUT_TERMINAL ): +case PTYPE (UAC_VERSION_2 ,UAC_INPUT_TERMINAL ): +case PTYPE (UAC_VERSION_3 ,UAC_INPUT_TERMINAL ): +return parse_audio_input_terminal (state, unitid, p1); +case PTYPE (UAC_VERSION_1 ,UAC_MIXER_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC_MIXER_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_MIXER_UNIT ): +return parse_audio_mixer_unit (state, unitid, p1); +case PTYPE (UAC_VERSION_2 ,UAC2_CLOCK_SOURCE ): +case PTYPE (UAC_VERSION_3 ,UAC3_CLOCK_SOURCE ): +return parse_clock_source_unit (state, unitid, p1); +case PTYPE (UAC_VERSION_1 ,UAC_SELECTOR_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC_SELECTOR_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_SELECTOR_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC2_CLOCK_SELECTOR ): +case PTYPE (UAC_VERSION_3 ,UAC3_CLOCK_SELECTOR ): +return parse_audio_selector_unit (state, unitid, p1); +case PTYPE (UAC_VERSION_1 ,UAC_FEATURE_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC_FEATURE_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_FEATURE_UNIT ): +return parse_audio_feature_unit (state, unitid, p1); +case PTYPE (UAC_VERSION_1 ,UAC1_PROCESSING_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC2_PROCESSING_UNIT_V2 ): +case PTYPE (UAC_VERSION_3 ,UAC3_PROCESSING_UNIT ): +return parse_audio_processing_unit (state, unitid, p1); +case PTYPE (UAC_VERSION_1 ,UAC1_EXTENSION_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC2_EXTENSION_UNIT_V2 ): +case PTYPE (UAC_VERSION_3 ,UAC3_EXTENSION_UNIT ): +return parse_audio_extension_unit (state, unitid, p1); +case PTYPE (UAC_VERSION_2 ,UAC2_EFFECT_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_EFFECT_UNIT ): +return 0 ;/* FIXME - effect units not implemented yet */ +default : +usb_audio_err (state->chip, +"unit %u: unexpected type 0x%02x\n" , + unitid, p1[2 ]); +return -EINVAL ; } }
Greg Kroah-Hartman
maintainerPATCH 59/125 ALSA: usb-audio: Unify the release of usb_mixer_elem_info objects
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 52c3e317a857091fd746e15179a637f32be4d337 upstream.
Instead of the direct kfree() calls, introduce a new local helper to release the usb_mixer_elem_info object. This will be extended to do more than a single kfree() in the later patches.
Also, use the standard goto instead of multiple calls in parse_audio_selector_unit() error paths.
--- sound/usb/mixer.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-)
sound/usb/mixer.c +28 -20
@@ -1041,10 +1041,15 @@ static struct usb_feature_control_info a { UAC2_FU_PHASE_INVERTER, "Phase Inverter Control", USB_MIXER_BOOLEAN, -1 }, }; +static void usb_mixer_elem_info_free (struct usb_mixer_elem_info *cval) +{ +kfree (cval); +} +/* private_free callback */ void snd_usb_mixer_elem_free (struct snd_kcontrol *kctl) { -kfree (kctl->private_data); +usb_mixer_elem_info_free (kctl->private_data); kctl->private_data =NULL ; }
@@ -1567,7 +1572,7 @@ static void __build_feature_ctl(struct u ctl_info =get_feature_control_info (control);if (!ctl_info) { -kfree (cval); +usb_mixer_elem_info_free (cval);return ; }if (mixer->protocol ==UAC_VERSION_1 )
@@ -1600,7 +1605,7 @@ static void __build_feature_ctl(struct uif (!kctl) {usb_audio_err (mixer->chip,"cannot malloc kcontrol\n" ); -kfree (cval); +usb_mixer_elem_info_free (cval);return ; } kctl->private_free = snd_usb_mixer_elem_free;
@@ -1770,7 +1775,7 @@ static void build_connector_control(stru kctl =snd_ctl_new1 (&usb_connector_ctl_ro, cval);if (!kctl) {usb_audio_err (mixer->chip,"cannot malloc kcontrol\n" ); -kfree (cval); +usb_mixer_elem_info_free (cval);return ; } get_connector_control_name(mixer, term, is_input, kctl->id.name,
@@ -1823,7 +1828,7 @@ static int parse_clock_source_unit(struc kctl =snd_ctl_new1 (&usb_bool_master_control_ctl_ro, cval);if (!kctl) { -kfree (cval); +usb_mixer_elem_info_free (cval);return -ENOMEM ; }
@@ -2089,7 +2094,7 @@ static void build_mixer_unit_ctl(struct kctl =snd_ctl_new1 (&usb_feature_unit_ctl, cval);if (!kctl) {usb_audio_err (state->chip,"cannot malloc kcontrol\n" ); -kfree (cval); +usb_mixer_elem_info_free (cval);return ; } kctl->private_free = snd_usb_mixer_elem_free;
@@ -2487,7 +2492,7 @@ static int build_audio_procunit(struct m kctl =snd_ctl_new1 (&mixer_procunit_ctl, cval);if (!kctl) { -kfree (cval); +usb_mixer_elem_info_free (cval);return -ENOMEM ; } kctl->private_free = snd_usb_mixer_elem_free;
@@ -2625,7 +2630,7 @@ static void usb_mixer_selector_elem_freeif (kctl->private_data) {struct usb_mixer_elem_info *cval = kctl->private_data; num_ins = cval->max; -kfree (cval); +usb_mixer_elem_info_free (cval); kctl->private_data =NULL ; }if (kctl->private_value) {
@@ -2697,10 +2702,10 @@ static int parse_audio_selector_unit(strbreak ; } - namelist =kmalloc_array (desc->bNrInPins,sizeof (char *),GFP_KERNEL ); + namelist =kcalloc (desc->bNrInPins,sizeof (char *),GFP_KERNEL );if (!namelist) { -kfree (cval); -return -ENOMEM ; + err = -ENOMEM ; + goto error_cval; }#define MAX_ITEM_NAME_LEN 64for (i =0 ; i < desc->bNrInPins; i++) {
@@ -2708,11 +2713,8 @@ static int parse_audio_selector_unit(str len =0 ; namelist[i] =kmalloc (MAX_ITEM_NAME_LEN ,GFP_KERNEL );if (!namelist[i]) { -while (i--) -kfree (namelist[i]); -kfree (namelist); -kfree (cval); -return -ENOMEM ; + err = -ENOMEM ; + goto error_name; } len =check_mapped_selector_name (state, unitid, i, namelist[i],MAX_ITEM_NAME_LEN );
@@ -2726,10 +2728,8 @@ static int parse_audio_selector_unit(str kctl =snd_ctl_new1 (&mixer_selectunit_ctl, cval);if (! kctl) {usb_audio_err (state->chip,"cannot malloc kcontrol\n" ); -for (i =0 ; i < desc->bNrInPins; i++) -kfree (namelist[i]); -kfree (namelist); -kfree (cval); + err = -ENOMEM ; + goto error_name;return -ENOMEM ; } kctl->private_value = (unsigned long )namelist;
@@ -2776,6 +2776,14 @@ static int parse_audio_selector_unit(strusb_audio_dbg (state->chip,"[%d] SU [%s] items = %d\n" , cval->head.id, kctl->id.name, desc->bNrInPins);return snd_usb_mixer_add_control (&cval->head, kctl); + + error_name: +for (i =0 ; i < desc->bNrInPins; i++) +kfree (namelist[i]); +kfree (namelist); + error_cval: +usb_mixer_elem_info_free (cval); +return err; }/*
Greg Kroah-Hartman
maintainerPATCH 60/125 ALSA: usb-audio: Remove superfluous bLength checks
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit b8e4f1fdfa422398c2d6c47bfb7d1feb3046d70a upstream.
Now that we got the more comprehensive validation code for USB-audio descriptors, the check of overflow in each descriptor unit parser became superfluous. Drop some of the obvious cases.
--- sound/usb/clock.c | 14 +++------ sound/usb/mixer.c | 84 ------------------------------------------------------ 2 files changed, 6 insertions(+), 92 deletions(-)
sound/usb/clock.c +6 -8
@@ -52,39 +52,37 @@ static void *find_uac_clock_desc(structstatic bool validate_clock_source_v2 (void *p,int id) {struct uac_clock_source_descriptor *cs = p; -return cs->bLength ==sizeof (*cs) && cs->bClockID == id; +return cs->bClockID == id; }static bool validate_clock_source_v3 (void *p,int id) {struct uac3_clock_source_descriptor *cs = p; -return cs->bLength ==sizeof (*cs) && cs->bClockID == id; +return cs->bClockID == id; }static bool validate_clock_selector_v2 (void *p,int id) {struct uac_clock_selector_descriptor *cs = p; -return cs->bLength >=sizeof (*cs) && cs->bClockID == id && - cs->bLength ==7 + cs->bNrInPins; +return cs->bClockID == id; }static bool validate_clock_selector_v3 (void *p,int id) {struct uac3_clock_selector_descriptor *cs = p; -return cs->bLength >=sizeof (*cs) && cs->bClockID == id && - cs->bLength ==11 + cs->bNrInPins; +return cs->bClockID == id; }static bool validate_clock_multiplier_v2 (void *p,int id) {struct uac_clock_multiplier_descriptor *cs = p; -return cs->bLength ==sizeof (*cs) && cs->bClockID == id; +return cs->bClockID == id; }static bool validate_clock_multiplier_v3 (void *p,int id) {struct uac3_clock_multiplier_descriptor *cs = p; -return cs->bLength ==sizeof (*cs) && cs->bClockID == id; +return cs->bClockID == id; }#define DEFINE_FIND_HELPER (name, obj, validator, type) \
sound/usb/mixer.c +0 -84
158 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 61/125 ALSA: usb-audio: Clean up check_input_term()
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit e0ccdef92653f8867e2d1667facfd3c23699f540 upstream.
The primary changes in this patch are cleanups of __check_input_term() and move to a non-nested switch-case block by evaluating the pair of UAC version and the unit type, as we've done for parse_audio_unit(). Also each parser is split into the function for readability.
Now, a slight behavior change by this cleanup is the handling of processing and extension units. Formerly we've dealt with them differently between UAC1/2 and UAC3; the latter returns an error if no input sources are available, while the former continues to parse.
In this patch, unify the behavior in all cases: when input sources are available, it parses recursively, then override the type and the id, as well as channel information if not provided yet.
--- sound/usb/mixer.c | 407 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 212 insertions(+), 195 deletions(-)
sound/usb/mixer.c +212 -195
@@ -773,224 +773,242 @@ static int uac_mixer_unit_get_channels(s }/* -* parse the source unit recursively until it reaches to a terminal -* or a branched unit. +* Parse Input Terminal Unit */ static int __check_input_term (struct mixer_build *state,int id, -struct usb_audio_term *term) +struct usb_audio_term *term); + +static int parse_term_uac1_iterm_unit (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id) +{ +struct uac_input_terminal_descriptor *d = p1; + + term->type =le16_to_cpu (d->wTerminalType); + term->channels = d->bNrChannels; + term->chconfig =le16_to_cpu (d->wChannelConfig); + term->name = d->iTerminal; +return 0 ; +} + +static int parse_term_uac2_iterm_unit (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id) { -int protocol = state->mixer->protocol; +struct uac2_input_terminal_descriptor *d = p1;int err; -void *p1; -unsigned char *hdr; -memset (term,0 ,sizeof (*term)); -for (;;) { -/* a loop in the terminal chain? */ -if (test_and_set_bit (id, state->termbitmap)) -return -EINVAL ; +/* call recursively to verify the referenced clock entity */ + err =__check_input_term (state, d->bCSourceID, term); +if (err <0 ) +return err; - p1 =find_audio_control_unit (state, id); -if (!p1) -break ; -if (!snd_usb_validate_audio_desc (p1, protocol)) -break ;/* bad descriptor */ +/* save input term properties after recursion, +* to ensure they are not overriden by the recursion calls +*/ + term->id = id; + term->type =le16_to_cpu (d->wTerminalType); + term->channels = d->bNrChannels; + term->chconfig =le32_to_cpu (d->bmChannelConfig); + term->name = d->iTerminal; +return 0 ; +} - hdr = p1; - term->id = id; +static int parse_term_uac3_iterm_unit (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id) +{ +struct uac3_input_terminal_descriptor *d = p1; +int err; -if (protocol ==UAC_VERSION_1 || protocol ==UAC_VERSION_2 ) { -switch (hdr[2 ]) { -case UAC_INPUT_TERMINAL : -if (protocol ==UAC_VERSION_1 ) { -struct uac_input_terminal_descriptor *d = p1; - - term->type =le16_to_cpu (d->wTerminalType); - term->channels = d->bNrChannels; - term->chconfig =le16_to_cpu (d->wChannelConfig); - term->name = d->iTerminal; - }else {/* UAC_VERSION_2 */ -struct uac2_input_terminal_descriptor *d = p1; - -/* call recursively to verify that the -* referenced clock entity is valid */ - err =__check_input_term (state, d->bCSourceID, term); -if (err <0 ) -return err; - -/* save input term properties after recursion, -* to ensure they are not overriden by the -* recursion calls */ - term->id = id; - term->type =le16_to_cpu (d->wTerminalType); - term->channels = d->bNrChannels; - term->chconfig =le32_to_cpu (d->bmChannelConfig); - term->name = d->iTerminal; - } -return 0 ; -case UAC_FEATURE_UNIT : { -/* the header is the same for v1 and v2 */ -struct uac_feature_unit_descriptor *d = p1; +/* call recursively to verify the referenced clock entity */ + err =__check_input_term (state, d->bCSourceID, term); +if (err <0 ) +return err; - id = d->bSourceID; -break ;/* continue to parse */ - } -case UAC_MIXER_UNIT : { -struct uac_mixer_unit_descriptor *d = p1; +/* save input term properties after recursion, +* to ensure they are not overriden by the recursion calls +*/ + term->id = id; + term->type =le16_to_cpu (d->wTerminalType); - term->type =UAC3_MIXER_UNIT <<16 ;/* virtual type */ - term->channels =uac_mixer_unit_bNrChannels (d); - term->chconfig =uac_mixer_unit_wChannelConfig (d, protocol); - term->name =uac_mixer_unit_iMixer (d); -return 0 ; - } -case UAC_SELECTOR_UNIT : -case UAC2_CLOCK_SELECTOR : { -struct uac_selector_unit_descriptor *d = p1; -/* call recursively to retrieve the channel info */ - err =__check_input_term (state, d->baSourceID[0 ], term); -if (err <0 ) -return err; - term->type =UAC3_SELECTOR_UNIT <<16 ;/* virtual type */ - term->id = id; - term->name =uac_selector_unit_iSelector (d); -return 0 ; - } -case UAC1_PROCESSING_UNIT : -/* UAC2_EFFECT_UNIT */ -if (protocol ==UAC_VERSION_1 ) - term->type =UAC3_PROCESSING_UNIT <<16 ;/* virtual type */ -else /* UAC_VERSION_2 */ - term->type =UAC3_EFFECT_UNIT <<16 ;/* virtual type */ -/* fall through */ -case UAC1_EXTENSION_UNIT : -/* UAC2_PROCESSING_UNIT_V2 */ -if (protocol ==UAC_VERSION_1 && !term->type) - term->type =UAC3_EXTENSION_UNIT <<16 ;/* virtual type */ -else if (protocol ==UAC_VERSION_2 && !term->type) - term->type =UAC3_PROCESSING_UNIT <<16 ;/* virtual type */ -/* fall through */ -case UAC2_EXTENSION_UNIT_V2 : { -struct uac_processing_unit_descriptor *d = p1; - -if (protocol ==UAC_VERSION_2 && - hdr[2 ] ==UAC2_EFFECT_UNIT ) { -/* UAC2/UAC1 unit IDs overlap here in an -* uncompatible way. Ignore this unit for now. -*/ -return 0 ; - } + err =get_cluster_channels_v3 (state,le16_to_cpu (d->wClusterDescrID)); +if (err <0 ) +return err; + term->channels = err; -if (d->bNrInPins) { - id = d->baSourceID[0 ]; -break ;/* continue to parse */ - } -if (!term->type) - term->type =UAC3_EXTENSION_UNIT <<16 ;/* virtual type */ +/* REVISIT: UAC3 IT doesn't have channels cfg */ + term->chconfig =0 ; - term->channels =uac_processing_unit_bNrChannels (d); - term->chconfig =uac_processing_unit_wChannelConfig (d, protocol); - term->name =uac_processing_unit_iProcessing (d, protocol); -return 0 ; - } -case UAC2_CLOCK_SOURCE : { -struct uac_clock_source_descriptor *d = p1; + term->name =le16_to_cpu (d->wTerminalDescrStr); +return 0 ; +} - term->type =UAC3_CLOCK_SOURCE <<16 ;/* virtual type */ - term->id = id; - term->name = d->iClockSource; -return 0 ; - } -default : -return -ENODEV ; - } - }else {/* UAC_VERSION_3 */ -switch (hdr[2 ]) { -case UAC_INPUT_TERMINAL : { -struct uac3_input_terminal_descriptor *d = p1; - -/* call recursively to verify that the -* referenced clock entity is valid */ - err =__check_input_term (state, d->bCSourceID, term); -if (err <0 ) -return err; - -/* save input term properties after recursion, -* to ensure they are not overriden by the -* recursion calls */ - term->id = id; - term->type =le16_to_cpu (d->wTerminalType); - - err =get_cluster_channels_v3 (state,le16_to_cpu (d->wClusterDescrID)); -if (err <0 ) -return err; - term->channels = err; +static int parse_term_mixer_unit (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id) +{ +struct uac_mixer_unit_descriptor *d = p1; +int protocol = state->mixer->protocol; +int err; -/* REVISIT: UAC3 IT doesn't have channels cfg */ - term->chconfig =0 ; + err =uac_mixer_unit_get_channels (state, d); +if (err <=0 ) +return err; - term->name =le16_to_cpu (d->wTerminalDescrStr); -return 0 ; - } -case UAC3_FEATURE_UNIT : { -struct uac3_feature_unit_descriptor *d = p1; + term->type =UAC3_MIXER_UNIT <<16 ;/* virtual type */ + term->channels = err; +if (protocol !=UAC_VERSION_3 ) { + term->chconfig =uac_mixer_unit_wChannelConfig (d, protocol); + term->name =uac_mixer_unit_iMixer (d); + } +return 0 ; +} - id = d->bSourceID; -break ;/* continue to parse */ - } -case UAC3_CLOCK_SOURCE : { -struct uac3_clock_source_descriptor *d = p1; +static int parse_term_selector_unit (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id) +{ +struct uac_selector_unit_descriptor *d = p1; +int err; - term->type =UAC3_CLOCK_SOURCE <<16 ;/* virtual type */ - term->id = id; - term->name =le16_to_cpu (d->wClockSourceStr); -return 0 ; - } -case UAC3_MIXER_UNIT : { -struct uac_mixer_unit_descriptor *d = p1; +/* call recursively to retrieve the channel info */ + err =__check_input_term (state, d->baSourceID[0 ], term); +if (err <0 ) +return err; + term->type =UAC3_SELECTOR_UNIT <<16 ;/* virtual type */ + term->id = id; +if (state->mixer->protocol !=UAC_VERSION_3 ) + term->name =uac_selector_unit_iSelector (d); +return 0 ; +} - err =uac_mixer_unit_get_channels (state, d); -if (err <=0 ) -return err; +static int parse_term_proc_unit (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id,int vtype) +{ +struct uac_processing_unit_descriptor *d = p1; +int protocol = state->mixer->protocol; +int err; - term->channels = err; - term->type =UAC3_MIXER_UNIT <<16 ;/* virtual type */ +if (d->bNrInPins) { +/* call recursively to retrieve the channel info */ + err =__check_input_term (state, d->baSourceID[0 ], term); +if (err <0 ) +return err; + } -return 0 ; - } -case UAC3_SELECTOR_UNIT : -case UAC3_CLOCK_SELECTOR : { -struct uac_selector_unit_descriptor *d = p1; -/* call recursively to retrieve the channel info */ - err =__check_input_term (state, d->baSourceID[0 ], term); -if (err <0 ) -return err; - term->type =UAC3_SELECTOR_UNIT <<16 ;/* virtual type */ - term->id = id; - term->name =0 ;/* TODO: UAC3 Class-specific strings */ + term->type = vtype <<16 ;/* virtual type */ + term->id = id; -return 0 ; - } -case UAC3_PROCESSING_UNIT : { -struct uac_processing_unit_descriptor *d = p1; +if (protocol ==UAC_VERSION_3 ) +return 0 ; -if (!d->bNrInPins) -return -EINVAL ; +if (!term->channels) { + term->channels =uac_processing_unit_bNrChannels (d); + term->chconfig =uac_processing_unit_wChannelConfig (d, protocol); + } + term->name =uac_processing_unit_iProcessing (d, protocol); +return 0 ; +} + +static int parse_term_uac2_clock_source (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id) +{ +struct uac_clock_source_descriptor *d = p1; + + term->type =UAC3_CLOCK_SOURCE <<16 ;/* virtual type */ + term->id = id; + term->name = d->iClockSource; +return 0 ; +} -/* call recursively to retrieve the channel info */ - err =__check_input_term (state, d->baSourceID[0 ], term); -if (err <0 ) -return err; - - term->type =UAC3_PROCESSING_UNIT <<16 ;/* virtual type */ - term->id = id; - term->name =0 ;/* TODO: UAC3 Class-specific strings */ +static int parse_term_uac3_clock_source (struct mixer_build *state, +struct usb_audio_term *term, +void *p1,int id) +{ +struct uac3_clock_source_descriptor *d = p1; + + term->type =UAC3_CLOCK_SOURCE <<16 ;/* virtual type */ + term->id = id; + term->name =le16_to_cpu (d->wClockSourceStr); +return 0 ; +} -return 0 ; - } -default : -return -ENODEV ; - } +#define PTYPE (a, b) ((a) << 8 | (b)) + +/* +* parse the source unit recursively until it reaches to a terminal +* or a branched unit. +*/ +static int __check_input_term (struct mixer_build *state,int id, +struct usb_audio_term *term) +{ +int protocol = state->mixer->protocol; +void *p1; +unsigned char *hdr; + +for (;;) { +/* a loop in the terminal chain? */ +if (test_and_set_bit (id, state->termbitmap)) +return -EINVAL ; + + p1 =find_audio_control_unit (state, id); +if (!p1) +break ; +if (!snd_usb_validate_audio_desc (p1, protocol)) +break ;/* bad descriptor */ + + hdr = p1; + term->id = id; + +switch (PTYPE (protocol, hdr[2 ])) { +case PTYPE (UAC_VERSION_1 ,UAC_FEATURE_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC_FEATURE_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_FEATURE_UNIT ): { +/* the header is the same for all versions */ +struct uac_feature_unit_descriptor *d = p1; + + id = d->bSourceID; +break ;/* continue to parse */ + } +case PTYPE (UAC_VERSION_1 ,UAC_INPUT_TERMINAL ): +return parse_term_uac1_iterm_unit (state, term, p1, id); +case PTYPE (UAC_VERSION_2 ,UAC_INPUT_TERMINAL ): +return parse_term_uac2_iterm_unit (state, term, p1, id); +case PTYPE (UAC_VERSION_3 ,UAC_INPUT_TERMINAL ): +return parse_term_uac3_iterm_unit (state, term, p1, id); +case PTYPE (UAC_VERSION_1 ,UAC_MIXER_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC_MIXER_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_MIXER_UNIT ): +return parse_term_mixer_unit (state, term, p1, id); +case PTYPE (UAC_VERSION_1 ,UAC_SELECTOR_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC_SELECTOR_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC2_CLOCK_SELECTOR ): +case PTYPE (UAC_VERSION_3 ,UAC3_SELECTOR_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_CLOCK_SELECTOR ): +return parse_term_selector_unit (state, term, p1, id); +case PTYPE (UAC_VERSION_1 ,UAC1_PROCESSING_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC2_PROCESSING_UNIT_V2 ): +case PTYPE (UAC_VERSION_3 ,UAC3_PROCESSING_UNIT ): +return parse_term_proc_unit (state, term, p1, id, +UAC3_PROCESSING_UNIT ); +case PTYPE (UAC_VERSION_2 ,UAC2_EFFECT_UNIT ): +case PTYPE (UAC_VERSION_3 ,UAC3_EFFECT_UNIT ): +return parse_term_proc_unit (state, term, p1, id, +UAC3_EFFECT_UNIT ); +case PTYPE (UAC_VERSION_1 ,UAC1_EXTENSION_UNIT ): +case PTYPE (UAC_VERSION_2 ,UAC2_EXTENSION_UNIT_V2 ): +case PTYPE (UAC_VERSION_3 ,UAC3_EXTENSION_UNIT ): +return parse_term_proc_unit (state, term, p1, id, +UAC3_EXTENSION_UNIT ); +case PTYPE (UAC_VERSION_2 ,UAC2_CLOCK_SOURCE ): +return parse_term_uac2_clock_source (state, term, p1, id); +case PTYPE (UAC_VERSION_3 ,UAC3_CLOCK_SOURCE ): +return parse_term_uac3_clock_source (state, term, p1, id); +default : +return -ENODEV ; } }return -ENODEV ;
@@ -2731,7 +2749,6 @@ static int parse_audio_unit(struct mixerreturn 0 ;/* skip invalid unit */ } -#define PTYPE (a, b) ((a) << 8 | (b))switch (PTYPE (protocol, p1[2 ])) {case PTYPE (UAC_VERSION_1 ,UAC_INPUT_TERMINAL ):case PTYPE (UAC_VERSION_2 ,UAC_INPUT_TERMINAL ):
Greg Kroah-Hartman
maintainerPATCH 62/125 ALSA: usb-audio: Fix possible NULL dereference at create_yamaha_midi_quirk()
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit 60849562a5db4a1eee2160167e4dce4590d3eafe upstream.
The previous addition of descriptor validation may lead to a NULL dereference at create_yamaha_midi_quirk() when either injd or outjd is NULL. Add proper non-NULL checks.
--- sound/usb/quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/usb/quirks.c +2 -2
@@ -259,8 +259,8 @@ static int create_yamaha_midi_quirk(stru NULL, USB_MS_MIDI_OUT_JACK);if (!injd && !outjd)return -ENODEV ; -if (!snd_usb_validate_midi_desc (injd) || - !snd_usb_validate_midi_desc (outjd)) +if (!(injd &&snd_usb_validate_midi_desc (injd)) || + !(outjd &&snd_usb_validate_midi_desc (outjd)))return -ENODEV ; if (injd && (injd->bLength < 5 || (injd->bJackType != USB_MS_EMBEDDED &&
Re: [PATCH 4.19 062/125] ALSA: usb-audio: Fix possible NULL dereference at create_yamaha_midi_quirk()
Hi!
Quoted 7 lines
From: Takashi Iwai <[email protected]>
commit
60849562a5db4a1eee2160167e4dce4590d3eafeupstream.The previous addition of descriptor validation may lead to a NULL dereference at
create_yamaha_midi_quirk()when either injd or outjd is NULL. Add proper non-NULL checks.
This is wrong.
sound/usb/quirks.c static int create_yamaha_midi_quirk(stru · line 261
Quoted 4 lines
sound/usb/quirks.c +0
-0@@ -259,8 +259,8 @@ static int create_yamaha_midi_quirk(stru NULL, USB_MS_MIDI_OUT_JACK);if (!injd && !outjd)return -ENODEV ;
Clearly code wants to allow at most one of them to be NULL.
sound/usb/quirks.c static int create_yamaha_midi_quirk(stru · line 264
Quoted 5 lines
sound/usb/quirks.c +2
-2-if (!snd_usb_validate_midi_desc (injd) || - !snd_usb_validate_midi_desc (outjd)) +if (!(injd &&snd_usb_validate_midi_desc (injd)) || + !(outjd &&snd_usb_validate_midi_desc (outjd)))return -ENODEV ;
Yet it will return here if it is. Correct check would be
+ if (!(!injd || snd_usb_validate_midi_desc(injd)) ||
+ !(!outjd || snd_usb_validate_midi_desc(outjd)))
AFAICT.
Best regards,
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 4.19 062/125] ALSA: usb-audio: Fix possible NULL dereference at create_yamaha_midi_quirk()
Quoted 31 lines · Pavel Machek
Hi!
Quoted 7 lines
From: Takashi Iwai <[email protected]>
commit
60849562a5db4a1eee2160167e4dce4590d3eafeupstream.The previous addition of descriptor validation may lead to a NULL dereference at
create_yamaha_midi_quirk()when either injd or outjd is NULL. Add proper non-NULL checks.This is wrong.
sound/usb/quirks.c static int create_yamaha_midi_quirk(stru · line 261
Quoted 4 lines
sound/usb/quirks.c +0
-0@@ -259,8 +259,8 @@ static int create_yamaha_midi_quirk(stru NULL, USB_MS_MIDI_OUT_JACK);if (!injd && !outjd)return -ENODEV ;Clearly code wants to allow at most one of them to be NULL.
sound/usb/quirks.c static int create_yamaha_midi_quirk(stru · line 264
Quoted 5 lines
sound/usb/quirks.c +2
-2-if (!snd_usb_validate_midi_desc (injd) || - !snd_usb_validate_midi_desc (outjd)) +if (!(injd &&snd_usb_validate_midi_desc (injd)) || + !(outjd &&snd_usb_validate_midi_desc (outjd)))return -ENODEV ;Yet it will return here if it is. Correct check would be
(quoted diff) +2
-0+ if (!(!injd || snd_usb_validate_midi_desc(injd)) || + !(!outjd || snd_usb_validate_midi_desc(outjd)))
Quoted 1 line
AFAICT.
Erm, right, but a better representation is:
if ((injd && !snd_usb_validate_midi_desc(injd)) || (outjd && !snd_usb_validate_midi_desc(injd)))
thanks,
Takashi
Re: [PATCH 4.19 062/125] ALSA: usb-audio: Fix possible NULL dereference at create_yamaha_midi_quirk()
Quoted 34 lines · Takashi Iwai
Quoted 31 lines · Pavel Machek
Hi!
Quoted 7 lines
From: Takashi Iwai <[email protected]>
commit
60849562a5db4a1eee2160167e4dce4590d3eafeupstream.The previous addition of descriptor validation may lead to a NULL dereference at
create_yamaha_midi_quirk()when either injd or outjd is NULL. Add proper non-NULL checks.This is wrong.
sound/usb/quirks.c static int create_yamaha_midi_quirk(stru · line 261
Quoted 4 lines
sound/usb/quirks.c +0
-0@@ -259,8 +259,8 @@ static int create_yamaha_midi_quirk(stru NULL, USB_MS_MIDI_OUT_JACK);if (!injd && !outjd)return -ENODEV ;Clearly code wants to allow at most one of them to be NULL.
sound/usb/quirks.c static int create_yamaha_midi_quirk(stru · line 264
Quoted 5 lines
sound/usb/quirks.c +2
-2-if (!snd_usb_validate_midi_desc (injd) || - !snd_usb_validate_midi_desc (outjd)) +if (!(injd &&snd_usb_validate_midi_desc (injd)) || + !(outjd &&snd_usb_validate_midi_desc (outjd)))return -ENODEV ;Yet it will return here if it is. Correct check would be
(quoted diff) +2
-0+ if (!(!injd || snd_usb_validate_midi_desc(injd)) || + !(!outjd || snd_usb_validate_midi_desc(outjd)))
Quoted 6 lines
Quoted 1 line
AFAICT.
Erm, right, but a better representation is:
if ((injd && !snd_usb_validate_midi_desc(injd)) || (outjd && !snd_usb_validate_midi_desc(injd)))
Of course, another typo:
if ((injd && !snd_usb_validate_midi_desc(injd)) ||
(outjd && !snd_usb_validate_midi_desc(outjd)))
Takashi
Re: [PATCH 4.19 062/125] ALSA: usb-audio: Fix possible NULL dereference at create_yamaha_midi_quirk()
Hi!
Quoted 22 lines
Quoted 13 lines
Quoted 13 lines
Clearly code wants to allow at most one of them to be NULL.
sound/usb/quirks.c static int create_yamaha_midi_quirk(stru · line 264
Quoted 5 lines
sound/usb/quirks.c +2
-2-if (!snd_usb_validate_midi_desc (injd) || - !snd_usb_validate_midi_desc (outjd)) +if (!(injd &&snd_usb_validate_midi_desc (injd)) || + !(outjd &&snd_usb_validate_midi_desc (outjd)))return -ENODEV ;Yet it will return here if it is. Correct check would be
(quoted diff) +2
-0+ if (!(!injd || snd_usb_validate_midi_desc(injd)) || + !(!outjd || snd_usb_validate_midi_desc(outjd)))Quoted 6 lines
Quoted 1 line
AFAICT.
Erm, right, but a better representation is:
if ((injd && !snd_usb_validate_midi_desc(injd)) || (outjd && !snd_usb_validate_midi_desc(injd)))Of course, another typo:
Review
Quoted 2 lines
(quoted diff) +0
-0if ((injd && !snd_usb_validate_midi_desc(injd)) || (outjd && !snd_usb_validate_midi_desc(outjd)))
Agreed, that is better. I was focusing on boolean algebra too much.
Best regards,
Pavel
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Greg Kroah-Hartman
maintainerPATCH 63/125 ALSA: usb-audio: remove some dead code
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit b39e077fcb283dd96dd251a3abeba585402c61fe upstream.
We recently cleaned up the error handling in commit 52c3e317a857 ("ALSA:
usb-audio: Unify the release of usb_mixer_elem_info objects") but accidentally left this stray return.
--- sound/usb/mixer.c | 1 - 1 file changed, 1 deletion(-)
sound/usb/mixer.c +0 -1
@@ -2670,7 +2670,6 @@ static int parse_audio_selector_unit(strusb_audio_err (state->chip,"cannot malloc kcontrol\n" ); err = -ENOMEM ; goto error_name; -return -ENOMEM ; } kctl->private_value = (unsigned long )namelist; kctl->private_free = usb_mixer_selector_elem_free;
Greg Kroah-Hartman
maintainerPATCH 64/125 ALSA: usb-audio: Fix copy&paste error in the validator
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
commit ba8bf0967a154796be15c4983603aad0b05c3138 upstream.
The recently introduced USB-audio descriptor validator had a stupid copy&paste error that may lead to an unexpected overlook of too short descriptors for processing and extension units. It's likely the cause of the report triggered by syzkaller fuzzer. Let's fix it.
--- sound/usb/validate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/usb/validate.c +1 -1
@@ -75,7 +75,7 @@ static bool validate_processing_unit(conif (d->bLength <sizeof (*d))return false; - len = d->bLength <sizeof (*d) + d->bNrInPins; + len =sizeof (*d) + d->bNrInPins;if (d->bLength < len)return false;switch (v->protocol) {
Greg Kroah-Hartman
maintainerPATCH 65/125 sched/fair: Fix low cpu usage with high throttling by removing expiration of cpu-local slices
In reply to Greg Kroah-HartmanFrom: Dave Chiluk <[email protected]>
commit de53fd7aedb100f03e5d2231cfce0e4993282425 upstream.
It has been observed, that highly-threaded, non-cpu-bound applications running under cpu.cfs_quota_us constraints can hit a high percentage of periods throttled while simultaneously not consuming the allocated amount of quota. This use case is typical of user-interactive non-cpu bound applications, such as those running in kubernetes or mesos when run on multiple cpu cores.
This has been root caused to cpu-local run queue being allocated per cpu bandwidth slices, and then not fully using that slice within the period. At which point the slice and quota expires. This expiration of unused slice results in applications not being able to utilize the quota for which they are allocated.
The non-expiration of per-cpu slices was recently fixed by 'commit 512ac999d275 ("sched/fair: Fix bandwidth timer clock drift condition")'. Prior to that it appears that this had been broken since at least 'commit 51f2176d74ac ("sched/fair: Fix unlocked reads of some cfs_b->quota/period")' which was introduced in v3.16-rc1 in 2014. That added the following conditional which resulted in slices never being expired.
if (cfs_rq->runtime_expires != cfs_b->runtime_expires) {
/* extend local deadline, drift is bounded above by 2 ticks */
cfs_rq->runtime_expires += TICK_NSEC;Because this was broken for nearly 5 years, and has recently been fixed and is now being noticed by many users running kubernetes
(https://github.com/kubernetes/kubernetes/issues/67577) it is my opinion that the mechanisms around expiring runtime should be removed altogether.
This allows quota already allocated to per-cpu run-queues to live longer than the period boundary. This allows threads on runqueues that do not use much CPU to continue to use their remaining slice over a longer period of time than cpu.cfs_period_us. However, this helps prevent the above condition of hitting throttling while also not fully utilizing your cpu quota.
This theoretically allows a machine to use slightly more than its allotted quota in some periods. This overflow would be bounded by the remaining quota left on each per-cpu runqueueu. This is typically no more than min_cfs_rq_runtime=1ms per cpu. For CPU bound tasks this will change nothing, as they should theoretically fully utilize all of their quota in each period. For user-interactive tasks as described above this provides a much better user/application experience as their cpu utilization will more closely match the amount they requested when they hit throttling. This means that cpu limits no longer strictly apply per period for non-cpu bound applications, but that they are still accurate over longer timeframes.
This greatly improves performance of high-thread-count, non-cpu bound applications with low cfs_quota_us allocation on high-core-count machines. In the case of an artificial testcase (10ms/100ms of quota on 80 CPU machine), this commit resulted in almost 30x performance improvement, while still maintaining correct cpu quota restrictions. That testcase is available at https://github.com/indeedeng/fibtest.
--- Documentation/scheduler/sched-bwc.txt | 45 +++++++++++++++++++++ kernel/sched/fair.c | 72 +++------------------------------- kernel/sched/sched.h | 4 - 3 files changed, 52 insertions(+), 69 deletions(-)
Documentation/scheduler/sched-bwc.txt +45 -0
@@ -90,6 +90,51 @@ There are two ways in which a group may In case b) above, even though the child may have runtime remaining it will not be allowed to until the parent's runtime is refreshed. +CFS Bandwidth Quota Caveats +--------------------------- +Once a slice is assigned to a cpu it does not expire. However all but 1ms of +the slice may be returned to the global pool if all threads on that cpu become +unrunnable. This is configured at compile time by the min_cfs_rq_runtime +variable. This is a performance tweak that helps prevent added contention on +the global lock. + +The fact that cpu-local slices do not expire results in some interesting corner +cases that should be understood. + +For cgroup cpu constrained applications that are cpu limited this is a +relatively moot point because they will naturally consume the entirety of their +quota as well as the entirety of each cpu-local slice in each period. As a +result it is expected that nr_periods roughly equal nr_throttled, and that +cpuacct.usage will increase roughly equal to cfs_quota_us in each period. + +For highly-threaded, non-cpu bound applications this non-expiration nuance +allows applications to briefly burst past their quota limits by the amount of +unused slice on each cpu that the task group is running on (typically at most +1ms per cpu or as defined by min_cfs_rq_runtime). This slight burst only +applies if quota had been assigned to a cpu and then not fully used or returned +in previous periods. This burst amount will not be transferred between cores. +As a result, this mechanism still strictly limits the task group to quota +average usage, albeit over a longer time window than a single period. This +also limits the burst ability to no more than 1ms per cpu. This provides +better more predictable user experience for highly threaded applications with +small quota limits on high core count machines. It also eliminates the +propensity to throttle these applications while simultanously using less than +quota amounts of cpu. Another way to say this, is that by allowing the unused +portion of a slice to remain valid across periods we have decreased the +possibility of wastefully expiring quota on cpu-local silos that don't need a +full slice's amount of cpu time. + +The interaction between cpu-bound and non-cpu-bound-interactive applications +should also be considered, especially when single core usage hits 100%. If you +gave each of these applications half of a cpu-core and they both got scheduled +on the same CPU it is theoretically possible that the non-cpu bound application +will use up to 1ms additional quota in some periods, thereby preventing the +cpu-bound application from fully using its quota by that same amount. In these +instances it will be up to the CFS algorithm (see sched-design-CFS.rst) to +decide which application is chosen to run, as they will both be runnable and +have remaining quota. This runtime discrepancy will be made up in the following +periods when the interactive application idles. + Examples -------- 1. Limit a group to 1 CPU worth of runtime.
kernel/sched/fair.c +7 -65
163 lines not on this page · raw message
kernel/sched/sched.h +0 -4
@@ -334,8 +334,6 @@ struct cfs_bandwidth {u64 quota;u64 runtime;s64 hierarchical_quota; -u64 runtime_expires; -int expires_seq;short idle;short period_active;
@@ -555,8 +553,6 @@ struct cfs_rq {#ifdef CONFIG_CFS_BANDWIDTH int runtime_enabled; -int expires_seq; -u64 runtime_expires;s64 runtime_remaining;u64 throttled_clock;
Greg Kroah-Hartman
maintainerPATCH 66/125 sched/fair: Fix -Wunused-but-set-variable warnings
In reply to Greg Kroah-HartmanFrom: Qian Cai <[email protected]>
commit 763a9ec06c409dcde2a761aac4bb83ff3938e0b3 upstream.
Commit:
de53fd7aedb1 ("sched/fair: Fix low cpu usage with high throttling by removing expiration of cpu-local slices")
introduced a few compilation warnings:
kernel/sched/fair.c: In function '__refill_cfs_bandwidth_runtime':
kernel/sched/fair.c:4365:6: warning: variable 'now' set but not used [-Wunused-but-set-variable] kernel/sched/fair.c: In function 'start_cfs_bandwidth':
kernel/sched/fair.c:4992:6: warning: variable 'overrun' set but not used [-Wunused-but-set-variable]
Also, __refill_cfs_bandwidth_runtime() does no longer update the expiration time, so fix the comments accordingly.
--- kernel/sched/fair.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-)
kernel/sched/fair.c +6 -13
@@ -4305,21 +4305,16 @@ static inline u64 sched_cfs_bandwidth_sl }/* -* Replenish runtime according to assigned quota and update expiration time. -* We use sched_clock_cpu directly instead of rq->clock to avoid adding -* additional synchronization around rq->lock. +* Replenish runtime according to assigned quota. We use sched_clock_cpu +* directly instead of rq->clock to avoid adding additional synchronization +* around rq->lock. * * requires cfs_b->lock */ void __refill_cfs_bandwidth_runtime (struct cfs_bandwidth *cfs_b) { -u64 now; - -if (cfs_b->quota ==RUNTIME_INF ) -return ; - - now =sched_clock_cpu (smp_processor_id ()); - cfs_b->runtime = cfs_b->quota; +if (cfs_b->quota !=RUNTIME_INF ) + cfs_b->runtime = cfs_b->quota; }static inline struct cfs_bandwidth *tg_cfs_bandwidth (struct task_group *tg)
@@ -4924,15 +4919,13 @@ static void init_cfs_rq_runtime(struct cvoid start_cfs_bandwidth (struct cfs_bandwidth *cfs_b) { -u64 overrun; -lockdep_assert_held (&cfs_b->lock);if (cfs_b->period_active)return ; cfs_b->period_active =1 ; - overrun =hrtimer_forward_now (&cfs_b->period_timer, cfs_b->period); +hrtimer_forward_now (&cfs_b->period_timer, cfs_b->period);hrtimer_start_expires (&cfs_b->period_timer,HRTIMER_MODE_ABS_PINNED ); }
Greg Kroah-Hartman
maintainerPATCH 67/125 usbip: Fix vhci_urb_enqueue() URB null transfer buffer error path
In reply to Greg Kroah-HartmanFrom: Shuah Khan <[email protected]>
commit 2c904963b1dd2acd4bc785b6c72e10a6283c2081 upstream.
Fix vhci_urb_enqueue() to print debug msg and return error instead of failing with BUG_ON.
--- drivers/usb/usbip/vhci_hcd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/usb/usbip/vhci_hcd.c +4 -2
@@ -702,8 +702,10 @@ static int vhci_urb_enqueue(struct usb_h } vdev = &vhci_hcd->vdev[portnum-1 ]; -/* patch to usb_sg_init() is in 2.5.60 */ -BUG_ON (!urb->transfer_buffer && urb->transfer_buffer_length); +if (!urb->transfer_buffer && urb->transfer_buffer_length) { +dev_dbg (dev,"Null URB transfer buffer\n" ); +return -EINVAL ; + }spin_lock_irqsave (&vhci->lock, flags);
Greg Kroah-Hartman
maintainerPATCH 68/125 usbip: Implement SG support to vhci-hcd and stub driver
In reply to Greg Kroah-HartmanFrom: Suwan Kim <[email protected]>
commit ea44d190764b4422af4d1c29eaeb9e69e353b406 upstream.
There are bugs on vhci with usb 3.0 storage device. In USB, each SG list entry buffer should be divisible by the bulk max packet size. But with native SG support, this problem doesn't matter because the SG buffer is treated as contiguous buffer. But without native SG support, USB storage driver breaks SG list into several URBs and the error occurs because of a buffer size of URB that cannot be divided by the bulk max packet size. The error situation is as follows.
When USB Storage driver requests 31.5 KB data and has SG list which has 3584 bytes buffer followed by 7 4096 bytes buffer for some reason. USB Storage driver splits this SG list into several URBs because VHCI doesn't support SG and sends them separately. So the first URB buffer size is 3584 bytes. When receiving data from device, USB 3.0 device sends data packet of 1024 bytes size because the max packet size of BULK pipe is 1024 bytes. So device sends 4096 bytes. But the first URB buffer has only 3584 bytes buffer size. So host controller terminates the transfer even though there is more data to receive. So, vhci needs to support SG transfer to prevent this error.
In this patch, vhci supports SG regardless of whether the server's host controller supports SG or not, because stub driver splits SG list into several URBs if the server's host controller doesn't support SG.
To support SG, vhci sets URB_DMA_MAP_SG flag in urb->transfer_flags if URB has SG list and this flag will tell stub driver to use SG list. After receiving urb from stub driver, vhci clear URB_DMA_MAP_SG flag to avoid unnecessary DMA unmapping in HCD.
vhci sends each SG list entry to stub driver. Then, stub driver sees the total length of the buffer and allocates SG table and pages according to the total buffer length calling sgl_alloc(). After stub driver receives completed URB, it again sends each SG list entry to vhci.
If the server's host controller doesn't support SG, stub driver breaks a single SG request into several URBs and submits them to the server's host controller. When all the split URBs are completed, stub driver reassembles the URBs into a single return command and sends it to vhci.
Moreover, in the situation where vhci supports SG, but stub driver does not, or vice versa, usbip works normally. Because there is no protocol modification, there is no problem in communication between server and client even if the one has a kernel without SG support.
In the case of vhci supports SG and stub driver doesn't, because vhci sends only the total length of the buffer to stub driver as it did before the patch applied, stub driver only needs to allocate the required length of buffers using only kmalloc() regardless of whether vhci supports SG or not. But stub driver has to allocate buffer with kmalloc() as much as the total length of SG buffer which is quite huge when vhci sends SG request, so it has overhead in buffer allocation in this situation.
If stub driver needs to send data buffer to vhci because of IN pipe, stub driver also sends only total length of buffer as metadata and then sends real data as vhci does. Then vhci receive data from stub driver and store it to the corresponding buffer of SG list entry.
And for the case of stub driver supports SG and vhci doesn't, since the USB storage driver checks that vhci doesn't support SG and sends the request to stub driver by splitting the SG list into multiple URBs, stub driver allocates a buffer for each URB with kmalloc() as it did before this patch.
* Test environment
Test uses two difference machines and two different kernel version to make mismatch situation between the client and the server where vhci supports SG, but stub driver does not, or vice versa. All tests are conducted in both full SG support that both vhci and stub support SG and half SG support that is the mismatch situation. Test kernel version is 5.3-rc6 with commit "usb: add a HCD_DMA flag instead of guestimating DMA capabilities" to avoid unnecessary DMA mapping and unmapping.
- Test kernel version
- 5.3-rc6 with SG support
- 5.1.20-200.fc29.x86_64 without SG support
* SG support test
- Test devices
- Super-speed storage device - SanDisk Ultra USB 3.0
- High-speed storage device - SMI corporation USB 2.0 flash drive
- Test description
Test read and write operation of mass storage device that uses the BULK transfer. In test, the client reads and writes files whose size is over 1G and it works normally.
* Regression test
- Test devices
- Super-speed device - Logitech Brio webcam
- High-speed device - Logitech C920 HD Pro webcam
- Full-speed device - Logitech bluetooth mouse
- Britz BR-Orion speaker
- Low-speed device - Logitech wired mouse
- Test description
Moving and click test for mouse. To test the webcam, use gnome-cheese. To test the speaker, play music and video on the client. All works normally.
* VUDC compatibility test
VUDC also works well with this patch. Tests are done with two USB gadget created by CONFIGFS USB gadget. Both use the BULK pipe.
1. Serial gadget
2. Mass storage gadget
- Serial gadget test
Serial gadget on the host sends and receives data using cat command on the /dev/ttyGS<N>. The client uses minicom to communicate with the serial gadget.
- Mass storage gadget test
After connecting the gadget with vhci, use "dd" to test read and write operation on the client side.
Read - dd if=/dev/sd<N> iflag=direct of=/dev/null bs=1G count=1 Write - dd if=<my file path> iflag=direct of=/dev/sd<N> bs=1G count=1
--- drivers/usb/usbip/stub.h | 7 + drivers/usb/usbip/stub_main.c | 57 ++++++++--- drivers/usb/usbip/stub_rx.c | 202 +++++++++++++++++++++++++++------------ drivers/usb/usbip/stub_tx.c | 99 ++++++++++++++----- drivers/usb/usbip/usbip_common.c | 59 +++++++---- drivers/usb/usbip/vhci_hcd.c | 12 ++ drivers/usb/usbip/vhci_rx.c | 3 drivers/usb/usbip/vhci_tx.c | 66 ++++++++++-- 8 files changed, 379 insertions(+), 126 deletions(-)
drivers/usb/usbip/stub.h +6 -1
@@ -52,7 +52,11 @@ struct stub_priv {unsigned long seqnum;struct list_head list;struct stub_device *sdev; -struct urb *urb; +struct urb **urbs; +struct scatterlist *sgl; +int num_urbs; +int completed_urbs; +int urb_status;int unlinking; };
@@ -86,6 +90,7 @@ extern struct usb_device_driver stub_dristruct bus_id_priv *get_busid_priv (const char *busid);void put_busid_priv (struct bus_id_priv *bid);int del_match_busid (char *busid); +void stub_free_priv_and_urb (struct stub_priv *priv);void stub_device_cleanup_urbs (struct stub_device *sdev);/* stub_rx.c */
drivers/usb/usbip/stub_main.c +42 -15
86 lines not on this page · raw message
drivers/usb/usbip/stub_rx.c +145 -57
260 lines not on this page · raw message
drivers/usb/usbip/stub_tx.c +77 -22
150 lines not on this page · raw message
drivers/usb/usbip/usbip_common.c +41 -18
78 lines not on this page · raw message
drivers/usb/usbip/vhci_hcd.c +11 -1
@@ -702,7 +702,8 @@ static int vhci_urb_enqueue(struct usb_h } vdev = &vhci_hcd->vdev[portnum-1 ]; -if (!urb->transfer_buffer && urb->transfer_buffer_length) { +if (!urb->transfer_buffer && !urb->num_sgs && + urb->transfer_buffer_length) {dev_dbg (dev,"Null URB transfer buffer\n" );return -EINVAL ; }
@@ -1148,6 +1149,15 @@ static int vhci_setup(struct usb_hcd *hc hcd->speed =HCD_USB3 ; hcd->self.root_hub->speed =USB_SPEED_SUPER ; } + +/* +* Support SG. +* sg_tablesize is an arbitrary value to alleviate memory pressure +* on the host. +*/ + hcd->self.sg_tablesize =32 ; + hcd->self.no_sg_constraint =1 ; +return 0 ; }
drivers/usb/usbip/vhci_rx.c +3 -0
@@ -90,6 +90,9 @@ static void vhci_recv_ret_submit(structif (usbip_dbg_flag_vhci_rx)usbip_dump_urb (urb); +if (urb->num_sgs) + urb->transfer_flags &= ~URB_DMA_MAP_SG ; +usbip_dbg_vhci_rx ("now giveback urb %u\n" , pdu->base.seqnum);spin_lock_irqsave (&vhci->lock, flags);
drivers/usb/usbip/vhci_tx.c +54 -12
126 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 69/125 PCI: tegra: Enable Relaxed Ordering only for Tegra20 & Tegra30
In reply to Greg Kroah-HartmanFrom: Vidya Sagar <[email protected]>
commit 7be142caabc4780b13a522c485abc806de5c4114 upstream.
The PCI Tegra controller conversion to a device tree configurable driver in commit d1523b52bff3 ("PCI: tegra: Move PCIe driver to drivers/pci/host") implied that code for the driver can be compiled in for a kernel supporting multiple platforms.
Unfortunately, a blind move of the code did not check that some of the quirks that were applied in arch/arm (eg enabling Relaxed Ordering on all PCI devices - since the quirk hook erroneously matches PCI_ANY_ID for both Vendor-ID and Device-ID) are now applied in all kernels that compile the PCI Tegra controlled driver, DT and ACPI alike.
This is completely wrong, in that enablement of Relaxed Ordering is only required by default in Tegra20 platforms as described in the Tegra20 Technical Reference Manual (available at
https://developer.nvidia.com/embedded/downloads#?search=tegra%202 in Section 34.1, where it is mentioned that Relaxed Ordering bit needs to be enabled in its root ports to avoid deadlock in hardware) and in the Tegra30 platforms for the same reasons (unfortunately not documented in the TRM).
There is no other strict requirement on PCI devices Relaxed Ordering enablement on any other Tegra platforms or PCI host bridge driver.
Fix this quite upsetting situation by limiting the vendor and device IDs to which the Relaxed Ordering quirk applies to the root ports in question, reported above.
--- drivers/pci/controller/pci-tegra.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/pci/controller/pci-tegra.c +5 -2
@@ -545,12 +545,15 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVDECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_NVIDIA ,0x0e1c , tegra_pcie_fixup_class);DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_NVIDIA ,0x0e1d , tegra_pcie_fixup_class); -/* Tegra PCIE requires relaxed ordering */ +/* Tegra20 and Tegra30 PCIE requires relaxed ordering */ static void tegra_pcie_relax_enable (struct pci_dev *dev) {pcie_capability_set_word (dev,PCI_EXP_DEVCTL ,PCI_EXP_DEVCTL_RELAX_EN ); } -DECLARE_PCI_FIXUP_FINAL (PCI_ANY_ID ,PCI_ANY_ID , tegra_pcie_relax_enable); +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_NVIDIA ,0x0bf0 , tegra_pcie_relax_enable); +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_NVIDIA ,0x0bf1 , tegra_pcie_relax_enable); +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_NVIDIA ,0x0e1c , tegra_pcie_relax_enable); +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_NVIDIA ,0x0e1d , tegra_pcie_relax_enable);static int tegra_pcie_request_resources (struct tegra_pcie *pcie) {
Greg Kroah-Hartman
maintainerPATCH 70/125 HID: google: add magnemite/masterball USB ids
In reply to Greg Kroah-HartmanFrom: Nicolas Boichat <[email protected]>
[ Upstream commit 9e4dbc4646a84b2562ea7c64a542740687ff7daf ]
Add 2 additional hammer-like devices.
--- drivers/hid/hid-google-hammer.c | 4 ++++ drivers/hid/hid-ids.h | 2 ++ 2 files changed, 6 insertions(+)
drivers/hid/hid-google-hammer.c +4 -0
@@ -120,6 +120,10 @@ static int hammer_input_configured(struct hid_device *hdev,static const struct hid_device_id hammer_devices[] = { {HID_DEVICE (BUS_USB ,HID_GROUP_GENERIC ,USB_VENDOR_ID_GOOGLE ,USB_DEVICE_ID_GOOGLE_HAMMER ) }, + {HID_DEVICE (BUS_USB ,HID_GROUP_GENERIC , +USB_VENDOR_ID_GOOGLE ,USB_DEVICE_ID_GOOGLE_MAGNEMITE ) }, + {HID_DEVICE (BUS_USB ,HID_GROUP_GENERIC , +USB_VENDOR_ID_GOOGLE ,USB_DEVICE_ID_GOOGLE_MASTERBALL ) }, {HID_DEVICE (BUS_USB ,HID_GROUP_GENERIC ,USB_VENDOR_ID_GOOGLE ,USB_DEVICE_ID_GOOGLE_STAFF ) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
drivers/hid/hid-ids.h +2 -0
@@ -466,6 +466,8 @@#define USB_DEVICE_ID_GOOGLE_STAFF 0x502b#define USB_DEVICE_ID_GOOGLE_WAND 0x502d#define USB_DEVICE_ID_GOOGLE_WHISKERS 0x5030 +#define USB_DEVICE_ID_GOOGLE_MASTERBALL 0x503c +#define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d#define USB_VENDOR_ID_GOTOP 0x08f2#define USB_DEVICE_ID_SUPER_Q2 0x007f
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 71/125 dmaengine: xilinx_dma: Fix control reg update in vdma_channel_set_config
In reply to Greg Kroah-HartmanFrom: Radhey Shyam Pandey <[email protected]>
[ Upstream commit 6c6de1ddb1be3840f2ed5cc9d009a622720940c9 ]
In vdma_channel_set_config clear the delay, frame count and master mask before updating their new values. It avoids programming incorrect state when input parameters are different from default.
--- drivers/dma/xilinx/xilinx_dma.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/dma/xilinx/xilinx_dma.c +7 -0
@@ -72,6 +72,9 @@#define XILINX_DMA_DMACR_CIRC_EN BIT(1)#define XILINX_DMA_DMACR_RUNSTOP BIT(0)#define XILINX_DMA_DMACR_FSYNCSRC_MASK GENMASK(6, 5) +#define XILINX_DMA_DMACR_DELAY_MASK GENMASK(31, 24) +#define XILINX_DMA_DMACR_FRAME_COUNT_MASK GENMASK(23, 16) +#define XILINX_DMA_DMACR_MASTER_MASK GENMASK(11, 8)#define XILINX_DMA_REG_DMASR 0x0004#define XILINX_DMA_DMASR_EOL_LATE_ERR BIT(15)
@@ -2112,8 +2115,10 @@ int xilinx_vdma_channel_set_config(struct dma_chan *dchan, chan->config.gen_lock = cfg->gen_lock; chan->config.master = cfg->master; + dmacr &= ~XILINX_DMA_DMACR_GENLOCK_EN ;if (cfg->gen_lock && chan->genlock) { dmacr |=XILINX_DMA_DMACR_GENLOCK_EN ; + dmacr &= ~XILINX_DMA_DMACR_MASTER_MASK ; dmacr |= cfg->master <<XILINX_DMA_DMACR_MASTER_SHIFT ; }
@@ -2129,11 +2134,13 @@ int xilinx_vdma_channel_set_config(struct dma_chan *dchan, chan->config.delay = cfg->delay;if (cfg->coalesc <=XILINX_DMA_DMACR_FRAME_COUNT_MAX ) { + dmacr &= ~XILINX_DMA_DMACR_FRAME_COUNT_MASK ; dmacr |= cfg->coalesc <<XILINX_DMA_DMACR_FRAME_COUNT_SHIFT ; chan->config.coalesc = cfg->coalesc; }if (cfg->delay <=XILINX_DMA_DMACR_DELAY_MAX ) { + dmacr &= ~XILINX_DMA_DMACR_DELAY_MASK ; dmacr |= cfg->delay <<XILINX_DMA_DMACR_DELAY_SHIFT ; chan->config.delay = cfg->delay; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 72/125 dmaengine: sprd: Fix the possible memory leak issue
In reply to Greg Kroah-HartmanFrom: Baolin Wang <[email protected]>
[ Upstream commit ec1ac309596a7bdf206743b092748205f6cd5720 ]
If we terminate the channel to free all descriptors associated with this channel, we will leak the memory of current descriptor if the current descriptor is not completed, since it had been deteled from the desc_issued list and have not been added into the desc_completed list.
Thus we should check if current descriptor is completed or not, when freeing the descriptors associated with one channel, if not, we should free it to avoid this issue.
--- drivers/dma/sprd-dma.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/dma/sprd-dma.c +15 -0
@@ -181,6 +181,7 @@ struct sprd_dma_dev {struct sprd_dma_chn channels[0 ]; }; +static void sprd_dma_free_desc (struct virt_dma_desc *vd);static bool sprd_dma_filter_fn (struct dma_chan *chan,void *param);static struct of_dma_filter_info sprd_dma_info = { .filter_fn = sprd_dma_filter_fn,
@@ -493,12 +494,19 @@ static int sprd_dma_alloc_chan_resources(struct dma_chan *chan)static void sprd_dma_free_chan_resources (struct dma_chan *chan) {struct sprd_dma_chn *schan =to_sprd_dma_chan (chan); +struct virt_dma_desc *cur_vd =NULL ;unsigned long flags;spin_lock_irqsave (&schan->vc.lock, flags); +if (schan->cur_desc) + cur_vd = &schan->cur_desc->vd; +sprd_dma_stop (schan);spin_unlock_irqrestore (&schan->vc.lock, flags); +if (cur_vd) +sprd_dma_free_desc (cur_vd); +vchan_free_chan_resources (&schan->vc);pm_runtime_put (chan->device->dev); }
@@ -814,15 +822,22 @@ static int sprd_dma_resume(struct dma_chan *chan)static int sprd_dma_terminate_all (struct dma_chan *chan) {struct sprd_dma_chn *schan =to_sprd_dma_chan (chan); +struct virt_dma_desc *cur_vd =NULL ;unsigned long flags;LIST_HEAD (head);spin_lock_irqsave (&schan->vc.lock, flags); +if (schan->cur_desc) + cur_vd = &schan->cur_desc->vd; +sprd_dma_stop (schan);vchan_get_all_descriptors (&schan->vc, &head);spin_unlock_irqrestore (&schan->vc.lock, flags); +if (cur_vd) +sprd_dma_free_desc (cur_vd); +vchan_dma_desc_free_list (&schan->vc, &head);return 0 ; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 73/125 HID: intel-ish-hid: fix wrong error handling in ishtp_cl_alloc_tx_ring()
In reply to Greg Kroah-HartmanFrom: Zhang Lixu <[email protected]>
[ Upstream commit 16ff7bf6dbcc6f77d2eec1ac9120edf44213c2f1 ]
When allocating tx ring buffers failed, should free tx buffers, not rx buffers.
--- drivers/hid/intel-ish-hid/ishtp/client-buffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/intel-ish-hid/ishtp/client-buffers.c +1 -1
@@ -90,7 +90,7 @@ int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl)return 0 ; out:dev_err (&cl->device->dev,"error in allocating Tx pool\n" ); -ishtp_cl_free_rx_ring (cl); +ishtp_cl_free_tx_ring (cl);return -ENOMEM ; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 74/125 RDMA/mlx5: Clear old rate limit when closing QP
In reply to Greg Kroah-HartmanFrom: Rafi Wiener <[email protected]>
[ Upstream commit c8973df2da677f375f8b12b6eefca2f44c8884d5 ]
Before QP is closed it changes to ERROR state, when this happens the QP was left with old rate limit that was already removed from the table.
--- drivers/infiniband/hw/mlx5/qp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/infiniband/hw/mlx5/qp.c +5 -3
@@ -2828,10 +2828,12 @@ static int modify_raw_packet_qp_sq(struct mlx5_core_dev *dev, }/* Only remove the old rate after new rate was set */ -if ((old_rl.rate && - !mlx5_rl_are_equal (&old_rl, &new_rl)) || - (new_state !=MLX5_SQC_STATE_RDY )) +if ((old_rl.rate && !mlx5_rl_are_equal (&old_rl, &new_rl)) || + (new_state !=MLX5_SQC_STATE_RDY )) {mlx5_rl_remove_rate (dev, &old_rl); +if (new_state !=MLX5_SQC_STATE_RDY ) +memset (&new_rl,0 ,sizeof (new_rl)); + } ibqp->rl = new_rl; sq->state = new_state;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 75/125 iw_cxgb4: fix ECN check on the passive accept
In reply to Greg Kroah-HartmanFrom: Potnuri Bharat Teja <[email protected]>
[ Upstream commit 612e0486ad0845c41ac10492e78144f99e326375 ]
pass_accept_req() is using the same skb for handling accept request and sending accept reply to HW. Here req and rpl structures are pointing to same skb->data which is over written by INIT_TP_WR() and leads to accessing corrupt req fields in accept_cr() while checking for ECN flags. Reordered code in accept_cr() to fetch correct req fields.
--- drivers/infiniband/hw/cxgb4/cm.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
drivers/infiniband/hw/cxgb4/cm.c +14 -14
@@ -2380,20 +2380,6 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;pr_debug ("ep %p tid %u\n" , ep, ep->hwtid); - -skb_get (skb); - rpl =cplhdr (skb); -if (!is_t4 (adapter_type)) { -skb_trim (skb,roundup (sizeof (*rpl5),16 )); - rpl5 = (void *)rpl; -INIT_TP_WR (rpl5, ep->hwtid); - }else { -skb_trim (skb,sizeof (*rpl)); -INIT_TP_WR (rpl, ep->hwtid); - } -OPCODE_TID (rpl) =cpu_to_be32 (MK_OPCODE_TID (CPL_PASS_ACCEPT_RPL , - ep->hwtid)); -cxgb_best_mtu (ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx, enable_tcp_timestamps && req->tcpopt.tstamp, (ep->com.remote_addr.ss_family ==AF_INET ) ?0 :1 );
@@ -2439,6 +2425,20 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,if (tcph->ece && tcph->cwr) opt2 |=CCTRL_ECN_V (1 ); } + +skb_get (skb); + rpl =cplhdr (skb); +if (!is_t4 (adapter_type)) { +skb_trim (skb,roundup (sizeof (*rpl5),16 )); + rpl5 = (void *)rpl; +INIT_TP_WR (rpl5, ep->hwtid); + }else { +skb_trim (skb,sizeof (*rpl)); +INIT_TP_WR (rpl, ep->hwtid); + } +OPCODE_TID (rpl) =cpu_to_be32 (MK_OPCODE_TID (CPL_PASS_ACCEPT_RPL , + ep->hwtid)); +if (CHELSIO_CHIP_VERSION (adapter_type) >CHELSIO_T4 ) {u32 isn = (prandom_u32 () & ~7UL ) -1 ; opt2 |=T5_OPT_2_VALID_F ;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 76/125 RDMA/qedr: Fix reported firmware version
In reply to Greg Kroah-HartmanFrom: Kamal Heib <[email protected]>
[ Upstream commit b806c94ee44e53233b8ce6c92d9078d9781786a5 ]
Remove spaces from the reported firmware version string. Actual value:
$ cat /sys/class/infiniband/qedr0/fw_ver 8. 37. 7. 0
Expected value:
$ cat /sys/class/infiniband/qedr0/fw_ver 8.37.7.0
--- drivers/infiniband/hw/qedr/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/qedr/main.c +1 -1
@@ -77,7 +77,7 @@ static void qedr_get_dev_fw_str(struct ib_device *ibdev, char *str)struct qedr_dev *qedr =get_qedr_dev (ibdev);u32 fw_ver = (u32 )qedr->attr.fw_ver; -snprintf (str,IB_FW_VERSION_NAME_MAX ,"%d. %d. %d. %d" , +snprintf (str,IB_FW_VERSION_NAME_MAX ,"%d.%d.%d.%d" , (fw_ver >>24 ) &0xFF , (fw_ver >>16 ) &0xFF , (fw_ver >>8 ) &0xFF , fw_ver &0xFF ); }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 77/125 net/mlx5e: TX, Fix consumer index of error cqe dump
In reply to Greg Kroah-HartmanFrom: Tariq Toukan <[email protected]>
[ Upstream commit 61ea02d2c13106116c6e4916ac5d9dd41151c959 ]
The completion queue consumer index increments upon a call to mlx5_cqwq_pop().
When dumping an error CQE, the index is already incremented. Decrease one for the print command.
--- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +4 -1
@@ -462,7 +462,10 @@ netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)static void mlx5e_dump_error_cqe (struct mlx5e_txqsq *sq,struct mlx5_err_cqe *err_cqe) { -u32 ci =mlx5_cqwq_get_ci (&sq->cq.wq); +struct mlx5_cqwq *wq = &sq->cq.wq; +u32 ci; + + ci =mlx5_cqwq_ctr2ix (wq, wq->cc -1 ); netdev_err(sq->channel->netdev, "Error cqe on cqn 0x%x, ci 0x%x, sqn 0x%x, syndrome 0x%x, vendor syndrome 0x%x\n",
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 78/125 net/mlx5: prevent memory leak in mlx5_fpga_conn_create_cq
In reply to Greg Kroah-HartmanFrom: Navid Emamdoost <[email protected]>
[ Upstream commit c8c2a057fdc7de1cd16f4baa51425b932a42eb39 ]
In mlx5_fpga_conn_create_cq if mlx5_vector2eqn fails the allocated memory should be released.
--- drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +3 -1
@@ -462,8 +462,10 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size) } err =mlx5_vector2eqn (mdev,smp_processor_id (), &eqn, &irqn); -if (err) +if (err) { +kvfree (in); goto err_cqwq; + } cqc =MLX5_ADDR_OF (create_cq_in, in, cq_context);MLX5_SET (cqc, cqc, log_cq_size,ilog2 (cq_size));
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 79/125 scsi: qla2xxx: fixup incorrect usage of host_byte
In reply to Greg Kroah-HartmanFrom: Hannes Reinecke <[email protected]>
[ Upstream commit 66cf50e65b183c863825f5c28a818e3f47a72e40 ]
DRIVER_ERROR is a a driver byte setting, not a host byte. The qla2xxx driver should rather return DID_ERROR here to be in line with the other drivers.
--- drivers/scsi/qla2xxx/qla_bsg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/scsi/qla2xxx/qla_bsg.c +3 -3
@@ -258,7 +258,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)srb_t *sp;const char *type;int req_sg_cnt, rsp_sg_cnt; -int rval = (DRIVER_ERROR <<16 ); +int rval = (DID_ERROR <<16 );uint16_t nextlid =0 ;if (bsg_request->msgcode ==FC_BSG_RPT_ELS ) {
@@ -433,7 +433,7 @@ qla2x00_process_ct(struct bsg_job *bsg_job)struct Scsi_Host *host =fc_bsg_to_shost (bsg_job);scsi_qla_host_t *vha =shost_priv (host);struct qla_hw_data *ha = vha->hw; -int rval = (DRIVER_ERROR <<16 ); +int rval = (DID_ERROR <<16 );int req_sg_cnt, rsp_sg_cnt;uint16_t loop_id;struct fc_port *fcport;
@@ -1948,7 +1948,7 @@ qlafx00_mgmt_cmd(struct bsg_job *bsg_job)struct Scsi_Host *host =fc_bsg_to_shost (bsg_job);scsi_qla_host_t *vha =shost_priv (host);struct qla_hw_data *ha = vha->hw; -int rval = (DRIVER_ERROR <<16 ); +int rval = (DID_ERROR <<16 );struct qla_mt_iocb_rqst_fx00 *piocb_rqst;srb_t *sp;int req_sg_cnt =0 , rsp_sg_cnt =0 ;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 80/125 RDMA/uverbs: Prevent potential underflow
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit a9018adfde809d44e71189b984fa61cc89682b5e ]
The issue is in drivers/infiniband/core/uverbs_std_types_cq.c in the UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE) function. We check that:
if (attr.comp_vector >= attrs->ufile->device->num_comp_vectors) {But we don't check if "attr.comp_vector" is negative. It could potentially lead to an array underflow. My concern would be where cq->vector is used in the create_cq() function from the cxgb4 driver.
And really "attr.comp_vector" is appears as a u32 to user space so that's the right type to use.
--- drivers/infiniband/core/uverbs.h | 2 +- include/rdma/ib_verbs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/core/uverbs.h +1 -1
@@ -98,7 +98,7 @@ ib_uverbs_init_udata_buf_or_null(struct ib_udata *udata,struct ib_uverbs_device {atomic_t refcount; -int num_comp_vectors; +u32 num_comp_vectors;struct completion comp;struct device *dev;struct ib_device __rcu *ib_dev;
include/rdma/ib_verbs.h +1 -1
@@ -310,7 +310,7 @@ struct ib_tm_caps {struct ib_cq_init_attr {unsigned int cqe; -int comp_vector; +u32 comp_vector;u32 flags; };
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 81/125 net: openvswitch: free vport unless register_netdevice() succeeds
In reply to Greg Kroah-HartmanFrom: Hillf Danton <[email protected]>
[ Upstream commit 9464cc37f3671ee69cb1c00662b5e1f113a96b23 ]
syzbot found the following crash on:
HEAD commit: 1e78030e Merge tag 'mmc-v5.3-rc1' of git://git.kernel.org/.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=148d3d1a600000 kernel config: https://syzkaller.appspot.com/x/.config?x=30cef20daf3e9977 dashboard link: https://syzkaller.appspot.com/bug?extid=13210896153522fe1ee5 compiler: gcc (GCC) 9.0.0 20181231 (experimental) syz repro: https://syzkaller.appspot.com/x/repro.syz?x=136aa8c4600000 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=109ba792600000
=====================================================================
BUG: memory leak
unreferenced object 0xffff8881207e4100 (size 128):
comm "syz-executor032", pid 7014, jiffies 4294944027 (age 13.830s)
hex dump (first 32 bytes):
00 70 16 18 81 88 ff ff 80 af 8c 22 81 88 ff ff .p........."....
00 b6 23 17 81 88 ff ff 00 00 00 00 00 00 00 00 ..#.............
backtrace:
[<000000000eb78212>] kmemleak_alloc_recursive include/linux/kmemleak.h:43 [inline]
[<000000000eb78212>] slab_post_alloc_hook mm/slab.h:522 [inline]
[<000000000eb78212>] slab_alloc mm/slab.c:3319 [inline]
[<000000000eb78212>] kmem_cache_alloc_trace+0x145/0x2c0 mm/slab.c:3548
[<00000000006ea6c6>] kmalloc include/linux/slab.h:552 [inline]
[<00000000006ea6c6>] kzalloc include/linux/slab.h:748 [inline]
[<00000000006ea6c6>] ovs_vport_alloc+0x37/0xf0 net/openvswitch/vport.c:130
[<00000000f9a04a7d>] internal_dev_create+0x24/0x1d0 net/openvswitch/vport-internal_dev.c:164
[<0000000056ee7c13>] ovs_vport_add+0x81/0x190 net/openvswitch/vport.c:199
[<000000005434efc7>] new_vport+0x19/0x80 net/openvswitch/datapath.c:194
[<00000000b7b253f1>] ovs_dp_cmd_new+0x22f/0x410 net/openvswitch/datapath.c:1614
[<00000000e0988518>] genl_family_rcv_msg+0x2ab/0x5b0 net/netlink/genetlink.c:629
[<00000000d0cc9347>] genl_rcv_msg+0x54/0x9c net/netlink/genetlink.c:654
[<000000006694b647>] netlink_rcv_skb+0x61/0x170 net/netlink/af_netlink.c:2477
[<0000000088381f37>] genl_rcv+0x29/0x40 net/netlink/genetlink.c:665
[<00000000dad42a47>] netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline]
[<00000000dad42a47>] netlink_unicast+0x1ec/0x2d0 net/netlink/af_netlink.c:1328
[<0000000067e6b079>] netlink_sendmsg+0x270/0x480 net/netlink/af_netlink.c:1917
[<00000000aab08a47>] sock_sendmsg_nosec net/socket.c:637 [inline]
[<00000000aab08a47>] sock_sendmsg+0x54/0x70 net/socket.c:657
[<000000004cb7c11d>] ___sys_sendmsg+0x393/0x3c0 net/socket.c:2311
[<00000000c4901c63>] __sys_sendmsg+0x80/0xf0 net/socket.c:2356
[<00000000c10abb2d>] __do_sys_sendmsg net/socket.c:2365 [inline]
[<00000000c10abb2d>] __se_sys_sendmsg net/socket.c:2363 [inline]
[<00000000c10abb2d>] __x64_sys_sendmsg+0x23/0x30 net/socket.c:2363BUG: memory leak
unreferenced object 0xffff88811723b600 (size 64):
comm "syz-executor032", pid 7014, jiffies 4294944027 (age 13.830s)
hex dump (first 32 bytes):
01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 02 00 00 00 05 35 82 c1 .............5..
backtrace:
[<00000000352f46d8>] kmemleak_alloc_recursive include/linux/kmemleak.h:43 [inline]
[<00000000352f46d8>] slab_post_alloc_hook mm/slab.h:522 [inline]
[<00000000352f46d8>] slab_alloc mm/slab.c:3319 [inline]
[<00000000352f46d8>] __do_kmalloc mm/slab.c:3653 [inline]
[<00000000352f46d8>] __kmalloc+0x169/0x300 mm/slab.c:3664
[<000000008e48f3d1>] kmalloc include/linux/slab.h:557 [inline]
[<000000008e48f3d1>] ovs_vport_set_upcall_portids+0x54/0xd0 net/openvswitch/vport.c:343
[<00000000541e4f4a>] ovs_vport_alloc+0x7f/0xf0 net/openvswitch/vport.c:139
[<00000000f9a04a7d>] internal_dev_create+0x24/0x1d0 net/openvswitch/vport-internal_dev.c:164
[<0000000056ee7c13>] ovs_vport_add+0x81/0x190 net/openvswitch/vport.c:199
[<000000005434efc7>] new_vport+0x19/0x80 net/openvswitch/datapath.c:194
[<00000000b7b253f1>] ovs_dp_cmd_new+0x22f/0x410 net/openvswitch/datapath.c:1614
[<00000000e0988518>] genl_family_rcv_msg+0x2ab/0x5b0 net/netlink/genetlink.c:629
[<00000000d0cc9347>] genl_rcv_msg+0x54/0x9c net/netlink/genetlink.c:654
[<000000006694b647>] netlink_rcv_skb+0x61/0x170 net/netlink/af_netlink.c:2477
[<0000000088381f37>] genl_rcv+0x29/0x40 net/netlink/genetlink.c:665
[<00000000dad42a47>] netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline]
[<00000000dad42a47>] netlink_unicast+0x1ec/0x2d0 net/netlink/af_netlink.c:1328
[<0000000067e6b079>] netlink_sendmsg+0x270/0x480 net/netlink/af_netlink.c:1917
[<00000000aab08a47>] sock_sendmsg_nosec net/socket.c:637 [inline]
[<00000000aab08a47>] sock_sendmsg+0x54/0x70 net/socket.c:657
[<000000004cb7c11d>] ___sys_sendmsg+0x393/0x3c0 net/socket.c:2311
[<00000000c4901c63>] __sys_sendmsg+0x80/0xf0 net/socket.c:2356BUG: memory leak
unreferenced object 0xffff8881228ca500 (size 128):
comm "syz-executor032", pid 7015, jiffies 4294944622 (age 7.880s)
hex dump (first 32 bytes):
00 f0 27 18 81 88 ff ff 80 ac 8c 22 81 88 ff ff ..'........"....
40 b7 23 17 81 88 ff ff 00 00 00 00 00 00 00 00 @.#.............
backtrace:
[<000000000eb78212>] kmemleak_alloc_recursive include/linux/kmemleak.h:43 [inline]
[<000000000eb78212>] slab_post_alloc_hook mm/slab.h:522 [inline]
[<000000000eb78212>] slab_alloc mm/slab.c:3319 [inline]
[<000000000eb78212>] kmem_cache_alloc_trace+0x145/0x2c0 mm/slab.c:3548
[<00000000006ea6c6>] kmalloc include/linux/slab.h:552 [inline]
[<00000000006ea6c6>] kzalloc include/linux/slab.h:748 [inline]
[<00000000006ea6c6>] ovs_vport_alloc+0x37/0xf0 net/openvswitch/vport.c:130
[<00000000f9a04a7d>] internal_dev_create+0x24/0x1d0 net/openvswitch/vport-internal_dev.c:164
[<0000000056ee7c13>] ovs_vport_add+0x81/0x190 net/openvswitch/vport.c:199
[<000000005434efc7>] new_vport+0x19/0x80 net/openvswitch/datapath.c:194
[<00000000b7b253f1>] ovs_dp_cmd_new+0x22f/0x410 net/openvswitch/datapath.c:1614
[<00000000e0988518>] genl_family_rcv_msg+0x2ab/0x5b0 net/netlink/genetlink.c:629
[<00000000d0cc9347>] genl_rcv_msg+0x54/0x9c net/netlink/genetlink.c:654
[<000000006694b647>] netlink_rcv_skb+0x61/0x170 net/netlink/af_netlink.c:2477
[<0000000088381f37>] genl_rcv+0x29/0x40 net/netlink/genetlink.c:665
[<00000000dad42a47>] netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline]
[<00000000dad42a47>] netlink_unicast+0x1ec/0x2d0 net/netlink/af_netlink.c:1328
[<0000000067e6b079>] netlink_sendmsg+0x270/0x480 net/netlink/af_netlink.c:1917
[<00000000aab08a47>] sock_sendmsg_nosec net/socket.c:637 [inline]
[<00000000aab08a47>] sock_sendmsg+0x54/0x70 net/socket.c:657
[<000000004cb7c11d>] ___sys_sendmsg+0x393/0x3c0 net/socket.c:2311
[<00000000c4901c63>] __sys_sendmsg+0x80/0xf0 net/socket.c:2356
[<00000000c10abb2d>] __do_sys_sendmsg net/socket.c:2365 [inline]
[<00000000c10abb2d>] __se_sys_sendmsg net/socket.c:2363 [inline]
[<00000000c10abb2d>] __x64_sys_sendmsg+0x23/0x30 net/socket.c:2363=====================================================================
The function in net core, register_netdevice(), may fail with vport's destruction callback either invoked or not. After commit 309b66970ee2 ("net: openvswitch: do not free vport if register_netdevice() is failed."), the duty to destroy vport is offloaded from the driver OTOH, which ends up in the memory leak reported.
It is fixed by releasing vport unless device is registered successfully. To do that, the callback assignment is defered until device is registered.
[sbrivio: this was sent to [email protected] and never made its way
to netdev -- resending original patch]
--- net/openvswitch/vport-internal_dev.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
net/openvswitch/vport-internal_dev.c +4 -7
@@ -149,7 +149,7 @@ static void do_setup(struct net_device *netdev) netdev->priv_flags |=IFF_LIVE_ADDR_CHANGE |IFF_OPENVSWITCH |IFF_NO_QUEUE ; netdev->needs_free_netdev = true; - netdev->priv_destructor = internal_dev_destructor; + netdev->priv_destructor =NULL ; netdev->ethtool_ops = &internal_dev_ethtool_ops; netdev->rtnl_link_ops = &internal_dev_link_ops;
@@ -171,7 +171,6 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)struct internal_dev *internal_dev;struct net_device *dev;int err; -bool free_vport = true; vport =ovs_vport_alloc (0 , &ovs_internal_vport_ops, parms);if (IS_ERR (vport)) {
@@ -202,10 +201,9 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)rtnl_lock (); err =register_netdevice (vport->dev); -if (err) { - free_vport = false; +if (err) goto error_unlock; - } + vport->dev->priv_destructor = internal_dev_destructor;dev_set_promiscuity (vport->dev,1 );rtnl_unlock ();
@@ -219,8 +217,7 @@ error_unlock: error_free_netdev:free_netdev (dev); error_free_vport: -if (free_vport) -ovs_vport_free (vport); +ovs_vport_free (vport); error:return ERR_PTR (err); }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 82/125 scsi: lpfc: Honor module parameter lpfc_use_adisc
In reply to Greg Kroah-HartmanFrom: Daniel Wagner <[email protected]>
[ Upstream commit 0fd103ccfe6a06e40e2d9d8c91d96332cc9e1239 ]
The initial lpfc_desc_set_adisc implementation in commit dea3101e0a5c ("lpfc: add Emulex FC driver version 8.0.28") enabled ADISC if
cfg_use_adisc && RSCN_MODE && FCP_2_DEVICE
In commit 92d7f7b0cde3 ("[SCSI] lpfc: NPIV: add NPIV support on top of SLI-3") this changed to
(cfg_use_adisc && RSC_MODE) || FCP_2_DEVICE
and later in commit ffc954936b13 ("[SCSI] lpfc 8.3.13: FC Discovery Fixes and enhancements.") to
(cfg_use_adisc && RSC_MODE) || (FCP_2_DEVICE && FCP_TARGET)
A customer reports that after a devloss, an ADISC failure is logged. It turns out the ADISC flag is set even the user explicitly set lpfc_use_adisc = 0.
[Sat Dec 22 22:55:58 2018] lpfc 0000:82:00.0: 2:(0):0203 Devloss timeout on WWPN 50:01:43:80:12:8e:40:20 NPort x05df00 Data: x82000000 x8 xa [Sat Dec 22 23:08:20 2018] lpfc 0000:82:00.0: 2:(0):2755 ADISC failure DID:05DF00 Status:x9/x70000
[mkp: fixed Hannes' email]
--- drivers/scsi/lpfc/lpfc_nportdisc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/lpfc/lpfc_nportdisc.c +2 -2
@@ -844,9 +844,9 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)if (!(vport->fc_flag &FC_PT2PT )) {/* Check config parameter use-adisc or FCP-2 */ -if ((vport->cfg_use_adisc && (vport->fc_flag &FC_RSCN_MODE )) || +if (vport->cfg_use_adisc && ((vport->fc_flag &FC_RSCN_MODE ) || ((ndlp->nlp_fcp_info &NLP_FCP_2_DEVICE ) && - (ndlp->nlp_type &NLP_FCP_TARGET ))) { + (ndlp->nlp_type &NLP_FCP_TARGET )))) {spin_lock_irq (shost->host_lock); ndlp->nlp_flag |=NLP_NPR_ADISC ;spin_unlock_irq (shost->host_lock);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 83/125 scsi: qla2xxx: Initialized mailbox to prevent driver load failure
In reply to Greg Kroah-HartmanFrom: Himanshu Madhani <[email protected]>
[ Upstream commit c2ff2a36eff60efb5e123c940115216d6bf65684 ]
This patch fixes issue with Gen7 adapter in a blade environment where one of the ports will not be detected by driver. Firmware expects mailbox 11 to be set or cleared by driver for newer ISP.
Following message is seen in the log file:
[ 18.810892] qla2xxx [0000:d8:00.0]-1820:1: **** Failed=102 mb[0]=4005 mb[1]=37 mb[2]=20 mb[3]=8 [ 18.819596] cmd=2 ****
[mkp: typos]
--- drivers/scsi/qla2xxx/qla_mbx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_mbx.c +2 -1
@@ -684,6 +684,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[2 ] =LSW (risc_addr); mcp->mb[3 ] =0 ; mcp->mb[4 ] =0 ; + mcp->mb[11 ] =0 ; ha->flags.using_lr_setting =0 ;if (IS_QLA25XX (ha) ||IS_QLA81XX (ha) ||IS_QLA83XX (ha) ||IS_QLA27XX (ha)) {
@@ -727,7 +728,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)if (ha->flags.exchoffld_enabled) mcp->mb[4 ] |=ENABLE_EXCHANGE_OFFLD ; - mcp->out_mb |=MBX_4 |MBX_3 |MBX_2 |MBX_1 ; + mcp->out_mb |=MBX_4 |MBX_3 |MBX_2 |MBX_1 |MBX_11 ; mcp->in_mb |=MBX_3 |MBX_2 |MBX_1 ; }else { mcp->mb[1 ] =LSW (risc_addr);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 84/125 netfilter: nf_flow_table: set timeout before insertion into hashes
In reply to Greg Kroah-HartmanFrom: Pablo Neira Ayuso <[email protected]>
[ Upstream commit daf61b026f4686250e6afa619e6d7b49edc61df7 ]
Other garbage collector might remove an entry not fully set up yet.
[570953.958293] RIP: 0010:memcmp+0x9/0x50 [...] [570953.958567] flow_offload_hash_cmp+0x1e/0x30 [nf_flow_table] [570953.958585] flow_offload_lookup+0x8c/0x110 [nf_flow_table] [570953.958606] nf_flow_offload_ip_hook+0x135/0xb30 [nf_flow_table] [570953.958624] nf_flow_offload_inet_hook+0x35/0x37 [nf_flow_table_inet] [570953.958646] nf_hook_slow+0x3c/0xb0 [570953.958664] __netif_receive_skb_core+0x90f/0xb10 [570953.958678] ? ip_rcv_finish+0x82/0xa0 [570953.958692] __netif_receive_skb_one_core+0x3b/0x80 [570953.958711] __netif_receive_skb+0x18/0x60 [570953.958727] netif_receive_skb_internal+0x45/0xf0 [570953.958741] napi_gro_receive+0xcd/0xf0 [570953.958764] ixgbe_clean_rx_irq+0x432/0xe00 [ixgbe] [570953.958782] ixgbe_poll+0x27b/0x700 [ixgbe] [570953.958796] net_rx_action+0x284/0x3c0 [570953.958817] __do_softirq+0xcc/0x27c [570953.959464] irq_exit+0xe8/0x100 [570953.960097] do_IRQ+0x59/0xe0 [570953.960734] common_interrupt+0xf/0xf
--- net/netfilter/nf_flow_table_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/netfilter/nf_flow_table_core.c +2 -1
@@ -187,6 +187,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) {int err; + flow->timeout = (u32 )jiffies +NF_FLOW_TIMEOUT ; + err =rhashtable_insert_fast (&flow_table->rhashtable, &flow->tuplehash[0 ].node, nf_flow_offload_rhash_params);
@@ -203,7 +205,6 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)return err; } - flow->timeout = (u32 )jiffies +NF_FLOW_TIMEOUT ;return 0 ; }EXPORT_SYMBOL_GPL (flow_offload_add);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 85/125 ipvs: dont ignore errors in case refcounting ip_vs module fails
In reply to Greg Kroah-HartmanFrom: Davide Caratti <[email protected]>
[ Upstream commit 62931f59ce9cbabb934a431f48f2f1f441c605ac ]
if the IPVS module is removed while the sync daemon is starting, there is a small gap where try_module_get() might fail getting the refcount inside ip_vs_use_count_inc(). Then, the refcounts of IPVS module are unbalanced, and the subsequent call to stop_sync_thread() causes the following splat:
WARNING: CPU: 0 PID: 4013 at kernel/module.c:1146 module_put.part.44+0x15b/0x290 Modules linked in: ip_vs(-) nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 veth ip6table_filter ip6_tables iptable_filter binfmt_misc intel_rapl_msr intel_rapl_common crct10dif_pclmul crc32_pclmul ext4 mbcache jbd2 ghash_clmulni_intel snd_hda_codec_generic ledtrig_audio snd_hda_intel snd_intel_nhlt snd_hda_codec snd_hda_core snd_hwdep snd_seq snd_seq_device snd_pcm aesni_intel crypto_simd cryptd glue_helper joydev pcspkr snd_timer virtio_balloon snd soundcore i2c_piix4 nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c ata_generic pata_acpi virtio_net net_failover virtio_blk failover virtio_console qxl drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ata_piix ttm crc32c_intel serio_raw drm virtio_pci libata virtio_ring virtio floppy dm_mirror dm_region_hash dm_log dm_mod [last unloaded: nf_defrag_ipv6] CPU: 0 PID: 4013 Comm: modprobe Tainted: G W 5.4.0-rc1.upstream+ #741 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 RIP: 0010:module_put.part.44+0x15b/0x290 Code: 04 25 28 00 00 00 0f 85 18 01 00 00 48 83 c4 68 5b 5d 41 5c 41 5d 41 5e 41 5f c3 89 44 24 28 83 e8 01 89 c5 0f 89 57 ff ff ff <0f> 0b e9 78 ff ff ff 65 8b 1d 67 83 26 4a 89 db be 08 00 00 00 48 RSP: 0018:ffff888050607c78 EFLAGS: 00010297 RAX: 0000000000000003 RBX: ffffffffc1420590 RCX: ffffffffb5db0ef9 RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffffffffc1420590 RBP: 00000000ffffffff R08: fffffbfff82840b3 R09: fffffbfff82840b3 R10: 0000000000000001 R11: fffffbfff82840b2 R12: 1ffff1100a0c0f90 R13: ffffffffc1420200 R14: ffff88804f533300 R15: ffff88804f533ca0 FS: 00007f8ea9720740(0000) GS:ffff888053800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f3245abe000 CR3: 000000004c28a006 CR4: 00000000001606f0 Call Trace: stop_sync_thread+0x3a3/0x7c0 [ip_vs] ip_vs_sync_net_cleanup+0x13/0x50 [ip_vs] ops_exit_list.isra.5+0x94/0x140 unregister_pernet_operations+0x29d/0x460 unregister_pernet_device+0x26/0x60 ip_vs_cleanup+0x11/0x38 [ip_vs] __x64_sys_delete_module+0x2d5/0x400 do_syscall_64+0xa5/0x4e0 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x7f8ea8bf0db7 Code: 73 01 c3 48 8b 0d b9 80 2c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 b8 b0 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 89 80 2c 00 f7 d8 64 89 01 48 RSP: 002b:00007ffcd38d2fe8 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0 RAX: ffffffffffffffda RBX: 0000000002436240 RCX: 00007f8ea8bf0db7 RDX: 0000000000000000 RSI: 0000000000000800 RDI: 00000000024362a8 RBP: 0000000000000000 R08: 00007f8ea8eba060 R09: 00007f8ea8c658a0 R10: 00007ffcd38d2a60 R11: 0000000000000206 R12: 0000000000000000 R13: 0000000000000001 R14: 00000000024362a8 R15: 0000000000000000 irq event stamp: 4538 hardirqs last enabled at (4537): [<ffffffffb6193dde>] quarantine_put+0x9e/0x170 hardirqs last disabled at (4538): [<ffffffffb5a0556a>] trace_hardirqs_off_thunk+0x1a/0x20 softirqs last enabled at (4522): [<ffffffffb6f8ebe9>] sk_common_release+0x169/0x2d0 softirqs last disabled at (4520): [<ffffffffb6f8eb3e>] sk_common_release+0xbe/0x2d0
Check the return value of ip_vs_use_count_inc() and let its caller return proper error. Inside do_ip_vs_set_ctl() the module is already refcounted, we don't need refcount/derefcount there. Finally, in register_ip_vs_app() and start_sync_thread(), take the module refcount earlier and ensure it's released in the error path.
Change since v1:
- better return values in case of failure of ip_vs_use_count_inc(), thanks to Julian Anastasov
- no need to increase/decrease the module refcount in ip_vs_set_ctl(), thanks to Julian Anastasov
--- net/netfilter/ipvs/ip_vs_app.c | 12 ++++++++++-- net/netfilter/ipvs/ip_vs_ctl.c | 14 ++++---------- net/netfilter/ipvs/ip_vs_pe.c | 3 ++- net/netfilter/ipvs/ip_vs_sched.c | 3 ++- net/netfilter/ipvs/ip_vs_sync.c | 13 ++++++++++--- 5 files changed, 28 insertions(+), 17 deletions(-)
net/netfilter/ipvs/ip_vs_app.c +10 -2
@@ -198,21 +198,29 @@ struct ip_vs_app *register_ip_vs_app(struct netns_ipvs *ipvs, struct ip_vs_app *mutex_lock (&__ip_vs_app_mutex); +/* increase the module use count */ +if (!ip_vs_use_count_inc ()) { + err = -ENOENT ; + goto out_unlock; + } +list_for_each_entry (a, &ipvs->app_list, a_list) {if (!strcmp (app->name, a->name)) { err = -EEXIST ; +/* decrease the module use count */ +ip_vs_use_count_dec (); goto out_unlock; } } a =kmemdup (app,sizeof (*app),GFP_KERNEL );if (!a) { err = -ENOMEM ; +/* decrease the module use count */ +ip_vs_use_count_dec (); goto out_unlock; }INIT_LIST_HEAD (&a->incs_list);list_add (&a->a_list, &ipvs->app_list); -/* increase the module use count */ -ip_vs_use_count_inc (); out_unlock:mutex_unlock (&__ip_vs_app_mutex);
net/netfilter/ipvs/ip_vs_ctl.c +4 -10
@@ -1204,7 +1204,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,struct ip_vs_service *svc =NULL ;/* increase the module use count */ -ip_vs_use_count_inc (); +if (!ip_vs_use_count_inc ()) +return -ENOPROTOOPT ;/* Lookup the scheduler by 'u->sched_name' */ if (strcmp (u->sched_name,"none" )) {
@@ -2363,9 +2364,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)if (copy_from_user (arg, user, len) !=0 )return -EFAULT ; -/* increase the module use count */ -ip_vs_use_count_inc (); -/* Handle daemons since they have another lock */ if (cmd ==IP_VS_SO_SET_STARTDAEMON || cmd ==IP_VS_SO_SET_STOPDAEMON ) {
@@ -2378,13 +2376,13 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ret = -EINVAL ;if (strscpy (cfg.mcast_ifn, dm->mcast_ifn,sizeof (cfg.mcast_ifn)) <=0 ) - goto out_dec; +return ret; cfg.syncid = dm->syncid; ret =start_sync_thread (ipvs, &cfg, dm->state); }else { ret =stop_sync_thread (ipvs, dm->state); } - goto out_dec; +return ret; }mutex_lock (&__ip_vs_mutex);
@@ -2479,10 +2477,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) out_unlock:mutex_unlock (&__ip_vs_mutex); - out_dec: -/* decrease the module use count */ -ip_vs_use_count_dec (); -return ret; }
net/netfilter/ipvs/ip_vs_pe.c +2 -1
@@ -67,7 +67,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)struct ip_vs_pe *tmp;/* increase the module use count */ -ip_vs_use_count_inc (); +if (!ip_vs_use_count_inc ()) +return -ENOENT ;mutex_lock (&ip_vs_pe_mutex);/* Make sure that the pe with this name doesn't exist
net/netfilter/ipvs/ip_vs_sched.c +2 -1
@@ -184,7 +184,8 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler) }/* increase the module use count */ -ip_vs_use_count_inc (); +if (!ip_vs_use_count_inc ()) +return -ENOENT ;mutex_lock (&ip_vs_sched_mutex);
net/netfilter/ipvs/ip_vs_sync.c +10 -3
@@ -1762,6 +1762,10 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,IP_VS_DBG (7 ,"Each ip_vs_sync_conn entry needs %zd bytes\n" ,sizeof (struct ip_vs_sync_conn_v0 )); +/* increase the module use count */ +if (!ip_vs_use_count_inc ()) +return -ENOPROTOOPT ; +/* Do not hold one mutex and then to block on another */ for (;;) {rtnl_lock ();
@@ -1892,9 +1896,6 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,mutex_unlock (&ipvs->sync_mutex);rtnl_unlock (); -/* increase the module use count */ -ip_vs_use_count_inc (); -return 0 ; out:
@@ -1924,11 +1925,17 @@ out: }kfree (ti); } + +/* decrease the module use count */ +ip_vs_use_count_dec ();return result; out_early:mutex_unlock (&ipvs->sync_mutex);rtnl_unlock (); + +/* decrease the module use count */ +ip_vs_use_count_dec ();return result; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 86/125 ipvs: move old_secure_tcp into struct netns_ipvs
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit c24b75e0f9239e78105f81c5f03a751641eb07ef ]
syzbot reported the following issue :
BUG: KCSAN: data-race in update_defense_level / update_defense_level
read to 0xffffffff861a6260 of 4 bytes by task 3006 on cpu 1:
update_defense_level+0x621/0xb30 net/netfilter/ipvs/ip_vs_ctl.c:177 defense_work_handler+0x3d/0xd0 net/netfilter/ipvs/ip_vs_ctl.c:225 process_one_work+0x3d4/0x890 kernel/workqueue.c:2269 worker_thread+0xa0/0x800 kernel/workqueue.c:2415 kthread+0x1d4/0x200 drivers/block/aoe/aoecmd.c:1253 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:352
write to 0xffffffff861a6260 of 4 bytes by task 7333 on cpu 0:
update_defense_level+0xa62/0xb30 net/netfilter/ipvs/ip_vs_ctl.c:205 defense_work_handler+0x3d/0xd0 net/netfilter/ipvs/ip_vs_ctl.c:225 process_one_work+0x3d4/0x890 kernel/workqueue.c:2269 worker_thread+0xa0/0x800 kernel/workqueue.c:2415 kthread+0x1d4/0x200 drivers/block/aoe/aoecmd.c:1253 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:352
Reported by Kernel Concurrency Sanitizer on:
CPU: 0 PID: 7333 Comm: kworker/0:5 Not tainted 5.4.0-rc3+ #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: events defense_work_handler
Indeed, old_secure_tcp is currently a static variable, while it needs to be a per netns variable.
--- include/net/ip_vs.h | 1 + net/netfilter/ipvs/ip_vs_ctl.c | 15 +++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-)
include/net/ip_vs.h +1 -0
@@ -885,6 +885,7 @@ struct netns_ipvs {struct delayed_work defense_work;/* Work handler */ int drop_rate;int drop_counter; +int old_secure_tcp;atomic_t dropentry;/* locks in ctl.c */ spinlock_t dropentry_lock;/* drop entry handling */
net/netfilter/ipvs/ip_vs_ctl.c +7 -8
@@ -98,7 +98,6 @@ static bool __ip_vs_addr_is_local_v6(struct net *net,static void update_defense_level (struct netns_ipvs *ipvs) {struct sysinfo i; -static int old_secure_tcp =0 ;int availmem;int nomem;int to_change =-1 ;
@@ -179,35 +178,35 @@ static void update_defense_level(struct netns_ipvs *ipvs)spin_lock (&ipvs->securetcp_lock);switch (ipvs->sysctl_secure_tcp) {case 0 : -if (old_secure_tcp >=2 ) +if (ipvs->old_secure_tcp >=2 ) to_change =0 ;break ;case 1 :if (nomem) { -if (old_secure_tcp <2 ) +if (ipvs->old_secure_tcp <2 ) to_change =1 ; ipvs->sysctl_secure_tcp =2 ; }else { -if (old_secure_tcp >=2 ) +if (ipvs->old_secure_tcp >=2 ) to_change =0 ; }break ;case 2 :if (nomem) { -if (old_secure_tcp <2 ) +if (ipvs->old_secure_tcp <2 ) to_change =1 ; }else { -if (old_secure_tcp >=2 ) +if (ipvs->old_secure_tcp >=2 ) to_change =0 ; ipvs->sysctl_secure_tcp =1 ; }break ;case 3 : -if (old_secure_tcp <2 ) +if (ipvs->old_secure_tcp <2 ) to_change =1 ;break ; } - old_secure_tcp = ipvs->sysctl_secure_tcp; + ipvs->old_secure_tcp = ipvs->sysctl_secure_tcp;if (to_change >=0 )ip_vs_protocol_timeout_change (ipvs, ipvs->sysctl_secure_tcp >1 );
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 87/125 bonding: fix unexpected IFF_BONDING bit unset
In reply to Greg Kroah-HartmanFrom: Taehee Yoo <[email protected]>
[ Upstream commit 65de65d9033750d2cf1b336c9d6e9da3a8b5cc6e ]
The IFF_BONDING means bonding master or bonding slave device. ->ndo_add_slave() sets IFF_BONDING flag and ->ndo_del_slave() unsets IFF_BONDING flag.
bond0<--bond1
Both bond0 and bond1 are bonding device and these should keep having IFF_BONDING flag until they are removed.
But bond1 would lose IFF_BONDING at ->ndo_del_slave() because that routine do not check whether the slave device is the bonding type or not. This patch adds the interface type check routine before removing IFF_BONDING flag.
Test commands:
ip link add bond0 type bond
ip link add bond1 type bond
ip link set bond1 master bond0
ip link set bond1 nomaster
ip link del bond1 type bond
ip link add bond1 type bond
Splat looks like:
[ 226.665555] proc_dir_entry 'bonding/bond1' already registered [ 226.666440] WARNING: CPU: 0 PID: 737 at fs/proc/generic.c:361 proc_register+0x2a9/0x3e0 [ 226.667571] Modules linked in: bonding af_packet sch_fq_codel ip_tables x_tables unix [ 226.668662] CPU: 0 PID: 737 Comm: ip Not tainted 5.4.0-rc3+ #96 [ 226.669508] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 [ 226.670652] RIP: 0010:proc_register+0x2a9/0x3e0 [ 226.671612] Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 39 01 00 00 48 8b 04 24 48 89 ea 48 c7 c7 a0 0b 14 9f 48 8b b0 e 0 00 00 00 e8 07 e7 88 ff <0f> 0b 48 c7 c7 40 2d a5 9f e8 59 d6 23 01 48 8b 4c 24 10 48 b8 00 [ 226.675007] RSP: 0018:ffff888050e17078 EFLAGS: 00010282 [ 226.675761] RAX: dffffc0000000008 RBX: ffff88805fdd0f10 RCX: ffffffff9dd344e2 [ 226.676757] RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffff88806c9f6b8c [ 226.677751] RBP: ffff8880507160f3 R08: ffffed100d940019 R09: ffffed100d940019 [ 226.678761] R10: 0000000000000001 R11: ffffed100d940018 R12: ffff888050716008 [ 226.679757] R13: ffff8880507160f2 R14: dffffc0000000000 R15: ffffed100a0e2c1e [ 226.680758] FS: 00007fdc217cc0c0(0000) GS:ffff88806c800000(0000) knlGS:0000000000000000 [ 226.681886] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 226.682719] CR2: 00007f49313424d0 CR3: 0000000050e46001 CR4: 00000000000606f0 [ 226.683727] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 226.684725] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 226.685681] Call Trace: [ 226.687089] proc_create_seq_private+0xb3/0xf0 [ 226.687778] bond_create_proc_entry+0x1b3/0x3f0 [bonding] [ 226.691458] bond_netdev_event+0x433/0x970 [bonding] [ 226.692139] ? __module_text_address+0x13/0x140 [ 226.692779] notifier_call_chain+0x90/0x160 [ 226.693401] register_netdevice+0x9b3/0xd80 [ 226.694010] ? alloc_netdev_mqs+0x854/0xc10 [ 226.694629] ? netdev_change_features+0xa0/0xa0 [ 226.695278] ? rtnl_create_link+0x2ed/0xad0 [ 226.695849] bond_newlink+0x2a/0x60 [bonding] [ 226.696422] __rtnl_newlink+0xb9f/0x11b0 [ 226.696968] ? rtnl_link_unregister+0x220/0x220
[ ... ]
--- drivers/net/bonding/bond_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/bonding/bond_main.c +4 -2
@@ -1798,7 +1798,8 @@ err_detach:slave_disable_netpoll (new_slave); err_close: - slave_dev->priv_flags &= ~IFF_BONDING ; +if (!netif_is_bond_master (slave_dev)) + slave_dev->priv_flags &= ~IFF_BONDING ;dev_close (slave_dev); err_restore_mac:
@@ -2004,7 +2005,8 @@ static int __bond_release_one(struct net_device *bond_dev,else dev_set_mtu (slave_dev, slave->original_mtu); - slave_dev->priv_flags &= ~IFF_BONDING ; +if (!netif_is_bond_master (slave_dev)) + slave_dev->priv_flags &= ~IFF_BONDING ;bond_free_slave (slave);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 88/125 macsec: fix refcnt leak in module exit routine
In reply to Greg Kroah-HartmanFrom: Taehee Yoo <[email protected]>
[ Upstream commit 2bce1ebed17da54c65042ec2b962e3234bad5b47 ]
When a macsec interface is created, it increases a refcnt to a lower device(real device). when macsec interface is deleted, the refcnt is decreased in macsec_free_netdev(), which is ->priv_destructor() of macsec interface.
The problem scenario is this.
When nested macsec interfaces are exiting, the exit routine of the macsec module makes refcnt leaks.
Test commands:
ip link add dummy0 type dummy
ip link add macsec0 link dummy0 type macsec
ip link add macsec1 link macsec0 type macsec
modprobe -rv macsec
[ 208.629433] unregister_netdevice: waiting for macsec0 to become free. Usage count = 1
Steps of exit routine of macsec module are below.
1. Calls ->dellink() in __rtnl_link_unregister().
2. Checks refcnt and wait refcnt to be 0 if refcnt is not 0 in netdev_run_todo().
3. Calls ->priv_destruvtor() in netdev_run_todo().
Step2 checks refcnt, but step3 decreases refcnt.
So, step2 waits forever.
This patch makes the macsec module do not hold a refcnt of the lower device because it already holds a refcnt of the lower device with netdev_upper_dev_link().
--- drivers/net/macsec.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/net/macsec.c +0 -4
@@ -3008,12 +3008,10 @@ static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = {static void macsec_free_netdev (struct net_device *dev) {struct macsec_dev *macsec =macsec_priv (dev); -struct net_device *real_dev = macsec->real_dev;free_percpu (macsec->stats);free_percpu (macsec->secy.tx_sc.stats); -dev_put (real_dev); }static void macsec_setup (struct net_device *dev)
@@ -3268,8 +3266,6 @@ static int macsec_newlink(struct net *net, struct net_device *dev,if (err <0 )return err; -dev_hold (real_dev); - macsec->nest_level =dev_get_nest_level (real_dev) +1 ;netdev_lockdep_set_classes (dev); lockdep_set_class_and_subclass(&dev->addr_list_lock,
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 89/125 usb: fsl: Check memory resource before releasing it
In reply to Greg Kroah-HartmanFrom: Nikhil Badola <[email protected]>
[ Upstream commit bc1e3a2dd0c9954fd956ac43ca2876bbea018c01 ]
Check memory resource existence before releasing it to avoid NULL pointer dereference
--- drivers/usb/gadget/udc/fsl_udc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/udc/fsl_udc_core.c +1 -1
@@ -2552,7 +2552,7 @@ static int fsl_udc_remove(struct platform_device *pdev)dma_pool_destroy (udc_controller->td_pool);free_irq (udc_controller->irq, udc_controller);iounmap (dr_regs); -if (pdata->operating_mode ==FSL_USB2_DR_DEVICE ) +if (res && (pdata->operating_mode ==FSL_USB2_DR_DEVICE ))release_mem_region (res->start,resource_size (res));/* free udc --wait for the release() finished */
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 90/125 usb: gadget: udc: atmel: Fix interrupt storm in FIFO mode.
In reply to Greg Kroah-HartmanFrom: Cristian Birsan <[email protected]>
[ Upstream commit ba3a1a915c49cc3023e4ddfc88f21e7514e82aa4 ]
Fix interrupt storm generated by endpoints when working in FIFO mode. The TX_COMPLETE interrupt is used only by control endpoints processing. Do not enable it for other types of endpoints.
--- drivers/usb/gadget/udc/atmel_usba_udc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/usb/gadget/udc/atmel_usba_udc.c +4 -2
@@ -436,9 +436,11 @@ static void submit_request(struct usba_ep *ep, struct usba_request *req)next_fifo_transaction (ep, req);if (req->last_transaction) {usba_ep_writel (ep,CTL_DIS ,USBA_TX_PK_RDY ); -usba_ep_writel (ep,CTL_ENB ,USBA_TX_COMPLETE ); +if (ep_is_control (ep)) +usba_ep_writel (ep,CTL_ENB ,USBA_TX_COMPLETE ); }else { -usba_ep_writel (ep,CTL_DIS ,USBA_TX_COMPLETE ); +if (ep_is_control (ep)) +usba_ep_writel (ep,CTL_DIS ,USBA_TX_COMPLETE );usba_ep_writel (ep,CTL_ENB ,USBA_TX_PK_RDY ); } }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 91/125 usb: gadget: composite: Fix possible double free memory bug
In reply to Greg Kroah-HartmanFrom: Chandana Kishori Chiluveru <[email protected]>
[ Upstream commit 1c20c89b0421b52b2417bb0f62a611bc669eda1d ]
composite_dev_cleanup call from the failure of configfs_composite_bind frees up the cdev->os_desc_req and cdev->req. If the previous calls of bind and unbind is successful these will carry stale values.
Consider the below sequence of function calls:configfs_composite_bind()
composite_dev_prepare()
- Allocate cdev->req, cdev->req->buf
composite_os_desc_req_prepare()
- Allocate cdev->os_desc_req, cdev->os_desc_req->bufconfigfs_composite_unbind()
composite_dev_cleanup()
- free the cdev->os_desc_req->buf and cdev->req->buf
Next composition switchconfigfs_composite_bind()
- If it fails goto err_comp_cleanup will call the composite_dev_cleanup() function
composite_dev_cleanup()
- calls kfree up with the stale values of cdev->req->buf and cdev->os_desc_req from the previous configfs_composite_bind call. The free call on these stale values leads to double free.
Hence, Fix this issue by setting request and buffer pointer to NULL after kfree.
--- drivers/usb/gadget/composite.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/gadget/composite.c +4 -0
@@ -2156,14 +2156,18 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)usb_ep_dequeue (cdev->gadget->ep0, cdev->os_desc_req);kfree (cdev->os_desc_req->buf); + cdev->os_desc_req->buf =NULL ;usb_ep_free_request (cdev->gadget->ep0, cdev->os_desc_req); + cdev->os_desc_req =NULL ; }if (cdev->req) {if (cdev->setup_pending)usb_ep_dequeue (cdev->gadget->ep0, cdev->req);kfree (cdev->req->buf); + cdev->req->buf =NULL ;usb_ep_free_request (cdev->gadget->ep0, cdev->req); + cdev->req =NULL ; } cdev->next_string_id =0 ;device_remove_file (&cdev->gadget->dev, &dev_attr_suspended);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 92/125 usb: dwc3: pci: prevent memory leak in dwc3_pci_probe
In reply to Greg Kroah-HartmanFrom: Navid Emamdoost <[email protected]>
[ Upstream commit 9bbfceea12a8f145097a27d7c7267af25893c060 ]
In dwc3_pci_probe a call to platform_device_alloc allocates a device which is correctly put in case of error except one case: when the call to platform_device_add_properties fails it directly returns instead of going to error handling. This commit replaces return with the goto.
--- drivers/usb/dwc3/dwc3-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/dwc3/dwc3-pci.c +1 -1
@@ -256,7 +256,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) ret =platform_device_add_properties (dwc->dwc3, p);if (ret <0 ) -return ret; + goto err; ret =dwc3_pci_quirks (dwc);if (ret)
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 93/125 usb: gadget: configfs: fix concurrent issue between composite APIs
In reply to Greg Kroah-HartmanFrom: Peter Chen <[email protected]>
[ Upstream commit 1a1c851bbd706ea9f3a9756c2d3db28523506d3b ]
We meet several NULL pointer issues if configfs_composite_unbind and composite_setup (or composite_disconnect) are running together. These issues occur when do the function switch stress test, the configfs_compsoite_unbind is called from user mode by
echo "" to /sys/../UDC entry, and meanwhile, the setup interrupt or disconnect interrupt occurs by hardware. The composite_setup will get the cdev from get_gadget_data, but configfs_composite_unbind will set gadget data as NULL, so the NULL pointer issue occurs. This concurrent is hard to reproduce by native kernel, but can be reproduced by android kernel.
In this commit, we introduce one spinlock belongs to structure gadget_info since we can't use the same spinlock in usb_composite_dev due to exclusive running together between composite_setup and configfs_composite_unbind. And one bit flag 'unbind' to indicate the code is at unbind routine, this bit is needed due to we release the lock at during configfs_composite_unbind sometimes, and composite_setup may be run at that time.
Several oops:
oops 1:android_work: sent uevent USB_STATE=CONNECTED
configfs-gadget gadget: super-speed config #1: bandroid_work: sent uevent USB_STATE=CONFIGURED
init: Received control message 'start' for 'adbd' from pid: 3515 (system_server)
Unable to handle kernel NULL pointer dereference at virtual address 0000002a
init: Received control message 'stop' for 'adbd' from pid: 3375 (/vendor/bin/hw/[email protected]) Mem abort info:
Exception class = DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000004
CM = 0, WnR = 0
user pgtable: 4k pages, 48-bit VAs, pgd = ffff8008f1b7f000
[000000000000002a] *pgd=0000000000000000
Internal error: Oops: 96000004 [#1] PREEMPT SMP Modules linked in: CPU: 4 PID: 2457 Comm: irq/125-5b11000 Not tainted 4.14.98-07846-g0b40a9b-dirty #16 Hardware name: Freescale i.MX8QM MEK (DT) task: ffff8008f2a98000 task.stack: ffff00000b7b8000 PC is at composite_setup+0x44/0x1508 LR is at android_setup+0xb8/0x13c pc : [<ffff0000089ffb3c>] lr : [<ffff000008a032fc>] pstate: 800001c5
sp : ffff00000b7bbb80
x29: ffff00000b7bbb80 x28: ffff8008f2a3c010
x27: 0000000000000001 x26: 0000000000000000 [1232/1897]
audit: audit_lost=25791 audit_rate_limit=5 audit_backlog_limit=64
x25: 00000000ffffffa1 x24: ffff8008f2a3c010
audit: rate limit exceeded
x23: 0000000000000409 x22: ffff000009c8e000
x21: ffff8008f7a8b428 x20: ffff00000afae000
x19: ffff0000089ff000 x18: 0000000000000000
x17: 0000000000000000 x16: ffff0000082b7c9c
x15: 0000000000000000 x14: f1866f5b952aca46
x13: e35502e30d44349c x12: 0000000000000008
x11: 0000000000000008 x10: 0000000000000a30
x9 : ffff00000b7bbd00 x8 : ffff8008f2a98a90
x7 : ffff8008f27a9c90 x6 : 0000000000000001
x5 : 0000000000000000 x4 : 0000000000000001
x3 : 0000000000000000 x2 : 0000000000000006
x1 : ffff0000089ff8d0 x0 : 732a010310b9ed00
X7: 0xffff8008f27a9c10:
9c10 00000002 00000000 00000001 00000000 13110000 ffff0000 00000002 00208040 9c30 00000000 00000000 00000000 00000000 00000000 00000005 00000029 00000000 9c50 00051778 00000001 f27a8e00 ffff8008 00000005 00000000 00000078 00000078 9c70 00000078 00000000 09031d48 ffff0000 00100000 00000000 00400000 00000000 9c90 00000001 00000000 00000000 00000000 00000000 00000000 ffefb1a0 ffff8008 9cb0 f27a9ca8 ffff8008 00000000 00000000 b9d88037 00000173 1618a3eb 00000001 9cd0 870a792a 0000002e 16188fe6 00000001 0000242b 00000000 00000000 00000000
using random self ethernet address
9cf0 019a4646 00000000 000547f3 00000000 ecfd6c33 00000002 00000000 using random host ethernet address
00000000
X8: 0xffff8008f2a98a10:
8a10 00000000 00000000 f7788d00 ffff8008 00000001 00000000 00000000 00000000 8a30 eb218000 ffff8008 f2a98000 ffff8008 f2a98000 ffff8008 09885000 ffff0000 8a50 f34df480 ffff8008 00000000 00000000 f2a98648 ffff8008 09c8e000 ffff0000 8a70 fff2c800 ffff8008 09031d48 ffff0000 0b7bbd00 ffff0000 0b7bbd00 ffff0000 8a90 080861bc ffff0000 00000000 00000000 00000000 00000000 00000000 00000000 8ab0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 8ad0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 8af0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
X21: 0xffff8008f7a8b3a8:
b3a8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 b3c8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 b3e8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 b408 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000000 b428 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 b448 0053004d 00540046 00300031 00010030 eb07b520 ffff8008 20011201 00000003 b468 e418d109 0104404e 00010302 00000000 eb07b558 ffff8008 eb07b558 ffff8008 b488 f7a8b488 ffff8008 f7a8b488 ffff8008 f7a8b300 ffff8008 00000000 00000000
X24: 0xffff8008f2a3bf90:
bf90 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 bfb0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 bfd0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 bff0 00000000 00000000 00000000 00000000 f76c8010 ffff8008 f76c8010 ffff8008 c010 00000000 00000000 f2a3c018 ffff8008 f2a3c018 ffff8008 08a067dc ffff0000 c030 f2a5a000 ffff8008 091c3650 ffff0000 f716fd18 ffff8008 f716fe30 ffff8008 c050 f2ce4a30 ffff8008 00000000 00000005 00000000 00000000 095d1568 ffff0000 c070 f76c8010 ffff8008 f2ce4b00 ffff8008 095cac68 ffff0000 f2a5a028 ffff8008
X28: 0xffff8008f2a3bf90:
bf90 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 bfb0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 bfd0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 bff0 00000000 00000000 00000000 00000000 f76c8010 ffff8008 f76c8010 ffff8008 c010 00000000 00000000 f2a3c018 ffff8008 f2a3c018 ffff8008 08a067dc ffff0000 c030 f2a5a000 ffff8008 091c3650 ffff0000 f716fd18 ffff8008 f716fe30 ffff8008 c050 f2ce4a30 ffff8008 00000000 00000005 00000000 00000000 095d1568 ffff0000 c070 f76c8010 ffff8008 f2ce4b00 ffff8008 095cac68 ffff0000 f2a5a028 ffff8008
Process irq/125-5b11000 (pid: 2457, stack limit = 0xffff00000b7b8000)
Call trace: Exception stack(0xffff00000b7bba40 to 0xffff00000b7bbb80)
ba40: 732a010310b9ed00 ffff0000089ff8d0 0000000000000006 0000000000000000
ba60: 0000000000000001 0000000000000000 0000000000000001 ffff8008f27a9c90
ba80: ffff8008f2a98a90 ffff00000b7bbd00 0000000000000a30 0000000000000008
baa0: 0000000000000008 e35502e30d44349c f1866f5b952aca46 0000000000000000
bac0: ffff0000082b7c9c 0000000000000000 0000000000000000 ffff0000089ff000
bae0: ffff00000afae000 ffff8008f7a8b428 ffff000009c8e000 0000000000000409
bb00: ffff8008f2a3c010 00000000ffffffa1 0000000000000000 0000000000000001
bb20: ffff8008f2a3c010 ffff00000b7bbb80 ffff000008a032fc ffff00000b7bbb80
bb40: ffff0000089ffb3c 00000000800001c5 ffff00000b7bbb80 732a010310b9ed00
bb60: ffffffffffffffff ffff0000080f777c ffff00000b7bbb80 ffff0000089ffb3c
[<ffff0000089ffb3c>] composite_setup+0x44/0x1508 [<ffff000008a032fc>] android_setup+0xb8/0x13c [<ffff0000089bd9a8>] cdns3_ep0_delegate_req+0x44/0x70 [<ffff0000089bdff4>] cdns3_check_ep0_interrupt_proceed+0x33c/0x654 [<ffff0000089bca44>] cdns3_device_thread_irq_handler+0x4b0/0x4bc [<ffff0000089b77b4>] cdns3_thread_irq+0x48/0x68 [<ffff000008145bf0>] irq_thread_fn+0x28/0x88 [<ffff000008145e38>] irq_thread+0x13c/0x228 [<ffff0000080fed70>] kthread+0x104/0x130 [<ffff000008085064>] ret_from_fork+0x10/0x18
oops2:composite_disconnect: Calling disconnect on a Gadget that is not connectedandroid_work: did not send uevent (0 0 (null))
init: Received control message 'stop' for 'adbd' from pid: 3359 (/vendor/bin/hw/[email protected])
init: Sending signal 9 to service 'adbd' (pid 22343) process group...
------------[ cut here ]------------ audit: audit_lost=180038 audit_rate_limit=5 audit_backlog_limit=64 audit: rate limit exceeded WARNING: CPU: 0 PID: 3468 at kernel_imx/drivers/usb/gadget/composite.c:2009 composite_disconnect+0x80/0x88 Modules linked in: CPU: 0 PID: 3468 Comm: HWC-UEvent-Thre Not tainted 4.14.98-07846-g0b40a9b-dirty #16 Hardware name: Freescale i.MX8QM MEK (DT) task: ffff8008f2349c00 task.stack: ffff00000b0a8000 PC is at composite_disconnect+0x80/0x88 LR is at composite_disconnect+0x80/0x88 pc : [<ffff0000089ff9b0>] lr : [<ffff0000089ff9b0>] pstate: 600001c5
sp : ffff000008003dd0
x29: ffff000008003dd0 x28: ffff8008f2349c00
x27: ffff000009885018 x26: ffff000008004000
Timeout for IPC response!
x25: ffff000009885018 x24: ffff000009c8e280
x23: ffff8008f2d98010 x22: 00000000000001c0
x21: ffff8008f2d98394 x20: ffff8008f2d98010
x19: 0000000000000000 x18: 0000e3956f4f075a
fxos8700 4-001e: i2c block read acc failed
x17: 0000e395735727e8 x16: ffff00000829f4d4
x15: ffffffffffffffff x14: 7463656e6e6f6320
x13: 746f6e2009090920 x12: 7369207461687420
x11: 7465676461472061 x10: 206e6f207463656e
x9 : 6e6f637369642067 x8 : ffff000009c8e280
x7 : ffff0000086ca6cc x6 : ffff000009f15e78
x5 : 0000000000000000 x4 : 0000000000000000
x3 : ffffffffffffffff x2 : c3f28b86000c3900
x1 : c3f28b86000c3900 x0 : 000000000000004e
X20: 0xffff8008f2d97f90:
7f90 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 7fb0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
libprocessgroup: Failed to kill process cgroup uid 0 pid 22343 in 215ms, 1 processes remain 7fd0
Timeout for IPC response!
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
using random self ethernet address
7ff0 00000000 00000000 00000000 00000000 f76c8010 ffff8008 f76c8010 ffff8008 8010 00000100 00000000 f2d98018 ffff8008 f2d98018 ffff8008 08a067dc
using random host ethernet address
ffff0000
8030 f206d800 ffff8008 091c3650 ffff0000 f7957b18 ffff8008 f7957730 ffff8008 8050 f716a630 ffff8008 00000000 00000005 00000000 00000000 095d1568 ffff0000 8070 f76c8010 ffff8008 f716a800 ffff8008 095cac68 ffff0000 f206d828 ffff8008
X21: 0xffff8008f2d98314:
8314 ffff8008 00000000 00000000 00000000 00000000 00000000 00000000 00000000 8334 00000000 00000000 00000000 00000000 00000000 08a04cf4 ffff0000 00000000 8354 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 8374 00000000 00000000 00000000 00001001 00000000 00000000 00000000 00000000 8394 e4bbe4bb 0f230000 ffff0000 0afae000 ffff0000 ae001000 00000000 f206d400 Timeout for IPC response! 83b4 ffff8008 00000000 00000000 f7957b18 ffff8008 f7957718 ffff8008 f7957018 83d4 ffff8008 f7957118 ffff8008 f7957618 ffff8008 f7957818 ffff8008 f7957918 83f4 ffff8008 f7957d18 ffff8008 00000000 00000000 00000000 00000000 00000000
X23: 0xffff8008f2d97f90:
7f90 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 7fb0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 7fd0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 7ff0 00000000 00000000 00000000 00000000 f76c8010 ffff8008 f76c8010 ffff8008 8010 00000100 00000000 f2d98018 ffff8008 f2d98018 ffff8008 08a067dc ffff0000 8030 f206d800 ffff8008 091c3650 ffff0000 f7957b18 ffff8008 f7957730 ffff8008 8050 f716a630 ffff8008 00000000 00000005 00000000 00000000 095d1568 ffff0000 8070 f76c8010 ffff8008 f716a800 ffff8008 095cac68 ffff0000 f206d828 ffff8008
X28: 0xffff8008f2349b80:
9b80 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9ba0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9bc0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9be0 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9c00 00000022 00000000 ffffffff ffffffff 00010001 00000000 00000000 00000000 9c20 0b0a8000 ffff0000 00000002 00404040 00000000 00000000 00000000 00000000 9c40 00000001 00000000 00000001 00000000 001ebd44 00000001 f390b800 ffff8008 9c60 00000000 00000001 00000070 00000070 00000070 00000000 09031d48 ffff0000
Call trace: Exception stack(0xffff000008003c90 to 0xffff000008003dd0)
3c80: 000000000000004e c3f28b86000c3900
3ca0: c3f28b86000c3900 ffffffffffffffff 0000000000000000 0000000000000000
3cc0: ffff000009f15e78 ffff0000086ca6cc ffff000009c8e280 6e6f637369642067
3ce0: 206e6f207463656e 7465676461472061 7369207461687420 746f6e2009090920
3d00: 7463656e6e6f6320 ffffffffffffffff ffff00000829f4d4 0000e395735727e8
3d20: 0000e3956f4f075a 0000000000000000 ffff8008f2d98010 ffff8008f2d98394
3d40: 00000000000001c0 ffff8008f2d98010 ffff000009c8e280 ffff000009885018
3d60: ffff000008004000 ffff000009885018 ffff8008f2349c00 ffff000008003dd0
3d80: ffff0000089ff9b0 ffff000008003dd0 ffff0000089ff9b0 00000000600001c5
3da0: ffff8008f33f2cd8 0000000000000000 0000ffffffffffff 0000000000000000
init: Received control message 'start' for 'adbd' from pid: 3359 (/vendor/bin/hw/[email protected]) 3dc0: ffff000008003dd0 ffff0000089ff9b0
[<ffff0000089ff9b0>] composite_disconnect+0x80/0x88 [<ffff000008a044d4>] android_disconnect+0x3c/0x68 [<ffff0000089ba9f8>] cdns3_device_irq_handler+0xfc/0x2c8 [<ffff0000089b84c0>] cdns3_irq+0x44/0x94 [<ffff00000814494c>] __handle_irq_event_percpu+0x60/0x24c [<ffff000008144c0c>] handle_irq_event+0x58/0xc0 [<ffff00000814873c>] handle_fasteoi_irq+0x98/0x180 [<ffff000008143a10>] generic_handle_irq+0x24/0x38 [<ffff000008144170>] __handle_domain_irq+0x60/0xac [<ffff0000080819c4>] gic_handle_irq+0xd4/0x17c
--- drivers/usb/gadget/configfs.c | 110 ++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 5 deletions(-)
drivers/usb/gadget/configfs.c +105 -5
@@ -61,6 +61,8 @@ struct gadget_info {bool use_os_desc;char b_vendor_code;char qw_sign[OS_STRING_QW_SIGN_LEN ]; +spinlock_t spinlock; +bool unbind; };static inline struct gadget_info *to_gadget_info (struct config_item *item)
@@ -1244,6 +1246,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,int ret;/* the gi->lock is hold by the caller */ + gi->unbind =0 ; cdev->gadget = gadget;set_gadget_data (gadget, cdev); ret =composite_dev_prepare (composite, cdev);
@@ -1376,31 +1379,128 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) {struct usb_composite_dev *cdev;struct gadget_info *gi; +unsigned long flags;/* the gi->lock is hold by the caller */ cdev =get_gadget_data (gadget); gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + gi->unbind =1 ; +spin_unlock_irqrestore (&gi->spinlock, flags);kfree (otg_desc[0 ]); otg_desc[0 ] =NULL ;purge_configs_funcs (gi);composite_dev_cleanup (cdev);usb_ep_autoconfig_reset (cdev->gadget); +spin_lock_irqsave (&gi->spinlock, flags); cdev->gadget =NULL ;set_gadget_data (gadget,NULL ); +spin_unlock_irqrestore (&gi->spinlock, flags); +} + +static int configfs_composite_setup (struct usb_gadget *gadget, +const struct usb_ctrlrequest *ctrl) +{ +struct usb_composite_dev *cdev; +struct gadget_info *gi; +unsigned long flags; +int ret; + + cdev =get_gadget_data (gadget); +if (!cdev) +return 0 ; + + gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + cdev =get_gadget_data (gadget); +if (!cdev || gi->unbind) { +spin_unlock_irqrestore (&gi->spinlock, flags); +return 0 ; + } + + ret =composite_setup (gadget, ctrl); +spin_unlock_irqrestore (&gi->spinlock, flags); +return ret; +} + +static void configfs_composite_disconnect (struct usb_gadget *gadget) +{ +struct usb_composite_dev *cdev; +struct gadget_info *gi; +unsigned long flags; + + cdev =get_gadget_data (gadget); +if (!cdev) +return ; + + gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + cdev =get_gadget_data (gadget); +if (!cdev || gi->unbind) { +spin_unlock_irqrestore (&gi->spinlock, flags); +return ; + } + +composite_disconnect (gadget); +spin_unlock_irqrestore (&gi->spinlock, flags); +} + +static void configfs_composite_suspend (struct usb_gadget *gadget) +{ +struct usb_composite_dev *cdev; +struct gadget_info *gi; +unsigned long flags; + + cdev =get_gadget_data (gadget); +if (!cdev) +return ; + + gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + cdev =get_gadget_data (gadget); +if (!cdev || gi->unbind) { +spin_unlock_irqrestore (&gi->spinlock, flags); +return ; + } + +composite_suspend (gadget); +spin_unlock_irqrestore (&gi->spinlock, flags); +} + +static void configfs_composite_resume (struct usb_gadget *gadget) +{ +struct usb_composite_dev *cdev; +struct gadget_info *gi; +unsigned long flags; + + cdev =get_gadget_data (gadget); +if (!cdev) +return ; + + gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + cdev =get_gadget_data (gadget); +if (!cdev || gi->unbind) { +spin_unlock_irqrestore (&gi->spinlock, flags); +return ; + } + +composite_resume (gadget); +spin_unlock_irqrestore (&gi->spinlock, flags); }static const struct usb_gadget_driver configfs_driver_template = { .bind = configfs_composite_bind, .unbind = configfs_composite_unbind, - .setup = composite_setup, - .reset = composite_disconnect, - .disconnect = composite_disconnect, + .setup = configfs_composite_setup, + .reset = configfs_composite_disconnect, + .disconnect = configfs_composite_disconnect, - .suspend = composite_suspend, - .resume = composite_resume, + .suspend = configfs_composite_suspend, + .resume = configfs_composite_resume, .max_speed =USB_SPEED_SUPER , .driver = {
Signature · 1 line
2.20.1
Re: [PATCH 4.19 093/125] usb: gadget: configfs: fix concurrent issue between composite APIs
Quoted 22 lines · Greg Kroah-Hartman
From: Peter Chen <[email protected]>
[ Upstream commit
1a1c851bbd706ea9f3a9756c2d3db28523506d3b]We meet several NULL pointer issues if
configfs_composite_unbindandcomposite_setup(orcomposite_disconnect) are running together. These issues occur when do the function switch stress test, theconfigfs_compsoite_unbindis called from user mode by echo "" to/sys/../UDCentry, and meanwhile, the setup interrupt or disconnect interrupt occurs by hardware. Thecomposite_setup+++
b/drivers/usb/gadget/configfs.cdrivers/usb/gadget/configfs.c +2
-0@@ -61,6 +61,8 @@ struct gadget_info {bool use_os_desc;char b_vendor_code;char qw_sign[OS_STRING_QW_SIGN_LEN ]; +spinlock_t spinlock; +bool unbind; };static inline struct gadget_info *to_gadget_info (struct config_item *item)
drivers/usb/gadget/configfs.c static int configfs_composite_bind(struct usb_gadget *gadget, · line 1250
Quoted 5 lines
drivers/usb/gadget/configfs.c +1
-0@@ -1244,6 +1246,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,int ret;/* the gi->lock is hold by the caller */ + gi->unbind =0 ; cdev->gadget = gadget;
Since variable is bool, I'd expect "= false" here?
drivers/usb/gadget/configfs.c static void configfs_composite_unbind(struct usb_gadget *gadget) · line 1384
Quoted 3 lines
drivers/usb/gadget/configfs.c +1
-0+unsigned long flags;/* the gi->lock is hold by the caller */
"is held".
drivers/usb/gadget/configfs.c static void configfs_composite_unbind(struct usb_gadget *gadget) · line 1389
Quoted 4 lines
drivers/usb/gadget/configfs.c +2
-0cdev =get_gadget_data (gadget); gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + gi->unbind =1 ;
= true;
Quoted 5 lines
drivers/usb/gadget/configfs.c +5
-0+static int configfs_composite_setup (struct usb_gadget *gadget, +const struct usb_ctrlrequest *ctrl) +{ +struct usb_composite_dev *cdev; +struct gadget_info *gi;
drivers/usb/gadget/configfs.c static void configfs_composite_unbind(struct usb_gadget *gadget) · line 1417
Quoted 10 lines
drivers/usb/gadget/configfs.c +10
-0+unsigned long flags; +int ret; + + cdev =get_gadget_data (gadget); +if (!cdev) +return 0 ; + + gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + cdev =get_gadget_data (gadget);
cdev already contains required value, why get it second time? (If it needs to be done under lock, comment might be useful...)
Best regards,
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
RE: [PATCH 4.19 093/125] usb: gadget: configfs: fix concurrent issue between composite APIs
Quoted 51 lines
Quoted 19 lines
We meet several NULL pointer issues if
configfs_composite_unbindandcomposite_setup(orcomposite_disconnect) are running together. These issues occur when do the function switch stress test, theconfigfs_compsoite_unbindis called from user mode by echo "" to/sys/../UDCentry, and meanwhile, the setup interrupt or disconnect interrupt occurs by hardware. Thecomposite_setup+++
b/drivers/usb/gadget/configfs.cdrivers/usb/gadget/configfs.c +2
-0@@ -61,6 +61,8 @@ struct gadget_info {bool use_os_desc;char b_vendor_code;char qw_sign[OS_STRING_QW_SIGN_LEN ]; +spinlock_t spinlock; +bool unbind; }; static inline struct gadget_info *to_gadget_info(struct config_itemQuoted 1 line
*item) @@ -1244,6 +1246,7 @@ static int configfs_composite_bind(struct
usb_gadget*gadget,drivers/usb/gadget/configfs.c static int configfs_composite_bind(struct usb_gadget *gadget, · line 1250
Quoted 5 lines
drivers/usb/gadget/configfs.c +1
-0int ret;/* the gi->lock is hold by the caller */ + gi->unbind =0 ; cdev->gadget = gadget;Since variable is bool, I'd expect "= false" here?
drivers/usb/gadget/configfs.c static void configfs_composite_unbind(struct usb_gadget *gadget) · line 1384
Quoted 3 lines
drivers/usb/gadget/configfs.c +1
-0+unsigned long flags;/* the gi->lock is hold by the caller */ "is held".
drivers/usb/gadget/configfs.c static void configfs_composite_unbind(struct usb_gadget *gadget) · line 1389
Quoted 4 lines
drivers/usb/gadget/configfs.c +2
-0cdev =get_gadget_data (gadget); gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + gi->unbind =1 ;= true;
Quoted 9 lines
drivers/usb/gadget/configfs.c +9
-0+static int configfs_composite_setup (struct usb_gadget *gadget, +const struct usb_ctrlrequest *ctrl) { +struct usb_composite_dev *cdev; +struct gadget_info *gi; +unsigned long flags; +int ret; + + cdev =get_gadget_data (gadget); +if (!cdev)
Quoted 9 lines
drivers/usb/gadget/configfs.c static void configfs_composite_unbind(struct usb_gadget *gadget) · line 1417
Quoted 5 lines
drivers/usb/gadget/configfs.c +5
-0+return 0 ; + + gi = container_of(cdev, struct gadget_info, cdev); +spin_lock_irqsave (&gi->spinlock, flags); + cdev =get_gadget_data (gadget);cdev already contains required value, why get it second time? (If it needs to be done under lock, comment might be useful...)
Hi Pavel,
Thanks for comment.
The reason is the cdev may be set to NULL by configfs_composite_unbind through another process, eg, the user wants to disable current USB gadget function, this patch tries to fix such kinds of concurrent issue.
Peter
Greg Kroah-Hartman
maintainerPATCH 94/125 usb: dwc3: remove the call trace of USBx_GFLADJ
In reply to Greg Kroah-HartmanFrom: Yinbo Zhu <[email protected]>
[ Upstream commit a7d9874c6f3fbc8d25cd9ceba35b6822612c4ebf ]
layerscape board sometimes reported some usb call trace, that is due to kernel sent LPM tokerns automatically when it has no pending transfers and think that the link is idle enough to enter L1, which procedure will ask usb register has a recovery,then kernel will compare USBx_GFLADJ and set GFLADJ_30MHZ, GFLADJ_30MHZ_REG until GFLADJ_30MHZ is equal 0x20, if the conditions were met then issue occur, but whatever the conditions whether were met that usb is all need keep GFLADJ_30MHZ of value is 0x20 (xhci spec ask use GFLADJ_30MHZ to adjust any offset from clock source that generates the clock that drives the SOF counter, 0x20 is default value of it)That is normal logic, so need remove the call trace.
--- drivers/usb/dwc3/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/usb/dwc3/core.c +1 -2
@@ -299,8 +299,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) reg =dwc3_readl (dwc->regs,DWC3_GFLADJ ); dft = reg &DWC3_GFLADJ_30MHZ_MASK ; -if (!dev_WARN_ONCE (dwc->dev, dft == dwc->fladj, -"request value same as default, ignoring\n" )) { +if (dft != dwc->fladj) { reg &= ~DWC3_GFLADJ_30MHZ_MASK ; reg |=DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;dwc3_writel (dwc->regs,DWC3_GFLADJ , reg);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 95/125 perf/x86/amd/ibs: Fix reading of the IBS OpData register and thus precise RIP validity
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
[ Upstream commit 317b96bb14303c7998dbcd5bc606bd8038fdd4b4 ]
The loop that reads all the IBS MSRs into *buf stopped one MSR short of reading the IbsOpData register, which contains the RipInvalid status bit.
Fix the offset_max assignment so the MSR gets read, so the RIP invalid evaluation is based on what the IBS h/w output, instead of what was left in memory.
--- arch/x86/events/amd/ibs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/events/amd/ibs.c +1 -1
@@ -625,7 +625,7 @@ fail:if (event->attr.sample_type &PERF_SAMPLE_RAW ) offset_max = perf_ibs->offset_max;else if (check_rip) - offset_max =2 ; + offset_max =3 ;else offset_max =1 ; do {
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 96/125 perf/x86/amd/ibs: Handle erratum #420 only on the affected CPU family (10h)
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
[ Upstream commit e431e79b60603079d269e0c2a5177943b95fa4b6 ]
This saves us writing the IBS control MSR twice when disabling the event.
I searched revision guides for all families since 10h, and did not find occurrence of erratum #420, nor anything remotely similar:
so we isolate the secondary MSR write to family 10h only.
Also unconditionally update the count mask for IBS Op implementations that have read & writeable current count (CurCnt) fields in addition to the MaxCnt field. These bits were reserved on prior implementations, and therefore shouldn't have negative impact.
--- arch/x86/events/amd/ibs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/events/amd/ibs.c +4 -2
@@ -389,7 +389,8 @@ static inline void perf_ibs_disable_event(struct perf_ibs *perf_ibs, struct hw_perf_event *hwc, u64 config) { config &= ~perf_ibs->cnt_mask; -wrmsrl (hwc->config_base, config); +if (boot_cpu_data.x86 ==0x10 ) +wrmsrl (hwc->config_base, config); config &= ~perf_ibs->enable_mask;wrmsrl (hwc->config_base, config); }
@@ -564,7 +565,8 @@ static struct perf_ibs perf_ibs_op = { }, .msr = MSR_AMD64_IBSOPCTL, .config_mask = IBS_OP_CONFIG_MASK, - .cnt_mask = IBS_OP_MAX_CNT, + .cnt_mask =IBS_OP_MAX_CNT |IBS_OP_CUR_CNT | + IBS_OP_CUR_CNT_RAND, .enable_mask = IBS_OP_ENABLE, .valid_mask = IBS_OP_VAL, .max_period = IBS_OP_MAX_CNT << 4,
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 97/125 perf/x86/uncore: Fix event group support
In reply to Greg Kroah-HartmanFrom: Kan Liang <[email protected]>
[ Upstream commit 75be6f703a141b048590d659a3954c4fedd30bba ]
The events in the same group don't start or stop simultaneously. Here is the ftrace when enabling event group for uncore_iio_0:
# perf stat -e "{uncore_iio_0/event=0x1/,uncore_iio_0/event=0xe/}" <idle>-0 [000] d.h. 8959.064832: read_msr: a41, value
b2b0b030 //Read counter reg of IIO unit0 counter0
<idle>-0 [000] d.h. 8959.064835: write_msr: a48, value
400001 //Write Ctrl reg of IIO unit0 counter0 to enable
counter0. <------ Although counter0 is enabled, Unit Ctrl is still
freezed. Nothing will count. We are still good here.
<idle>-0 [000] d.h. 8959.064836: read_msr: a40, value
30100 //Read Unit Ctrl reg of IIO unit0
<idle>-0 [000] d.h. 8959.064838: write_msr: a40, value
30000 //Write Unit Ctrl reg of IIO unit0 to enable all
counters in the unit by clear Freeze bit <------Unit0 is un-freezed.
Counter0 has been enabled. Now it starts counting. But counter1 has not
been enabled yet. The issue starts here.
<idle>-0 [000] d.h. 8959.064846: read_msr: a42, value 0
//Read counter reg of IIO unit0 counter1
<idle>-0 [000] d.h. 8959.064847: write_msr: a49, value 40000e //Write Ctrl reg of IIO unit0 counter1 to enable
counter1. <------ Now, counter1 just starts to count. Counter0 has
been running for a while.
Current code un-freezes the Unit Ctrl right after the first counter is enabled. The subsequent group events always loses some counter values.
Implement pmu_enable and pmu_disable support for uncore, which can help to batch hardware accesses.
No one uses uncore_enable_box and uncore_disable_box. Remove them.
--- arch/x86/events/intel/uncore.c | 44 +++++++++++++++++++++++++++++----- arch/x86/events/intel/uncore.h | 12 ---------- 2 files changed, 38 insertions(+), 18 deletions(-)
arch/x86/events/intel/uncore.c +38 -6
@@ -485,10 +485,8 @@ void uncore_pmu_event_start(struct perf_event *event, int flags)local64_set (&event->hw.prev_count,uncore_read_counter (box, event));uncore_enable_event (box, event); -if (box->n_active ==1 ) { -uncore_enable_box (box); +if (box->n_active ==1 )uncore_pmu_start_hrtimer (box); - } }void uncore_pmu_event_stop (struct perf_event *event,int flags)
@@ -512,10 +510,8 @@ void uncore_pmu_event_stop(struct perf_event *event, int flags)WARN_ON_ONCE (hwc->state &PERF_HES_STOPPED ); hwc->state |=PERF_HES_STOPPED ; -if (box->n_active ==0 ) { -uncore_disable_box (box); +if (box->n_active ==0 )uncore_pmu_cancel_hrtimer (box); - } }if ((flags &PERF_EF_UPDATE ) && !(hwc->state &PERF_HES_UPTODATE )) {
@@ -769,6 +765,40 @@ static int uncore_pmu_event_init(struct perf_event *event)return ret; } +static void uncore_pmu_enable (struct pmu *pmu) +{ +struct intel_uncore_pmu *uncore_pmu; +struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); +if (!uncore_pmu) +return ; + + box =uncore_pmu_to_box (uncore_pmu,smp_processor_id ()); +if (!box) +return ; + +if (uncore_pmu->type->ops->enable_box) + uncore_pmu->type->ops->enable_box (box); +} + +static void uncore_pmu_disable (struct pmu *pmu) +{ +struct intel_uncore_pmu *uncore_pmu; +struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); +if (!uncore_pmu) +return ; + + box =uncore_pmu_to_box (uncore_pmu,smp_processor_id ()); +if (!box) +return ; + +if (uncore_pmu->type->ops->disable_box) + uncore_pmu->type->ops->disable_box (box); +} +static ssize_t uncore_get_attr_cpumask (struct device *dev,struct device_attribute *attr,char *buf) {
@@ -794,6 +824,8 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu) pmu->pmu = (struct pmu ) { .attr_groups = pmu->type->attr_groups, .task_ctx_nr = perf_invalid_context, + .pmu_enable = uncore_pmu_enable, + .pmu_disable = uncore_pmu_disable, .event_init = uncore_pmu_event_init, .add = uncore_pmu_event_add, .del = uncore_pmu_event_del,
arch/x86/events/intel/uncore.h +0 -12
@@ -412,18 +412,6 @@ static inline int uncore_freerunning_hw_config(struct intel_uncore_box *box,return -EINVAL ; } -static inline void uncore_disable_box (struct intel_uncore_box *box) -{ -if (box->pmu->type->ops->disable_box) - box->pmu->type->ops->disable_box (box); -} - -static inline void uncore_enable_box (struct intel_uncore_box *box) -{ -if (box->pmu->type->ops->enable_box) - box->pmu->type->ops->enable_box (box); -} -static inline void uncore_disable_event (struct intel_uncore_box *box,struct perf_event *event) {
Signature · 1 line
2.20.1
Re: [PATCH 4.19 097/125] perf/x86/uncore: Fix event group support
Hi!
arch/x86/events/intel/uncore.c static int uncore_pmu_event_init(struct perf_event *event) · line 775
Quoted 11 lines
arch/x86/events/intel/uncore.c +8
-0return ret; } +static void uncore_pmu_enable (struct pmu *pmu) +{ +struct intel_uncore_pmu *uncore_pmu; +struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); +if (!uncore_pmu) +return ;
AFAICT this test can never trigger.
arch/x86/events/intel/uncore.c static int uncore_pmu_event_init(struct perf_event *event) · line 792
Quoted 8 lines
arch/x86/events/intel/uncore.c +8
-0+static void uncore_pmu_disable (struct pmu *pmu) +{ +struct intel_uncore_pmu *uncore_pmu; +struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); +if (!uncore_pmu) +return ;
And neither can this one.
Best regards,
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 4.19 097/125] perf/x86/uncore: Fix event group support
Quoted 16 lines · Pavel Machek
Hi!
arch/x86/events/intel/uncore.c static int uncore_pmu_event_init(struct perf_event *event) · line 775
Quoted 11 lines
return ret; }arch/x86/events/intel/uncore.c +8
-0+static void uncore_pmu_enable (struct pmu *pmu) +{ +struct intel_uncore_pmu *uncore_pmu; +struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); +if (!uncore_pmu) +return ;AFAICT this test can never trigger.
Quoted 10 lines
arch/x86/events/intel/uncore.c static int uncore_pmu_event_init(struct perf_event *event) · line 792
Quoted 8 lines
arch/x86/events/intel/uncore.c +8
-0+static void uncore_pmu_disable (struct pmu *pmu) +{ +struct intel_uncore_pmu *uncore_pmu; +struct intel_uncore_box *box; + + uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu); +if (!uncore_pmu) +return ;And neither can this one.
I will submit a patch to fix it.
Thanks,
Kan
Greg Kroah-Hartman
maintainerPATCH 98/125 USB: Skip endpoints with 0 maxpacket length
In reply to Greg Kroah-HartmanFrom: Alan Stern <[email protected]>
[ Upstream commit d482c7bb0541d19dea8bff437a9f3c5563b5b2d2 ]
Endpoints with a maxpacket length of 0 are probably useless. They can't transfer any data, and it's not at all unlikely that an HCD will crash or hang when trying to handle an URB for such an endpoint.
Currently the USB core does not check for endpoints having a maxpacket value of 0. This patch adds a check, printing a warning and skipping over any endpoints it catches.
Now, the USB spec does not rule out endpoints having maxpacket = 0. But since they wouldn't have any practical use, there doesn't seem to be any good reason for us to accept them.
--- drivers/usb/core/config.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/core/config.c +5 -0
@@ -348,6 +348,11 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,/* Validate the wMaxPacketSize field */ maxp =usb_endpoint_maxp (&endpoint->desc); +if (maxp ==0 ) { +dev_warn (ddev,"config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n" , + cfgno, inum, asnum, d->bEndpointAddress); + goto skip_to_next_endpoint_or_interface_descriptor; + }/* Find the highest legal maxpacket size for this endpoint */ i =0 ;/* additional transactions per microframe */
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 99/125 USB: ldusb: use unsigned size format specifiers
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
[ Upstream commit 88f6bf3846ee90bf33aa1ce848cd3bfb3229f4a4 ]
A recent info-leak bug manifested itself along with warning about a negative buffer overflow:
ldusb 1-1:0.28: Read buffer overflow, -131383859965943 bytes dropped
when it was really a rather large positive one.
A sanity check that prevents this has now been put in place, but let's fix up the size format specifiers, which should all be unsigned.
--- drivers/usb/misc/ldusb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/usb/misc/ldusb.c +4 -3
@@ -487,7 +487,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, } bytes_to_read =min (count, *actual_buffer);if (bytes_to_read < *actual_buffer) -dev_warn (&dev->intf->dev,"Read buffer overflow, %zd bytes dropped\n" , +dev_warn (&dev->intf->dev,"Read buffer overflow, %zu bytes dropped\n" , *actual_buffer-bytes_to_read);/* copy one interrupt_in_buffer from ring_buffer into userspace */
@@ -562,8 +562,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,/* write the data into interrupt_out_buffer from userspace */ bytes_to_write =min (count, write_buffer_size*dev->interrupt_out_endpoint_size);if (bytes_to_write < count) -dev_warn (&dev->intf->dev,"Write buffer overflow, %zd bytes dropped\n" , count-bytes_to_write); -dev_dbg (&dev->intf->dev,"%s: count = %zd, bytes_to_write = %zd\n" , +dev_warn (&dev->intf->dev,"Write buffer overflow, %zu bytes dropped\n" , + count - bytes_to_write); +dev_dbg (&dev->intf->dev,"%s: count = %zu, bytes_to_write = %zu\n" , __func__, count, bytes_to_write);if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 100/125 usbip: tools: Fix read_usb_vudc_device() error path handling
In reply to Greg Kroah-HartmanFrom: GwanYeong Kim <[email protected]>
[ Upstream commit 28df0642abbf6d66908a2858922a7e4b21cdd8c2 ]
This isn't really accurate right. fread() doesn't always return 0 in error. It could return < number of elements and set errno.
--- tools/usb/usbip/libsrc/usbip_device_driver.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/usb/usbip/libsrc/usbip_device_driver.c +4 -2
@@ -81,7 +81,7 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)FILE *fd =NULL ;struct udev_device *plat;const char *speed; -int ret =0 ; +size_t ret; plat =udev_device_get_parent (sdev); path =udev_device_get_syspath (plat);
@@ -91,8 +91,10 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)if (!fd)return -1 ; ret =fread ((char *) &descr,sizeof (descr),1 , fd); -if (ret <0 ) +if (ret !=1 ) { +err ("Cannot read vudc device descr file: %s" ,strerror (errno)); goto err; + }fclose (fd);copy_descr_attr (dev, &descr, bDeviceClass);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 101/125 RDMA/iw_cxgb4: Avoid freeing skb twice in arp failure case
In reply to Greg Kroah-HartmanFrom: Potnuri Bharat Teja <[email protected]>
[ Upstream commit d4934f45693651ea15357dd6c7c36be28b6da884 ]
_put_ep_safe() and _put_pass_ep_safe() free the skb before it is freed by process_work(). fix double free by freeing the skb only in process_work().
--- drivers/infiniband/hw/cxgb4/cm.c | 2 -- 1 file changed, 2 deletions(-)
drivers/infiniband/hw/cxgb4/cm.c +0 -2
@@ -493,7 +493,6 @@ static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) ep = *((struct c4iw_ep **)(skb->cb +2 *sizeof (void *)));release_ep_resources (ep); -kfree_skb (skb);return 0 ; }
@@ -504,7 +503,6 @@ static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb) ep = *((struct c4iw_ep **)(skb->cb +2 *sizeof (void *)));c4iw_put_ep (&ep->parent_ep->com);release_ep_resources (ep); -kfree_skb (skb);return 0 ; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 102/125 RDMA/hns: Prevent memory leaks of eq->buf_list
In reply to Greg Kroah-HartmanFrom: Lijun Ou <[email protected]>
[ Upstream commit b681a0529968d2261aa15d7a1e78801b2c06bb07 ]
eq->buf_list->buf and eq->buf_list should also be freed when eqe_hop_num is set to 0, or there will be memory leaks.
--- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/infiniband/hw/hns/hns_roce_hw_v2.c +3 -3
@@ -4572,9 +4572,9 @@ static void hns_roce_v2_free_eq(struct hns_roce_dev *hr_dev,return ; } -if (eq->buf_list) -dma_free_coherent (hr_dev->dev, buf_chk_sz, - eq->buf_list->buf, eq->buf_list->map); +dma_free_coherent (hr_dev->dev, buf_chk_sz, eq->buf_list->buf, + eq->buf_list->map); +kfree (eq->buf_list); } static void hns_roce_config_eqc(struct hns_roce_dev *hr_dev,
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 103/125 scsi: qla2xxx: stop timer in shutdown path
In reply to Greg Kroah-HartmanFrom: Nicholas Piggin <[email protected]>
[ Upstream commit d3566abb1a1e7772116e4d50fb6a58d19c9802e5 ]
In shutdown/reboot paths, the timer is not stopped:
qla2x00_shutdown
pci_device_shutdown
device_shutdown
kernel_restart_prepare
kernel_restart
sys_reboot
This causes lockups (on powerpc) when firmware config space access calls are interrupted by smp_send_stop later in reboot.
--- drivers/scsi/qla2xxx/qla_os.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/scsi/qla2xxx/qla_os.c +4 -0
@@ -3496,6 +3496,10 @@ qla2x00_shutdown(struct pci_dev *pdev)qla2x00_try_to_stop_firmware (vha); } +/* Disable timer */ +if (vha->timer_active) +qla2x00_stop_timer (vha); +/* Turn adapter off line */ vha->flags.online =0 ;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 104/125 nvme-multipath: fix possible io hang after ctrl reconnect
In reply to Greg Kroah-HartmanFrom: Anton Eidelman <[email protected]>
[ Upstream commit af8fd0424713a2adb812d10d55e86718152cf656 ]
The following scenario results in an IO hang:
1) ctrl completes a request with NVME_SC_ANA_TRANSITION. NVME_NS_ANA_PENDING bit in ns->flags is set and ana_work is triggered.
2) ana_work: nvme_read_ana_log() tries to get the ANA log page from the ctrl. This fails because ctrl disconnects.
Therefore nvme_update_ns_ana_state() is not called
and NVME_NS_ANA_PENDING bit in ns->flags is not cleared.
3) ctrl reconnects: nvme_mpath_init(ctrl,...) calls nvme_read_ana_log(ctrl, groups_only=true).
However, nvme_update_ana_state() does not update namespaces because nr_nsids = 0 (due to groups_only mode).
4) scan_work calls nvme_validate_ns() finds the ns and re-validates OK.
Result:
The ctrl is now live but NVME_NS_ANA_PENDING bit in ns->flags is still set. Consequently ctrl will never be considered a viable path by __nvme_find_path(). IO will hang if ctrl is the only or the last path to the namespace.
More generally, while ctrl is reconnecting, its ANA state may change. And because nvme_mpath_init() requests ANA log in groups_only mode, these changes are not propagated to the existing ctrl namespaces. This may result in a mal-function or an IO hang.
Solution:nvme_mpath_init() will nvme_read_ana_log() with groups_only set to false. This will not harm the new ctrl case (no namespaces present), and will make sure the ANA state of namespaces gets updated after reconnect.
Note: Another option would be for nvme_mpath_init() to invoke nvme_parse_ana_log(..., nvme_set_ns_ana_state) for each existing namespace.
--- drivers/nvme/host/multipath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/multipath.c +1 -1
@@ -575,7 +575,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) goto out; } - error =nvme_read_ana_log (ctrl, true); + error =nvme_read_ana_log (ctrl, false);if (error) goto out_free_ana_log_buf;return 0 ;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 105/125 fjes: Handle workqueue allocation failure
In reply to Greg Kroah-HartmanFrom: Will Deacon <[email protected]>
[ Upstream commit 85ac30fa2e24f628e9f4f9344460f4015d33fd7d ]
In the highly unlikely event that we fail to allocate either of the "/txrx" or "/control" workqueues, we should bail cleanly rather than blindly march on with NULL queue pointer(s) installed in the 'fjes_adapter' instance.
--- drivers/net/fjes/fjes_main.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
drivers/net/fjes/fjes_main.c +14 -1
@@ -1252,8 +1252,17 @@ static int fjes_probe(struct platform_device *plat_dev) adapter->open_guard = false; adapter->txrx_wq =alloc_workqueue (DRV_NAME "/txrx" ,WQ_MEM_RECLAIM ,0 ); +if (unlikely (!adapter->txrx_wq)) { + err = -ENOMEM ; + goto err_free_netdev; + } + adapter->control_wq =alloc_workqueue (DRV_NAME "/control" ,WQ_MEM_RECLAIM ,0 ); +if (unlikely (!adapter->control_wq)) { + err = -ENOMEM ; + goto err_free_txrx_wq; + }INIT_WORK (&adapter->tx_stall_task, fjes_tx_stall_task); INIT_WORK(&adapter->raise_intr_rxdata_task,
@@ -1270,7 +1279,7 @@ static int fjes_probe(struct platform_device *plat_dev) hw->hw_res.irq =platform_get_irq (plat_dev,0 ); err =fjes_hw_init (&adapter->hw);if (err) - goto err_free_netdev; + goto err_free_control_wq;/* setup MAC address (02:00:00:00:00:[epid])*/ netdev->dev_addr[0 ] =2 ;
@@ -1292,6 +1301,10 @@ static int fjes_probe(struct platform_device *plat_dev) err_hw_exit:fjes_hw_exit (&adapter->hw); +err_free_control_wq: +destroy_workqueue (adapter->control_wq); +err_free_txrx_wq: +destroy_workqueue (adapter->txrx_wq); err_free_netdev:free_netdev (netdev); err_out:
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 106/125 net: hisilicon: Fix "Trying to free already-free IRQ"
In reply to Greg Kroah-HartmanFrom: Jiangfeng Xiao <[email protected]>
[ Upstream commit 63a41746827cb16dc6ad0d4d761ab4e7dda7a0c3 ]
When rmmod hip04_eth.ko, we can get the following warning:
Task track: rmmod(1623)>bash(1591)>login(1581)>init(1)
------------[ cut here ]------------ WARNING: CPU: 0 PID: 1623 at kernel/irq/manage.c:1557 __free_irq+0xa4/0x2ac() Trying to free already-free IRQ 200 Modules linked in: ping(O) pramdisk(O) cpuinfo(O) rtos_snapshot(O) interrupt_ctrl(O) mtdblock mtd_blkdevrtfs nfs_acl nfs lockd grace sunrpc xt_tcpudp ipt_REJECT iptable_filter ip_tables x_tables nf_reject_ipv CPU: 0 PID: 1623 Comm: rmmod Tainted: G O 4.4.193 #1 Hardware name: Hisilicon A15 [<c020b408>] (rtos_unwind_backtrace) from [<c0206624>] (show_stack+0x10/0x14) [<c0206624>] (show_stack) from [<c03f2be4>] (dump_stack+0xa0/0xd8) [<c03f2be4>] (dump_stack) from [<c021a780>] (warn_slowpath_common+0x84/0xb0) [<c021a780>] (warn_slowpath_common) from [<c021a7e8>] (warn_slowpath_fmt+0x3c/0x68) [<c021a7e8>] (warn_slowpath_fmt) from [<c026876c>] (__free_irq+0xa4/0x2ac) [<c026876c>] (__free_irq) from [<c0268a14>] (free_irq+0x60/0x7c) [<c0268a14>] (free_irq) from [<c0469e80>] (release_nodes+0x1c4/0x1ec) [<c0469e80>] (release_nodes) from [<c0466924>] (__device_release_driver+0xa8/0x104) [<c0466924>] (__device_release_driver) from [<c0466a80>] (driver_detach+0xd0/0xf8) [<c0466a80>] (driver_detach) from [<c0465e18>] (bus_remove_driver+0x64/0x8c) [<c0465e18>] (bus_remove_driver) from [<c02935b0>] (SyS_delete_module+0x198/0x1e0) [<c02935b0>] (SyS_delete_module) from [<c0202ed0>] (__sys_trace_return+0x0/0x10) ---[ end trace bb25d6123d849b44 ]---
Currently "rmmod hip04_eth.ko" call free_irq more than once as devres_release_all and hip04_remove both call free_irq. This results in a 'Trying to free already-free IRQ' warning. To solve the problem free_irq has been moved out of hip04_remove.
--- drivers/net/ethernet/hisilicon/hip04_eth.c | 1 - 1 file changed, 1 deletion(-)
drivers/net/ethernet/hisilicon/hip04_eth.c +0 -1
@@ -945,7 +945,6 @@ static int hip04_remove(struct platform_device *pdev)hip04_free_ring (ndev, d);unregister_netdev (ndev); -free_irq (ndev->irq, ndev);of_node_put (priv->phy_node);cancel_work_sync (&priv->tx_timeout_task);free_netdev (ndev);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 107/125 net: mscc: ocelot: fix vlan_filtering when enslaving to bridge before link is up
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
[ Upstream commit 1c44ce560b4de639f237b458be1729489ff44d0a ]
Background information: the driver operates the hardware in a mode where a single VLAN can be transmitted as untagged on a particular egress port. That is the "native VLAN on trunk port" use case. Its value is held in port->vid.
Consider the following command sequence (no network manager, all interfaces are down, debugging prints added by me):
$ ip link add dev br0 type bridge vlan_filtering 1 $ ip link set dev swp0 master br0
Kernel code path during last command:
br_add_slave -> ocelot_netdevice_port_event (NETDEV_CHANGEUPPER):
[ 21.401901] ocelot_vlan_port_apply: port 0 vlan aware 0 pvid 0 vid 0
br_add_slave -> nbp_vlan_init -> switchdev_port_attr_set -> ocelot_port_attr_set (SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING):
[ 21.413335] ocelot_vlan_port_apply: port 0 vlan aware 1 pvid 0 vid 0
br_add_slave -> nbp_vlan_init -> nbp_vlan_add -> br_switchdev_port_vlan_add -> switchdev_port_obj_add -> ocelot_port_obj_add -> ocelot_vlan_vid_add
[ 21.667421] ocelot_vlan_port_apply: port 0 vlan aware 1 pvid 1 vid 1
So far so good. The bridge has replaced the driver's default pvid used in standalone mode (0) with its own default_pvid (1). The port's vid (native VLAN) has also changed from 0 to 1.
$ ip link set dev swp0 up
[ 31.722956] 8021q: adding VLAN 0 to HW filter on device swp0 do_setlink -> dev_change_flags -> vlan_vid_add -> ocelot_vlan_rx_add_vid -> ocelot_vlan_vid_add: [ 31.728700] ocelot_vlan_port_apply: port 0 vlan aware 1 pvid 1 vid 0
The 8021q module uses the .ndo_vlan_rx_add_vid API on .ndo_open to make ports be able to transmit and receive 802.1p-tagged traffic by default. This API is supposed to offload a VLAN sub-interface, which for a switch port means to add a VLAN that is not a pvid, and tagged on egress.
But the driver implementation of .ndo_vlan_rx_add_vid is wrong: it adds back vid 0 as "egress untagged". Now back to the initial paragraph:
there is a single untagged VID that the driver keeps track of, and that has just changed from 1 (the pvid) to 0. So this breaks the bridge core's expectation, because it has changed vid 1 from untagged to tagged, when what the user sees is.
$ bridge vlan port vlan ids swp0 1 PVID Egress Untagged
br0 1 PVID Egress Untagged
But curiously, instead of manifesting itself as "untagged and pvid-tagged traffic gets sent as tagged on egress", the bug:
- is hidden when vlan_filtering=0
- manifests as dropped traffic when vlan_filtering=1, due to this setting:
if (port->vlan_aware && !port->vid) /* If port is vlan-aware and tagged, drop untagged and priority * tagged frames. */ val |= ANA_PORT_DROP_CFG_DROP_UNTAGGED_ENA | ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA | ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA;
which would have made sense if it weren't for this bug. The setting's intention was "this is a trunk port with no native VLAN, so don't accept untagged traffic". So the driver was never expecting to set VLAN 0 as the value of the native VLAN, 0 was just encoding for "invalid".
So the fix is to not send 802.1p traffic as untagged, because that would change the port's native vlan to 0, unbeknownst to the bridge, and trigger unexpected code paths in the driver.
--- drivers/net/ethernet/mscc/ocelot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mscc/ocelot.c +1 -1
@@ -886,7 +886,7 @@ end:static int ocelot_vlan_rx_add_vid (struct net_device *dev,__be16 proto,u16 vid) { -return ocelot_vlan_vid_add (dev, vid, false, true); +return ocelot_vlan_vid_add (dev, vid, false, false); } static int ocelot_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 108/125 net: mscc: ocelot: refuse to overwrite the ports native vlan
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
[ Upstream commit b9cd75e6689560140dadaed98eb4b41aad75d55d ]
The switch driver keeps a "vid" variable per port, which signifies _the_ VLAN ID that is stripped on that port's egress (aka the native VLAN on a trunk port).
That is the way the hardware is designed (mostly). The port->vid is programmed into REW:PORT:PORT_VLAN_CFG:PORT_VID and the rewriter is told to send all traffic as tagged except the one having port->vid.
There exists a possibility of finer-grained egress untagging decisions:
using the VCAP IS1 engine, one rule can be added to match every VLAN-tagged frame whose VLAN should be untagged, and set POP_CNT=1 as action. However, the IS1 can hold at most 512 entries, and the VLANs are in the order of 6 * 4096.
So the code is fine for now. But this sequence of commands:
$ bridge vlan add dev swp0 vid 1 pvid untagged $ bridge vlan add dev swp0 vid 2 untagged
makes untagged and pvid-tagged traffic be sent out of swp0 as tagged with VID 1, despite user's request.
Prevent that from happening. The user should temporarily remove the existing untagged VLAN (1 in this case), add it back as tagged, and then add the new untagged VLAN (2 in this case).
--- drivers/net/ethernet/mscc/ocelot.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/net/ethernet/mscc/ocelot.c +8 -1
@@ -253,8 +253,15 @@ static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid, port->pvid = vid;/* Untagged egress vlan clasification */ -if (untagged) +if (untagged && port->vid != vid) { +if (port->vid) { +dev_err (ocelot->dev, +"Port already has a native VLAN: %d\n" , + port->vid); +return -EBUSY ; + } port->vid = vid; + }ocelot_vlan_port_apply (ocelot, port);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 109/125 iommu/amd: Apply the same IVRS IOAPIC workaround to Acer Aspire A315-41
In reply to Greg Kroah-HartmanFrom: Takashi Iwai <[email protected]>
[ Upstream commit ad3e8da2d422c63c13819a53d3c5ea9312cc0b9d ]
Acer Aspire A315-41 requires the very same workaround as the existing quirk for Dell Latitude 5495. Add the new entry for that.
--- drivers/iommu/amd_iommu_quirks.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/iommu/amd_iommu_quirks.c +13 -0
@@ -73,6 +73,19 @@ static const struct dmi_system_id ivrs_quirks[] __initconst = { }, .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495], }, + { +/* +* Acer Aspire A315-41 requires the very same workaround as +* Dell Latitude 5495 +*/ + .callback = ivrs_ioapic_quirk_cb, + .ident = "Acer Aspire A315-41", + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"Acer" ), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-41"), + }, + .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495], + }, { .callback = ivrs_ioapic_quirk_cb, .ident = "Lenovo ideapad 330S-15ARR",
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 110/125 drm/amdgpu: If amdgpu_ib_schedule fails return back the error.
In reply to Greg Kroah-HartmanFrom: Andrey Grodzovsky <[email protected]>
[ Upstream commit 57c0f58e9f562089de5f0b60da103677d232374c ]
Use ERR_PTR to return back the error happened during amdgpu_ib_schedule.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +3 -1
@@ -203,7 +203,7 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)struct amdgpu_ring *ring =to_amdgpu_ring (sched_job->sched);struct dma_fence *fence =NULL , *finished;struct amdgpu_job *job; -int r; +int r =0 ; job =to_amdgpu_job (sched_job); finished = &job->base.s_fence->finished;
@@ -228,6 +228,8 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) job->fence =dma_fence_get (fence);amdgpu_job_free_resources (job); + + fence = r ?ERR_PTR (r) : fence;return fence; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 111/125 drm/amd/display: Passive DP->HDMI dongle detection fix
In reply to Greg Kroah-HartmanFrom: Michael Strauss <[email protected]>
[ Upstream commit bc2fde42e2418808dbfc04de1a6da91d7d31cf1a ]
[WHY]i2c_read is called to differentiate passive DP->HDMI and DP->DVI-D dongles The call is expected to fail in DVI-D case but pass in HDMI case Some HDMI dongles have a chance to fail as well, causing misdetection as DVI-D
[HOW]
Retry i2c_read to ensure failed result is valid
--- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +18 -6
@@ -433,6 +433,7 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(enum display_dongle_type *dongle = &sink_cap->dongle_type;uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE ];bool is_type2_dongle = false; +int retry_count =2 ;struct dp_hdmi_dongle_signature_data *dongle_signature;/* Assume we have no valid DP passive dongle connected */
@@ -445,13 +446,24 @@ void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( DP_HDMI_DONGLE_ADDRESS, type2_dongle_buf, sizeof(type2_dongle_buf))) { - *dongle =DISPLAY_DONGLE_DP_DVI_DONGLE ; - sink_cap->max_hdmi_pixel_clock =DP_ADAPTOR_DVI_MAX_TMDS_CLK ; +/* Passive HDMI dongles can sometimes fail here without retrying*/ +while (retry_count >0 ) { +if (i2c_read (ddc, +DP_HDMI_DONGLE_ADDRESS , + type2_dongle_buf, +sizeof (type2_dongle_buf))) +break ; + retry_count--; + } +if (retry_count ==0 ) { + *dongle =DISPLAY_DONGLE_DP_DVI_DONGLE ; + sink_cap->max_hdmi_pixel_clock =DP_ADAPTOR_DVI_MAX_TMDS_CLK ; -CONN_DATA_DETECT (ddc->link, type2_dongle_buf,sizeof (type2_dongle_buf), -"DP-DVI passive dongle %dMhz: " , -DP_ADAPTOR_DVI_MAX_TMDS_CLK /1000 ); -return ; +CONN_DATA_DETECT (ddc->link, type2_dongle_buf,sizeof (type2_dongle_buf), +"DP-DVI passive dongle %dMhz: " , +DP_ADAPTOR_DVI_MAX_TMDS_CLK /1000 ); +return ; + } }/* Check if Type 2 dongle.*/
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 112/125 hv_netvsc: Fix error handling in netvsc_attach()
In reply to Greg Kroah-HartmanFrom: Haiyang Zhang <[email protected]>
[ Upstream commit 719b85c336ed35565d0f3982269d6f684087bb00 ]
If rndis_filter_open() fails, we need to remove the rndis device created in earlier steps, before returning an error code. Otherwise, the retry of netvsc_attach() from its callers will fail and hang.
--- drivers/net/hyperv/netvsc_drv.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/net/hyperv/netvsc_drv.c +8 -1
@@ -993,7 +993,7 @@ static int netvsc_attach(struct net_device *ndev,if (netif_running (ndev)) { ret =rndis_filter_open (nvdev);if (ret) -return ret; + goto err; rdev = nvdev->extension;if (!rdev->link_state)
@@ -1001,6 +1001,13 @@ static int netvsc_attach(struct net_device *ndev, }return 0 ; + +err: +netif_device_detach (ndev); + +rndis_filter_device_remove (hdev, nvdev); + +return ret; } static int netvsc_set_channels(struct net_device *net,
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 113/125 usb: dwc3: gadget: fix race when disabling ep with cancelled xfers
In reply to Greg Kroah-HartmanFrom: Felipe Balbi <[email protected]>
[ Upstream commit d8eca64eec7103ab1fbabc0a187dbf6acfb2af93 ]
When disabling an endpoint which has cancelled requests, we should make sure to giveback requests that are currently pending in the cancelled list, otherwise we may fall into a situation where command completion interrupt fires after endpoint has been disabled, therefore causing a splat.
--- drivers/usb/dwc3/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/dwc3/gadget.c +6 -0
@@ -698,6 +698,12 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)dwc3_gadget_giveback (dep, req, -ESHUTDOWN ); } + +while (!list_empty (&dep->cancelled_list)) { + req =next_request (&dep->cancelled_list); + +dwc3_gadget_giveback (dep, req, -ESHUTDOWN ); + } }/**
Signature · 1 line
2.20.1
Re: [PATCH 4.19 113/125] usb: dwc3: gadget: fix race when disabling ep with cancelled xfers
Hi!
Quoted 25 lines
From: Felipe Balbi <[email protected]>
[ Upstream commit
d8eca64eec7103ab1fbabc0a187dbf6acfb2af93]When disabling an endpoint which has cancelled requests, we should make sure to giveback requests that are currently pending in the cancelled list, otherwise we may fall into a situation where command completion interrupt fires after endpoint has been disabled, therefore causing a splat.
Fixes fec9095bdef4 "usb: dwc3: gadget: remove wait_end_transfer"Reported-by Roger Quadros <[email protected]>Signed-off-by Felipe Balbi <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- drivers/usb/dwc3/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+)drivers/usb/dwc3/gadget.c +0
-0
drivers/usb/dwc3/gadget.c static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) · line 707
Quoted 10 lines
drivers/usb/dwc3/gadget.c +6
-0@@ -698,6 +698,12 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)dwc3_gadget_giveback (dep, req, -ESHUTDOWN ); } + +while (!list_empty (&dep->cancelled_list)) { + req =next_request (&dep->cancelled_list); + +dwc3_gadget_giveback (dep, req, -ESHUTDOWN ); + } }
This is third copy of a loop. Perhaps it is time to create a helper?
Best regards,
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Greg Kroah-Hartman
maintainerPATCH 114/125 NFSv4: Dont allow a cached open with a revoked delegation
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
[ Upstream commit be3df3dd4c70ee020587a943a31b98a0fb4b6424 ]
If the delegation is marked as being revoked, we must not use it for cached opens.
--- fs/nfs/delegation.c | 10 ++++++++++ fs/nfs/delegation.h | 1 + fs/nfs/nfs4proc.c | 7 ++----- 3 files changed, 13 insertions(+), 5 deletions(-)
fs/nfs/delegation.c +10 -0
@@ -54,6 +54,16 @@ nfs4_is_valid_delegation(const struct nfs_delegation *delegation,return false; } +struct nfs_delegation *nfs4_get_valid_delegation (const struct inode *inode) +{ +struct nfs_delegation *delegation; + + delegation =rcu_dereference (NFS_I (inode)->delegation); +if (nfs4_is_valid_delegation (delegation,0 )) +return delegation; +return NULL ; +} +static int nfs4_do_check_delegation (struct inode *inode,fmode_t flags,bool mark) {
fs/nfs/delegation.h +1 -0
@@ -66,6 +66,7 @@ int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state,bool nfs4_copy_delegation_stateid (struct inode *inode,fmode_t flags,nfs4_stateid *dst,struct rpc_cred **cred);bool nfs4_refresh_delegation_stateid (nfs4_stateid *dst,struct inode *inode); +struct nfs_delegation *nfs4_get_valid_delegation (const struct inode *inode);void nfs_mark_delegation_referenced (struct nfs_delegation *delegation);int nfs4_have_delegation (struct inode *inode,fmode_t flags);int nfs4_check_delegation (struct inode *inode,fmode_t flags);
fs/nfs/nfs4proc.c +2 -5
@@ -1393,8 +1393,6 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode,return 0 ;if ((delegation->type & fmode) != fmode)return 0 ; -if (test_bit (NFS_DELEGATION_RETURNING , &delegation->flags)) -return 0 ;switch (claim) {case NFS4_OPEN_CLAIM_NULL :case NFS4_OPEN_CLAIM_FH :
@@ -1751,7 +1749,6 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmostatic struct nfs4_state *nfs4_try_open_cached (struct nfs4_opendata *opendata) {struct nfs4_state *state = opendata->state; -struct nfs_inode *nfsi =NFS_I (state->inode);struct nfs_delegation *delegation;int open_mode = opendata->o_arg.open_flags;fmode_t fmode = opendata->o_arg.fmode;
@@ -1768,7 +1765,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) }spin_unlock (&state->owner->so_lock);rcu_read_lock (); - delegation =rcu_dereference (nfsi->delegation); + delegation =nfs4_get_valid_delegation (state->inode);if (!can_open_delegated (delegation, fmode, claim)) {rcu_read_unlock ();break ;
@@ -2293,7 +2290,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) data->o_arg.open_flags, claim)) goto out_no_action;rcu_read_lock (); - delegation =rcu_dereference (NFS_I (data->state->inode)->delegation); + delegation =nfs4_get_valid_delegation (data->state->inode);if (can_open_delegated (delegation, data->o_arg.fmode, claim)) goto unlock_no_action;rcu_read_unlock ();
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 115/125 net: ethernet: arc: add the missed clk_disable_unprepare
In reply to Greg Kroah-HartmanFrom: Chuhong Yuan <[email protected]>
[ Upstream commit 4202e219edd6cc164c042e16fa327525410705ae ]
The remove misses to disable and unprepare priv->macclk like what is done when probe fails.
Add the missed call in remove.
--- drivers/net/ethernet/arc/emac_rockchip.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/arc/emac_rockchip.c +3 -0
@@ -265,6 +265,9 @@ static int emac_rockchip_remove(struct platform_device *pdev)if (priv->regulator)regulator_disable (priv->regulator); +if (priv->soc_data->need_div_macclk) +clk_disable_unprepare (priv->macclk); +free_netdev (ndev);return err; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 116/125 igb: Fix constant media auto sense switching when no cable is connected
In reply to Greg Kroah-HartmanFrom: Manfred Rudigier <[email protected]>
[ Upstream commit 8d5cfd7f76a2414e23c74bb8858af7540365d985 ]
At least on the i350 there is an annoying behavior that is maybe also present on 82580 devices, but was probably not noticed yet as MAS is not widely used.
If no cable is connected on both fiber/copper ports the media auto sense code will constantly swap between them as part of the watchdog task and produce many unnecessary kernel log messages.
The swap code responsible for this behavior (switching to fiber) should not be executed if the current media type is copper and there is no signal detected on the fiber port. In this case we can safely wait until the AUTOSENSE_EN bit is cleared.
--- drivers/net/ethernet/intel/igb/igb_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/igb/igb_main.c +2 -1
@@ -2064,7 +2064,8 @@ static void igb_check_swap_media(struct igb_adapter *adapter)if ((hw->phy.media_type == e1000_media_type_copper) && (!(connsw &E1000_CONNSW_AUTOSENSE_EN ))) { swap_now = true; - }else if (!(connsw &E1000_CONNSW_SERDESD )) { + }else if ((hw->phy.media_type != e1000_media_type_copper) && + !(connsw &E1000_CONNSW_SERDESD )) {/* copper signal takes time to appear */ if (adapter->copper_tries <4 ) { adapter->copper_tries++;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 117/125 e1000: fix memory leaks
In reply to Greg Kroah-HartmanFrom: Wenwen Wang <[email protected]>
[ Upstream commit 8472ba62154058b64ebb83d5f57259a352d28697 ]
In e1000_set_ringparam(), 'tx_old' and 'rx_old' are not deallocated if e1000_up() fails, leading to memory leaks. Refactor the code to fix this issue.
--- drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/net/ethernet/intel/e1000/e1000_ethtool.c +3 -4
@@ -607,6 +607,7 @@ static int e1000_set_ringparam(struct net_device *netdev,for (i =0 ; i < adapter->num_rx_queues; i++) rxdr[i].count = rxdr->count; + err =0 ;if (netif_running (adapter->netdev)) {/* Try to get new resources before deleting old */ err =e1000_setup_all_rx_resources (adapter);
@@ -627,14 +628,13 @@ static int e1000_set_ringparam(struct net_device *netdev, adapter->rx_ring = rxdr; adapter->tx_ring = txdr; err =e1000_up (adapter); -if (err) - goto err_setup; }kfree (tx_old);kfree (rx_old);clear_bit (__E1000_RESETTING, &adapter->flags); -return 0 ; +return err; + err_setup_tx:e1000_free_all_rx_resources (adapter); err_setup_rx:
@@ -646,7 +646,6 @@ err_alloc_rx: err_alloc_tx:if (netif_running (adapter->netdev))e1000_up (adapter); -err_setup:clear_bit (__E1000_RESETTING, &adapter->flags);return err; }
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 118/125 pinctrl: intel: Avoid potential glitches if pin is in GPIO mode
In reply to Greg Kroah-HartmanFrom: Andy Shevchenko <[email protected]>
[ Upstream commit 29c2c6aa32405dfee4a29911a51ba133edcedb0f ]
When consumer requests a pin, in order to be on the safest side, we switch it first to GPIO mode followed by immediate transition to the input state. Due to posted writes it's luckily to be a single I/O transaction.
However, if firmware or boot loader already configures the pin to the GPIO mode, user expects no glitches for the requested pin. We may check if the pin is pre-configured and leave it as is till the actual consumer toggles its state to avoid glitches.
Depends-on: f5a26acf0162 ("pinctrl: intel: Initialize GPIO properly when used through irqchip")
--- drivers/pinctrl/intel/pinctrl-intel.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
drivers/pinctrl/intel/pinctrl-intel.c +20 -1
@@ -49,6 +49,7 @@#define PADCFG0_GPIROUTNMI BIT(17)#define PADCFG0_PMODE_SHIFT 10#define PADCFG0_PMODE_MASK (0xf << PADCFG0_PMODE_SHIFT) +#define PADCFG0_PMODE_GPIO 0#define PADCFG0_GPIORXDIS BIT(9)#define PADCFG0_GPIOTXDIS BIT(8)#define PADCFG0_GPIORXSTATE BIT(1)
@@ -301,7 +302,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, cfg1 =readl (intel_get_padcfg (pctrl, pin,PADCFG1 )); mode = (cfg0 &PADCFG0_PMODE_MASK ) >>PADCFG0_PMODE_SHIFT ; -if (!mode) +if (mode ==PADCFG0_PMODE_GPIO )seq_puts (s,"GPIO " );else seq_printf (s,"mode %d " , mode);
@@ -422,6 +423,11 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)writel (value, padcfg0); } +static int intel_gpio_get_gpio_mode (void __iomem *padcfg0) +{ +return (readl (padcfg0) &PADCFG0_PMODE_MASK ) >>PADCFG0_PMODE_SHIFT ; +} +static void intel_gpio_set_gpio_mode (void __iomem *padcfg0) {u32 value;
@@ -450,7 +456,20 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, } padcfg0 =intel_get_padcfg (pctrl, pin,PADCFG0 ); + +/* +* If pin is already configured in GPIO mode, we assume that +* firmware provides correct settings. In such case we avoid +* potential glitches on the pin. Otherwise, for the pin in +* alternative mode, consumer has to supply respective flags. +*/ +if (intel_gpio_get_gpio_mode (padcfg0) ==PADCFG0_PMODE_GPIO ) { +raw_spin_unlock_irqrestore (&pctrl->lock, flags); +return 0 ; + } +intel_gpio_set_gpio_mode (padcfg0); +/* Disable TX buffer and enable RX (this will be input) */ __intel_gpio_set_direction (padcfg0, true);
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 119/125 ocfs2: protect extent tree in ocfs2_prepare_inode_for_write()
In reply to Greg Kroah-HartmanFrom: Shuning Zhang <[email protected]>
[ Upstream commit e74540b285569d2b1e14fe7aee92297078f235ce ]
When the extent tree is modified, it should be protected by inode cluster lock and ip_alloc_sem.
The extent tree is accessed and modified in the ocfs2_prepare_inode_for_write, but isn't protected by ip_alloc_sem.
The following is a case. The function ocfs2_fiemap is accessing the extent tree, which is modified at the same time.
kernel BUG at fs/ocfs2/extent_map.c:475!
invalid opcode: 0000 [#1] SMP
Modules linked in: tun ocfs2 ocfs2_nodemanager configfs ocfs2_stackglue [...]
CPU: 16 PID: 14047 Comm: o2info Not tainted 4.1.12-124.23.1.el6uek.x86_64 #2
Hardware name: Oracle Corporation ORACLE SERVER X7-2L/ASM, MB MECH, X7-2L, BIOS 42040600 10/19/2018
task: ffff88019487e200 ti: ffff88003daa4000 task.ti: ffff88003daa4000
RIP: ocfs2_get_clusters_nocache.isra.11+0x390/0x550 [ocfs2]
Call Trace:
ocfs2_fiemap+0x1e3/0x430 [ocfs2]
do_vfs_ioctl+0x155/0x510
SyS_ioctl+0x81/0xa0
system_call_fastpath+0x18/0xd8
Code: 18 48 c7 c6 60 7f 65 a0 31 c0 bb e2 ff ff ff 48 8b 4a 40 48 8b 7a 28 48 c7 c2 78 2d 66 a0 e8 38 4f 05 00 e9 28 fe ff ff 0f 1f 00 <0f> 0b 66 0f 1f 44 00 00 bb 86 ff ff ff e9 13 fe ff ff 66 0f 1f
RIP ocfs2_get_clusters_nocache.isra.11+0x390/0x550 [ocfs2]
---[ end trace c8aa0c8180e869dc ]---
Kernel panic - not syncing: Fatal exception
Kernel Offset: disabledThis issue can be reproduced every week in a production environment.
This issue is related to the usage mode. If others use ocfs2 in this mode, the kernel will panic frequently.
--- fs/ocfs2/file.c | 134 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 44 deletions(-)
fs/ocfs2/file.c +90 -44
@@ -2106,54 +2106,90 @@ static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)return 0 ; } -static int ocfs2_prepare_inode_for_refcount (struct inode *inode, -struct file *file, -loff_t pos,size_t count, -int *meta_level) +static int ocfs2_inode_lock_for_extent_tree (struct inode *inode, +struct buffer_head **di_bh, +int meta_level, +int overwrite_io, +int write_sem, +int wait) { -int ret; -struct buffer_head *di_bh =NULL ; -u32 cpos = pos >>OCFS2_SB (inode->i_sb)->s_clustersize_bits; -u32 clusters = -ocfs2_clusters_for_bytes (inode->i_sb, pos + count) - cpos; +int ret =0 ; - ret =ocfs2_inode_lock (inode, &di_bh,1 ); -if (ret) { -mlog_errno (ret); +if (wait) + ret =ocfs2_inode_lock (inode,NULL , meta_level); +else + ret =ocfs2_try_inode_lock (inode, + overwrite_io ?NULL : di_bh, meta_level); +if (ret <0 ) goto out; + +if (wait) { +if (write_sem) +down_write (&OCFS2_I (inode)->ip_alloc_sem); +else +down_read (&OCFS2_I (inode)->ip_alloc_sem); + }else { +if (write_sem) + ret =down_write_trylock (&OCFS2_I (inode)->ip_alloc_sem); +else + ret =down_read_trylock (&OCFS2_I (inode)->ip_alloc_sem); + +if (!ret) { + ret = -EAGAIN ; + goto out_unlock; + } } - *meta_level =1 ; +return ret; - ret =ocfs2_refcount_cow (inode, di_bh, cpos, clusters,UINT_MAX ); -if (ret) -mlog_errno (ret); +out_unlock: +brelse (*di_bh); +ocfs2_inode_unlock (inode, meta_level); out: -brelse (di_bh);return ret; } +static void ocfs2_inode_unlock_for_extent_tree (struct inode *inode, +struct buffer_head **di_bh, +int meta_level, +int write_sem) +{ +if (write_sem) +up_write (&OCFS2_I (inode)->ip_alloc_sem); +else +up_read (&OCFS2_I (inode)->ip_alloc_sem); + +brelse (*di_bh); + *di_bh =NULL ; + +if (meta_level >=0 ) +ocfs2_inode_unlock (inode, meta_level); +} +static int ocfs2_prepare_inode_for_write (struct file *file,loff_t pos,size_t count,int wait) {int ret =0 , meta_level =0 , overwrite_io =0 ; +int write_sem =0 ;struct dentry *dentry = file->f_path.dentry;struct inode *inode =d_inode (dentry);struct buffer_head *di_bh =NULL ;loff_t end; +u32 cpos; +u32 clusters;/* * We start with a read level meta lock and only jump to an ex * if we need to make modifications here. */ for (;;) { -if (wait) - ret =ocfs2_inode_lock (inode,NULL , meta_level); -else - ret =ocfs2_try_inode_lock (inode, - overwrite_io ?NULL : &di_bh, meta_level); + ret =ocfs2_inode_lock_for_extent_tree (inode, + &di_bh, + meta_level, + overwrite_io, + write_sem, + wait);if (ret <0 ) { - meta_level =-1 ;if (ret != -EAGAIN )mlog_errno (ret); goto out;
@@ -2165,15 +2201,8 @@ static int ocfs2_prepare_inode_for_write(struct file *file,*/ if (!wait && !overwrite_io) { overwrite_io =1 ; -if (!down_read_trylock (&OCFS2_I (inode)->ip_alloc_sem)) { - ret = -EAGAIN ; - goto out_unlock; - } ret =ocfs2_overwrite_io (inode, di_bh, pos, count); -brelse (di_bh); - di_bh =NULL ; -up_read (&OCFS2_I (inode)->ip_alloc_sem);if (ret <0 ) {if (ret != -EAGAIN )mlog_errno (ret);
@@ -2192,7 +2221,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file,* set inode->i_size at the end of a write. */ if (should_remove_suid (dentry)) {if (meta_level ==0 ) { -ocfs2_inode_unlock (inode, meta_level); +ocfs2_inode_unlock_for_extent_tree (inode, + &di_bh, + meta_level, + write_sem); meta_level =1 ;continue ; }
@@ -2208,18 +2240,32 @@ static int ocfs2_prepare_inode_for_write(struct file *file, ret =ocfs2_check_range_for_refcount (inode, pos, count);if (ret ==1 ) { -ocfs2_inode_unlock (inode, meta_level); - meta_level =-1 ; - - ret =ocfs2_prepare_inode_for_refcount (inode, - file, - pos, - count, - &meta_level); +ocfs2_inode_unlock_for_extent_tree (inode, + &di_bh, + meta_level, + write_sem); + ret =ocfs2_inode_lock_for_extent_tree (inode, + &di_bh, + meta_level, + overwrite_io, +1 , + wait); + write_sem =1 ; +if (ret <0 ) { +if (ret != -EAGAIN ) +mlog_errno (ret); + goto out; + } + + cpos = pos >>OCFS2_SB (inode->i_sb)->s_clustersize_bits; + clusters = +ocfs2_clusters_for_bytes (inode->i_sb, pos + count) - cpos; + ret =ocfs2_refcount_cow (inode, di_bh, cpos, clusters,UINT_MAX ); }if (ret <0 ) { -mlog_errno (ret); +if (ret != -EAGAIN ) +mlog_errno (ret); goto out_unlock; }
@@ -2230,10 +2276,10 @@ out_unlock:trace_ocfs2_prepare_inode_for_write (OCFS2_I (inode)->ip_blkno, pos, count, wait); -brelse (di_bh); - -if (meta_level >=0 ) -ocfs2_inode_unlock (inode, meta_level); +ocfs2_inode_unlock_for_extent_tree (inode, + &di_bh, + meta_level, + write_sem); out:return ret;
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 120/125 pinctrl: cherryview: Fix irq_valid_mask calculation
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
[ Upstream commit 63bdef6cd6941917c823b9cc9aa0219d19fcb716 ]
Commit 03c4749dd6c7 ("gpio / ACPI: Drop unnecessary ACPI GPIO to Linux GPIO translation") has made the cherryview gpio numbers sparse, to get a 1:1 mapping between ACPI pin numbers and gpio numbers in Linux.
This has greatly simplified things, but the code setting the irq_valid_mask was not updated for this, so the valid mask is still in the old "compressed" numbering with the gaps in the pin numbers skipped, which is wrong as irq_valid_mask needs to be expressed in gpio numbers.
This results in the following error on devices using pin 24 (0x0018) on the north GPIO controller as an ACPI event source:
[ 0.422452] cherryview-pinctrl INT33FF:01: Failed to translate GPIO to IRQ
This has been reported (by email) to be happening on a Caterpillar CAT T20 tablet and I've reproduced this myself on a Medion Akoya e2215t 2-in-1.
This commit uses the pin number instead of the compressed index into community->pins to clear the correct bits in irq_valid_mask for GPIOs using GPEs for interrupts, fixing these errors and in case of the Medion Akoya e2215t also fixing the LID switch not working.
--- drivers/pinctrl/intel/pinctrl-cherryview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/intel/pinctrl-cherryview.c +1 -1
@@ -1595,7 +1595,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) intsel >>=CHV_PADCTRL0_INTSEL_SHIFT ;if (need_valid_mask && intsel >= community->nirqs) -clear_bit (i, chip->irq.valid_mask); +clear_bit (desc->number, chip->irq.valid_mask); }/*
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 121/125 blkcg: make blkcg_print_stat() print stats only for online blkgs
In reply to Greg Kroah-HartmanFrom: Tejun Heo <[email protected]>
[ Upstream commit b0814361a25cba73a224548843ed92d8ea78715a ]
blkcg_print_stat() iterates blkgs under RCU and doesn't test whether the blkg is online. This can call into pd_stat_fn() on a pd which is still being initialized leading to an oops.
The heaviest operation - recursively summing up rwstat counters - is already done while holding the queue_lock. Expand queue_lock to cover the other operations and skip the blkg if it isn't online yet. The online state is protected by both blkcg and queue locks, so this guarantees that only online blkgs are processed.
--- block/blk-cgroup.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
block/blk-cgroup.c +8 -5
@@ -955,9 +955,14 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)int i;bool has_stats = false; +spin_lock_irq (blkg->q->queue_lock); + +if (!blkg->online) + goto skip; + dname =blkg_dev_name (blkg);if (!dname) -continue ; + goto skip;/* * Hooray string manipulation, count is the size written NOT
@@ -967,8 +972,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)*/ off +=scnprintf (buf+off, size-off,"%s " , dname); -spin_lock_irq (blkg->q->queue_lock); - rwstat =blkg_rwstat_recursive_sum (blkg,NULL , offsetof(struct blkcg_gq , stat_bytes)); rbytes =atomic64_read (&rwstat.aux_cnt[BLKG_RWSTAT_READ ]);
@@ -981,8 +984,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v) wios =atomic64_read (&rwstat.aux_cnt[BLKG_RWSTAT_WRITE ]); dios =atomic64_read (&rwstat.aux_cnt[BLKG_RWSTAT_DISCARD ]); -spin_unlock_irq (blkg->q->queue_lock); -if (rbytes || wbytes || rios || wios) { has_stats = true; off += scnprintf(buf+off, size-off,
@@ -1023,6 +1024,8 @@ next:seq_commit (sf,-1 ); } } + skip: +spin_unlock_irq (blkg->q->queue_lock); }rcu_read_unlock ();
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 122/125 iio: imu: mpu6050: Add support for the ICM 20602 IMU
In reply to Greg Kroah-HartmanFrom: Randolph Maaßen <[email protected]>
[ Upstream commit 22904bdff97839960bd98b3452a583b1daee628b ]
The Invensense ICM-20602 is a 6-axis MotionTracking device that combines a 3-axis gyroscope and an 3-axis accelerometer. It is very similar to the ICM-20608 imu which is already supported by the mpu6050 driver. The main difference is that the ICM-20602 has the i2c bus disable bit in a separate register.
--- drivers/iio/imu/inv_mpu6050/Kconfig | 8 +++--- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 31 ++++++++++++++++++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 6 +++++ drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 8 ++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 12 ++++++--- 5 files changed, 58 insertions(+), 7 deletions(-)
drivers/iio/imu/inv_mpu6050/Kconfig +4 -4
@@ -13,8 +13,8 @@ config INV_MPU6050_I2C select INV_MPU6050_IIO select REGMAP_I2C help - This driver supports the Invensense MPU6050/6500/9150 and ICM20608 - motion tracking devices over I2C. + This driver supports the Invensense MPU6050/6500/9150 and + ICM20608/20602 motion tracking devices over I2C. This driver can be built as a module. The module will be called inv-mpu6050-i2c.
@@ -24,7 +24,7 @@ config INV_MPU6050_SPI select INV_MPU6050_IIO select REGMAP_SPI help - This driver supports the Invensense MPU6050/6500/9150 and ICM20608 - motion tracking devices over SPI. + This driver supports the Invensense MPU6050/6500/9150 and + ICM20608/20602 motion tracking devices over SPI. This driver can be built as a module. The module will be called inv-mpu6050-spi.
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +31 -0
@@ -37,6 +37,29 @@ static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724};*/ static const int accel_scale[] = {598 ,1196 ,2392 ,4785 }; +static const struct inv_mpu6050_reg_map reg_set_icm20602 = { + .sample_rate_div =INV_MPU6050_REG_SAMPLE_RATE_DIV , + .lpf =INV_MPU6050_REG_CONFIG , + .accel_lpf =INV_MPU6500_REG_ACCEL_CONFIG_2 , + .user_ctrl =INV_MPU6050_REG_USER_CTRL , + .fifo_en =INV_MPU6050_REG_FIFO_EN , + .gyro_config =INV_MPU6050_REG_GYRO_CONFIG , + .accl_config =INV_MPU6050_REG_ACCEL_CONFIG , + .fifo_count_h =INV_MPU6050_REG_FIFO_COUNT_H , + .fifo_r_w =INV_MPU6050_REG_FIFO_R_W , + .raw_gyro =INV_MPU6050_REG_RAW_GYRO , + .raw_accl =INV_MPU6050_REG_RAW_ACCEL , + .temperature =INV_MPU6050_REG_TEMPERATURE , + .int_enable =INV_MPU6050_REG_INT_ENABLE , + .int_status =INV_MPU6050_REG_INT_STATUS , + .pwr_mgmt_1 =INV_MPU6050_REG_PWR_MGMT_1 , + .pwr_mgmt_2 =INV_MPU6050_REG_PWR_MGMT_2 , + .int_pin_cfg =INV_MPU6050_REG_INT_PIN_CFG , + .accl_offset =INV_MPU6500_REG_ACCEL_OFFSET , + .gyro_offset =INV_MPU6050_REG_GYRO_OFFSET , + .i2c_if =INV_ICM20602_REG_I2C_IF , +}; +static const struct inv_mpu6050_reg_map reg_set_6500 = { .sample_rate_div =INV_MPU6050_REG_SAMPLE_RATE_DIV , .lpf =INV_MPU6050_REG_CONFIG ,
@@ -57,6 +80,7 @@ static const struct inv_mpu6050_reg_map reg_set_6500 = { .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG, .accl_offset = INV_MPU6500_REG_ACCEL_OFFSET, .gyro_offset = INV_MPU6050_REG_GYRO_OFFSET, + .i2c_if = 0, };static const struct inv_mpu6050_reg_map reg_set_6050 = {
@@ -77,6 +101,7 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = { .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG, .accl_offset = INV_MPU6050_REG_ACCEL_OFFSET, .gyro_offset = INV_MPU6050_REG_GYRO_OFFSET, + .i2c_if = 0, };static const struct inv_mpu6050_chip_config chip_config_6050 = {
@@ -139,6 +164,12 @@ static const struct inv_mpu6050_hw hw_info[] = { .reg = ®_set_6500, .config = &chip_config_6050, }, + { + .whoami = INV_ICM20602_WHOAMI_VALUE, + .name = "ICM20602", + .reg = ®_set_icm20602, + .config = &chip_config_6050, + }, };int inv_mpu6050_switch_engine (struct inv_mpu6050_state *st,bool en,u32 mask)
drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +6 -0
@@ -127,6 +127,7 @@ static int inv_mpu_probe(struct i2c_client *client, st =iio_priv (dev_get_drvdata (&client->dev));switch (st->chip_type) {case INV_ICM20608 : +case INV_ICM20602 :/* no i2c auxiliary bus on the chip */ break ;default :
@@ -179,6 +180,7 @@ static const struct i2c_device_id inv_mpu_id[] = { {"mpu9250", INV_MPU9250}, {"mpu9255", INV_MPU9255}, {"icm20608", INV_ICM20608}, + {"icm20602", INV_ICM20602}, {} };
@@ -213,6 +215,10 @@ static const struct of_device_id inv_of_match[] = { .compatible = "invensense,icm20608", .data = (void *)INV_ICM20608 }, + { + .compatible = "invensense,icm20602", + .data = (void *)INV_ICM20602 + }, { } };MODULE_DEVICE_TABLE (of, inv_of_match);
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +8 -0
@@ -44,6 +44,7 @@* @int_pin_cfg; Controls interrupt pin configuration. * @accl_offset: Controls the accelerometer calibration offset. * @gyro_offset: Controls the gyroscope calibration offset. +* @i2c_if: Controls the i2c interface */ struct inv_mpu6050_reg_map {u8 sample_rate_div;
@@ -65,6 +66,7 @@ struct inv_mpu6050_reg_map {u8 int_pin_cfg;u8 accl_offset;u8 gyro_offset; +u8 i2c_if; };/*device enum */
@@ -77,6 +79,7 @@ enum inv_devices {INV_MPU9250 ,INV_MPU9255 ,INV_ICM20608 , +INV_ICM20602 , INV_NUM_PARTS };
@@ -193,6 +196,10 @@ struct inv_mpu6050_state {#define INV_MPU6050_BIT_PWR_ACCL_STBY 0x38#define INV_MPU6050_BIT_PWR_GYRO_STBY 0x07 +/* ICM20602 register */ +#define INV_ICM20602_REG_I2C_IF 0x70 +#define INV_ICM20602_BIT_I2C_IF_DIS 0x40 +#define INV_MPU6050_REG_FIFO_COUNT_H 0x72#define INV_MPU6050_REG_FIFO_R_W 0x74
@@ -259,6 +266,7 @@ struct inv_mpu6050_state {#define INV_MPU9255_WHOAMI_VALUE 0x73#define INV_MPU6515_WHOAMI_VALUE 0x74#define INV_ICM20608_WHOAMI_VALUE 0xAF +#define INV_ICM20602_WHOAMI_VALUE 0x12/* scan element definition */ enum inv_mpu6050_scan {
drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +9 -3
@@ -31,9 +31,14 @@ static int inv_mpu_i2c_disable(struct iio_dev *indio_dev)if (ret)return ret; - st->chip_config.user_ctrl |=INV_MPU6050_BIT_I2C_IF_DIS ; - ret =regmap_write (st->map, st->reg->user_ctrl, - st->chip_config.user_ctrl); +if (st->reg->i2c_if) { + ret =regmap_write (st->map, st->reg->i2c_if, +INV_ICM20602_BIT_I2C_IF_DIS ); + }else { + st->chip_config.user_ctrl |=INV_MPU6050_BIT_I2C_IF_DIS ; + ret =regmap_write (st->map, st->reg->user_ctrl, + st->chip_config.user_ctrl); + }if (ret) {inv_mpu6050_set_power_itg (st, false);return ret;
@@ -81,6 +86,7 @@ static const struct spi_device_id inv_mpu_id[] = { {"mpu9250", INV_MPU9250}, {"mpu9255", INV_MPU9255}, {"icm20608", INV_ICM20608}, + {"icm20602", INV_ICM20602}, {} };
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 123/125 iio: imu: inv_mpu6050: fix no data on MPU6050
In reply to Greg Kroah-HartmanFrom: Jean-Baptiste Maneyrol <[email protected]>
[ Upstream commit 6e82ae6b8d11b948b74e71396efd8e074c415f44 ]
Some chips have a fifo overflow bit issue where the bit is always set. The result is that every data is dropped.
Change fifo overflow management by checking fifo count against a maximum value.
Add fifo size in chip hardware set of values.
--- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 9 +++++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 ++ drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 15 ++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-)
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +9 -0
@@ -121,54 +121,63 @@ static const struct inv_mpu6050_hw hw_info[] = { .name = "MPU6050", .reg = ®_set_6050, .config = &chip_config_6050, + .fifo_size = 1024, }, { .whoami = INV_MPU6500_WHOAMI_VALUE, .name = "MPU6500", .reg = ®_set_6500, .config = &chip_config_6050, + .fifo_size = 512, }, { .whoami = INV_MPU6515_WHOAMI_VALUE, .name = "MPU6515", .reg = ®_set_6500, .config = &chip_config_6050, + .fifo_size = 512, }, { .whoami = INV_MPU6000_WHOAMI_VALUE, .name = "MPU6000", .reg = ®_set_6050, .config = &chip_config_6050, + .fifo_size = 1024, }, { .whoami = INV_MPU9150_WHOAMI_VALUE, .name = "MPU9150", .reg = ®_set_6050, .config = &chip_config_6050, + .fifo_size = 1024, }, { .whoami = INV_MPU9250_WHOAMI_VALUE, .name = "MPU9250", .reg = ®_set_6500, .config = &chip_config_6050, + .fifo_size = 512, }, { .whoami = INV_MPU9255_WHOAMI_VALUE, .name = "MPU9255", .reg = ®_set_6500, .config = &chip_config_6050, + .fifo_size = 512, }, { .whoami = INV_ICM20608_WHOAMI_VALUE, .name = "ICM20608", .reg = ®_set_6500, .config = &chip_config_6050, + .fifo_size = 512, }, { .whoami = INV_ICM20602_WHOAMI_VALUE, .name = "ICM20602", .reg = ®_set_icm20602, .config = &chip_config_6050, + .fifo_size = 1008, }, };
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +2 -0
@@ -108,12 +108,14 @@ struct inv_mpu6050_chip_config {* @name: name of the chip. * @reg: register map of the chip. * @config: configuration of the chip. +* @fifo_size: size of the FIFO in bytes. */ struct inv_mpu6050_hw {u8 whoami;u8 *name;const struct inv_mpu6050_reg_map *reg;const struct inv_mpu6050_chip_config *config; +size_t fifo_size; };/*
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +12 -3
@@ -188,9 +188,6 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) "failed to ack interrupt\n"); goto flush_fifo; } -/* handle fifo overflow by reseting fifo */ -if (int_status &INV_MPU6050_BIT_FIFO_OVERFLOW_INT ) - goto flush_fifo;if (!(int_status &INV_MPU6050_BIT_RAW_DATA_RDY_INT )) {dev_warn (regmap_get_device (st->map),"spurious interrupt with status 0x%x\n" , int_status);
@@ -216,6 +213,18 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)if (result) goto end_session; fifo_count =get_unaligned_be16 (&data[0 ]); + +/* +* Handle fifo overflow by resetting fifo. +* Reset if there is only 3 data set free remaining to mitigate +* possible delay between reading fifo count and fifo data. +*/ + nb =3 * bytes_per_datum; +if (fifo_count >= st->hw->fifo_size - nb) { +dev_warn (regmap_get_device (st->map),"fifo overflow reset\n" ); + goto flush_fifo; + } +/* compute and process all complete datum */ nb = fifo_count / bytes_per_datum;inv_mpu6050_update_period (st, pf->timestamp, nb);
Signature · 1 line
2.20.1
Re: [PATCH 4.19 123/125] iio: imu: inv_mpu6050: fix no data on MPU6050
Quoted 21 lines · Greg Kroah-Hartman
From: Jean-Baptiste Maneyrol <[email protected]>
[ Upstream commit
6e82ae6b8d11b948b74e71396efd8e074c415f44]Some chips have a fifo overflow bit issue where the bit is always set. The result is that every data is dropped.
Change fifo overflow management by checking fifo count against a maximum value.
Add fifo size in chip hardware set of values.
(quoted diff) +5
-0@@ -216,6 +213,18 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) if (result) goto end_session; fifo_count = get_unaligned_be16(&data[0]); + + /* + * Handle fifo overflow by resetting fifo. + * Reset if there is only 3 data set free remaining to mitigate + * possible delay between reading fifo count and fifo data.
Review irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) · line 230
Quoted 10 lines
(quoted diff) +7
-0+ */ + nb = 3 * bytes_per_datum; + if (fifo_count >= st->hw->fifo_size - nb) { + dev_warn(regmap_get_device(st->map), "fifo overflow reset\n"); + goto flush_fifo; + } + /* compute and process all complete datum */ nb = fifo_count / bytes_per_datum; inv_mpu6050_update_period(st, pf->timestamp, nb);
Would this make sense to reduce code duplication?
Best regards,
Pavel
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +2 -6
@@ -232,16 +232,12 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) timestamp =inv_mpu6050_get_timestamp (st);iio_push_to_buffers_with_timestamp (indio_dev, data, timestamp); } - -end_session: -mutex_unlock (&st->lock); -iio_trigger_notify_done (indio_dev->trig); - -return IRQ_HANDLED ; + goto end_session; flush_fifo:/* Flush HW and SW FIFOs. */ inv_reset_fifo (indio_dev); +end_session:mutex_unlock (&st->lock);iio_trigger_notify_done (indio_dev->trig);
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Greg Kroah-Hartman
maintainerPATCH 124/125 mm/filemap.c: dont initiate writeback if mapping has no dirty pages
In reply to Greg Kroah-HartmanFrom: Konstantin Khlebnikov <[email protected]>
commit c3aab9a0bd91b696a852169479b7db1ece6cbf8c upstream.
Functions like filemap_write_and_wait_range() should do nothing if inode has no dirty pages or pages currently under writeback. But they anyway construct struct writeback_control and this does some atomic operations if CONFIG_CGROUP_WRITEBACK=y - on fast path it locks inode->i_lock and updates state of writeback ownership, on slow path might be more work. Current this path is safely avoided only when inode mapping has no pages.
For example generic_file_read_iter() calls filemap_write_and_wait_range() at each O_DIRECT read - pretty hot path.
This patch skips starting new writeback if mapping has no dirty tags set. If writeback is already in progress filemap_write_and_wait_range() will wait for it.
--- mm/filemap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
mm/filemap.c +2 -1
@@ -438,7 +438,8 @@ int __filemap_fdatawrite_range(struct ad .range_end = end, }; -if (!mapping_cap_writeback_dirty (mapping)) +if (!mapping_cap_writeback_dirty (mapping) || + !mapping_tagged (mapping,PAGECACHE_TAG_DIRTY ))return 0 ;wbc_attach_fdatawrite_inode (&wbc, mapping->host);
Greg Kroah-Hartman
maintainerPATCH 125/125 cgroup,writeback: dont switch wbs immediately on dead wbs if the memcg is dead
In reply to Greg Kroah-HartmanFrom: Tejun Heo <[email protected]>
commit 65de03e251382306a4575b1779c57c87889eee49 upstream.
cgroup writeback tries to refresh the associated wb immediately if the current wb is dead. This is to avoid keeping issuing IOs on the stale wb after memcg - blkcg association has changed (ie. when blkcg got disabled / enabled higher up in the hierarchy).
Unfortunately, the logic gets triggered spuriously on inodes which are associated with dead cgroups. When the logic is triggered on dead cgroups, the attempt fails only after doing quite a bit of work allocating and initializing a new wb.
While c3aab9a0bd91 ("mm/filemap.c: don't initiate writeback if mapping has no dirty pages") alleviated the issue significantly as it now only triggers when the inode has dirty pages. However, the condition can still be triggered before the inode is switched to a different cgroup and the logic simply doesn't make sense.
Skip the immediate switching if the associated memcg is dying.
This is a simplified version of the following two patches:
* https://lore.kernel.org/linux-mm/20190513183053.GA73423@dennisz-mbp/
* http://lkml.kernel.org/r/156355839560.2063.5265687291430814589.stgit@buzz
--- fs/fs-writeback.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
fs/fs-writeback.c +6 -3
@@ -582,10 +582,13 @@ void wbc_attach_and_unlock_inode(structspin_unlock (&inode->i_lock);/* -* A dying wb indicates that the memcg-blkcg mapping has changed -* and a new wb is already serving the memcg. Switch immediately. +* A dying wb indicates that either the blkcg associated with the +* memcg changed or the associated memcg is dying. In the first +* case, a replacement wb should already be available and we should +* refresh the wb immediately. In the second case, trying to +* refresh will keep failing. */ -if (unlikely (wb_dying (wbc->wb))) +if (unlikely (wb_dying (wbc->wb) && !css_is_dying (wbc->wb->memcg_css)))inode_switch_wbs (inode, wbc->wb_id); }
stable-rc/linux-4.19.y boot: 120 boots: 0 failed, 112 passed with 8 offline (v4.19.83-126-g0f8b6b0b5b94)
stable-rc/linux-4.19.y boot: 120 boots: 0 failed, 112 passed with 8 offline (v4.19.83-126-g0f8b6b0b5b94)
Full Boot Summary: https://kernelci.org/boot/all/job/stable-rc/branch/linux-4.19.y/kernel/v4.19.83-126-g0f8b6b0b5b94/
Full Build Summary: https://kernelci.org/build/stable-rc/branch/linux-4.19.y/kernel/v4.19.83-126-g0f8b6b0b5b94/
Tree: stable-rc
Branch: linux-4.19.y
Git Describe: v4.19.83-126-g0f8b6b0b5b94
Git Commit: 0f8b6b0b5b946b33f5b60e9de252afb809a17e6a
Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
Tested: 68 unique boards, 22 SoC families, 14 builds out of 206
Offline Platforms:
arm:
sunxi_defconfig:
gcc-8
sun5i-r8-chip: 1 offline lab
sun7i-a20-bananapi: 1 offline lab
multi_v7_defconfig:
gcc-8
qcom-apq8064-cm-qs600: 1 offline lab
sun5i-r8-chip: 1 offline lab
sun7i-a20-bananapi: 1 offline lab
davinci_all_defconfig:
gcc-8
dm365evm,legacy: 1 offline lab
qcom_defconfig:
gcc-8
qcom-apq8064-cm-qs600: 1 offline labarm64:
defconfig:
gcc-8
meson-axg-s400: 1 offline lab
---
For more info write to <[email protected]>
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.19.84 release. There are 125 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 13 Nov 2019 18:08:44 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.19.84-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.19.y
and the diffstat can be found below.thanks,
greg k-h
Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.
Summary
------------------------------------------------------------------------
kernel: 4.19.84-rc1
git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-4.19.y
git commit: 0f8b6b0b5b946b33f5b60e9de252afb809a17e6a
git describe: v4.19.83-126-g0f8b6b0b5b94
Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-4.19-oe/build/v4.19.83-126-g0f8b6b0b5b94
No regressions (compared to build v4.19.83-124-gb8764c8bac2d)
No fixes (compared to build v4.19.83-124-gb8764c8bac2d)
Ran 23945 total tests in the following environments and test suites.
Environments
--------------
- dragonboard-410c
- hi6220-hikey
- i386
- juno-r2
- qemu_arm
- qemu_arm64
- qemu_i386
- qemu_x86_64
- x15
- x86
Test Suites
-----------
* build
* install-android-platform-tools-r2600
* kselftest
* libgpiod
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* perf
* spectre-meltdown-checker-test
* network-basic-tests
* v4l2-compliance
* ltp-open-posix-tests
* kvm-unit-tests
* ssuite
* kselftest-vsyscall-mode-native
* kselftest-vsyscall-mode-none
Signature · 2 lines
Linaro LKFT https://lkft.linaro.org
Jon Hunter
maintainerQuoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.19.84 release. There are 125 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 13 Nov 2019 18:08:44 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.19.84-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-4.19.y
and the diffstat can be found below.thanks,
greg k-h
All tests for Tegra are passing ...
Test results for stable-v4.19:
12 builds: 12 pass, 0 fail
22 boots: 22 pass, 0 fail
32 tests: 32 pass, 0 failLinux version: 4.19.84-rc1-g0f8b6b0b5b94
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra194-p2972-0000, tegra20-ventana,
tegra210-p2371-2180, tegra30-cardhu-a04Cheers
Jon
Signature · 1 line
nvpublic
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 4.19.84 release. There are 125 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 13 Nov 2019 18:08:44 +0000. Anything received after that time might be too late.
Build results:
total: 156 pass: 156 fail: 0 Qemu test results: total: 390 pass: 390 fail: 0
Guenter