Files
Greg Kroah-Hartman bbc4834e22 Merge 4.19.320 into android-4.19-stable
Changes in 4.19.320
	platform/chrome: cros_ec_debugfs: fix wrong EC message version
	hfsplus: fix to avoid false alarm of circular locking
	x86/of: Return consistent error type from x86_of_pci_irq_enable()
	x86/pci/intel_mid_pci: Fix PCIBIOS_* return code handling
	x86/pci/xen: Fix PCIBIOS_* return code handling
	x86/platform/iosf_mbi: Convert PCIBIOS_* return codes to errnos
	hwmon: (adt7475) Fix default duty on fan is disabled
	pwm: stm32: Always do lazy disabling
	hwmon: (max6697) Fix underflow when writing limit attributes
	hwmon: Introduce SENSOR_DEVICE_ATTR_{RO, RW, WO} and variants
	hwmon: (max6697) Auto-convert to use SENSOR_DEVICE_ATTR_{RO, RW, WO}
	hwmon: (max6697) Fix swapped temp{1,8} critical alarms
	arm64: dts: rockchip: Increase VOP clk rate on RK3328
	m68k: atari: Fix TT bootup freeze / unexpected (SCU) interrupt messages
	x86/xen: Convert comma to semicolon
	m68k: cmpxchg: Fix return value for default case in __arch_xchg()
	wifi: brcmsmac: LCN PHY code is used for BCM4313 2G-only device
	net/smc: Allow SMC-D 1MB DMB allocations
	net/smc: set rmb's SG_MAX_SINGLE_ALLOC limitation only when CONFIG_ARCH_NO_SG_CHAIN is defined
	selftests/bpf: Check length of recv in test_sockmap
	wifi: cfg80211: fix typo in cfg80211_calculate_bitrate_he()
	wifi: cfg80211: handle 2x996 RU allocation in cfg80211_calculate_bitrate_he()
	net: fec: Refactor: #define magic constants
	net: fec: Fix FEC_ECR_EN1588 being cleared on link-down
	ipvs: Avoid unnecessary calls to skb_is_gso_sctp
	perf: Fix perf_aux_size() for greater-than 32-bit size
	perf: Prevent passing zero nr_pages to rb_alloc_aux()
	bna: adjust 'name' buf size of bna_tcb and bna_ccb structures
	selftests: forwarding: devlink_lib: Wait for udev events after reloading
	media: imon: Fix race getting ictx->lock
	saa7134: Unchecked i2c_transfer function result fixed
	media: uvcvideo: Allow entity-defined get_info and get_cur
	media: uvcvideo: Override default flags
	media: renesas: vsp1: Fix _irqsave and _irq mix
	media: renesas: vsp1: Store RPF partition configuration per RPF instance
	leds: trigger: Unregister sysfs attributes before calling deactivate()
	perf report: Fix condition in sort__sym_cmp()
	drm/etnaviv: fix DMA direction handling for cached RW buffers
	mfd: omap-usb-tll: Use struct_size to allocate tll
	ext4: avoid writing unitialized memory to disk in EA inodes
	sparc64: Fix incorrect function signature and add prototype for prom_cif_init
	PCI: Equalize hotplug memory and io for occupied and empty slots
	PCI: Fix resource double counting on remove & rescan
	RDMA/mlx4: Fix truncated output warning in mad.c
	RDMA/mlx4: Fix truncated output warning in alias_GUID.c
	RDMA/rxe: Don't set BTH_ACK_MASK for UC or UD QPs
	mtd: make mtd_test.c a separate module
	Input: elan_i2c - do not leave interrupt disabled on suspend failure
	MIPS: Octeron: remove source file executable bit
	powerpc/xmon: Fix disassembly CPU feature checks
	macintosh/therm_windtunnel: fix module unload.
	bnxt_re: Fix imm_data endianness
	ice: Rework flex descriptor programming
	netfilter: ctnetlink: use helper function to calculate expect ID
	pinctrl: core: fix possible memory leak when pinctrl_enable() fails
	pinctrl: single: fix possible memory leak when pinctrl_enable() fails
	pinctrl: ti: ti-iodelay: Drop if block with always false condition
	pinctrl: ti: ti-iodelay: fix possible memory leak when pinctrl_enable() fails
	pinctrl: freescale: mxs: Fix refcount of child
	fs/nilfs2: remove some unused macros to tame gcc
	nilfs2: avoid undefined behavior in nilfs_cnt32_ge macro
	tick/broadcast: Make takeover of broadcast hrtimer reliable
	net: netconsole: Disable target before netpoll cleanup
	af_packet: Handle outgoing VLAN packets without hardware offloading
	ipv6: take care of scope when choosing the src addr
	char: tpm: Fix possible memory leak in tpm_bios_measurements_open()
	media: venus: fix use after free in vdec_close
	hfs: fix to initialize fields of hfs_inode_info after hfs_alloc_inode()
	drm/gma500: fix null pointer dereference in cdv_intel_lvds_get_modes
	drm/gma500: fix null pointer dereference in psb_intel_lvds_get_modes
	m68k: amiga: Turn off Warp1260 interrupts during boot
	ext4: check dot and dotdot of dx_root before making dir indexed
	ext4: make sure the first directory block is not a hole
	wifi: mwifiex: Fix interface type change
	leds: ss4200: Convert PCIBIOS_* return codes to errnos
	tools/memory-model: Fix bug in lock.cat
	hwrng: amd - Convert PCIBIOS_* return codes to errnos
	PCI: hv: Return zero, not garbage, when reading PCI_INTERRUPT_PIN
	binder: fix hang of unregistered readers
	scsi: qla2xxx: Return ENOBUFS if sg_cnt is more than one for ELS cmds
	f2fs: fix to don't dirty inode for readonly filesystem
	clk: davinci: da8xx-cfgchip: Initialize clk_init_data before use
	ubi: eba: properly rollback inside self_check_eba
	decompress_bunzip2: fix rare decompression failure
	kobject_uevent: Fix OOB access within zap_modalias_env()
	rtc: cmos: Fix return value of nvmem callbacks
	scsi: qla2xxx: During vport delete send async logout explicitly
	scsi: qla2xxx: validate nvme_local_port correctly
	perf/x86/intel/pt: Fix topa_entry base length
	watchdog/perf: properly initialize the turbo mode timestamp and rearm counter
	platform: mips: cpu_hwmon: Disable driver on unsupported hardware
	RDMA/iwcm: Fix a use-after-free related to destroying CM IDs
	selftests/sigaltstack: Fix ppc64 GCC build
	nilfs2: handle inconsistent state in nilfs_btnode_create_block()
	kdb: Fix bound check compiler warning
	kdb: address -Wformat-security warnings
	kdb: Use the passed prompt in kdb_position_cursor()
	jfs: Fix array-index-out-of-bounds in diFree
	dma: fix call order in dmam_free_coherent
	MIPS: SMP-CPS: Fix address for GCR_ACCESS register for CM3 and later
	net: ip_rt_get_source() - use new style struct initializer instead of memset
	ipv4: Fix incorrect source address in Record Route option
	net: bonding: correctly annotate RCU in bond_should_notify_peers()
	tipc: Return non-zero value from tipc_udp_addr2str() on error
	mISDN: Fix a use after free in hfcmulti_tx()
	mm: avoid overflows in dirty throttling logic
	PCI: rockchip: Make 'ep-gpios' DT property optional
	PCI: rockchip: Use GPIOD_OUT_LOW flag while requesting ep_gpio
	parport: parport_pc: Mark expected switch fall-through
	parport: Convert printk(KERN_<LEVEL> to pr_<level>(
	parport: Standardize use of printmode
	dev/parport: fix the array out-of-bounds risk
	driver core: Cast to (void *) with __force for __percpu pointer
	devres: Fix memory leakage caused by driver API devm_free_percpu()
	perf/x86/intel/pt: Export pt_cap_get()
	perf/x86/intel/pt: Use helpers to obtain ToPA entry size
	perf/x86/intel/pt: Use pointer arithmetics instead in ToPA entry calculation
	perf/x86/intel/pt: Split ToPA metadata and page layout
	perf/x86/intel/pt: Fix a topa_entry base address calculation
	remoteproc: imx_rproc: ignore mapping vdev regions
	remoteproc: imx_rproc: Fix ignoring mapping vdev regions
	remoteproc: imx_rproc: Skip over memory region when node value is NULL
	drm/vmwgfx: Fix overlay when using Screen Targets
	net/iucv: fix use after free in iucv_sock_close()
	ipv6: fix ndisc_is_useropt() handling for PIO
	protect the fetch of ->fd[fd] in do_dup2() from mispredictions
	ALSA: usb-audio: Correct surround channels in UAC1 channel map
	net: usb: sr9700: fix uninitialized variable use in sr_mdio_read
	irqchip/mbigen: Fix mbigen node address layout
	x86/mm: Fix pti_clone_pgtable() alignment assumption
	net: usb: qmi_wwan: fix memory leak for not ip packets
	net: linkwatch: use system_unbound_wq
	Bluetooth: l2cap: always unlock channel in l2cap_conless_channel()
	net: fec: Stop PPS on driver remove
	md/raid5: avoid BUG_ON() while continue reshape after reassembling
	clocksource/drivers/sh_cmt: Address race condition for clock events
	PCI: Add Edimax Vendor ID to pci_ids.h
	udf: prevent integer overflow in udf_bitmap_free_blocks()
	wifi: nl80211: don't give key data to userspace
	btrfs: fix bitmap leak when loading free space cache on duplicate entry
	media: uvcvideo: Ignore empty TS packets
	media: uvcvideo: Fix the bandwdith quirk on USB 3.x
	jbd2: avoid memleak in jbd2_journal_write_metadata_buffer
	s390/sclp: Prevent release of buffer in I/O
	SUNRPC: Fix a race to wake a sync task
	ext4: fix wrong unit use in ext4_mb_find_by_goal
	arm64: Add support for SB barrier and patch in over DSB; ISB sequences
	arm64: cpufeature: Force HWCAP to be based on the sysreg visible to user-space
	arm64: Add Neoverse-V2 part
	arm64: cputype: Add Cortex-X4 definitions
	arm64: cputype: Add Neoverse-V3 definitions
	arm64: errata: Add workaround for Arm errata 3194386 and 3312417
	arm64: cputype: Add Cortex-X3 definitions
	arm64: cputype: Add Cortex-A720 definitions
	arm64: cputype: Add Cortex-X925 definitions
	arm64: errata: Unify speculative SSBS errata logic
	arm64: errata: Expand speculative SSBS workaround
	arm64: cputype: Add Cortex-X1C definitions
	arm64: cputype: Add Cortex-A725 definitions
	arm64: errata: Expand speculative SSBS workaround (again)
	i2c: smbus: Don't filter out duplicate alerts
	i2c: smbus: Improve handling of stuck alerts
	i2c: smbus: Send alert notifications to all devices if source not found
	bpf: kprobe: remove unused declaring of bpf_kprobe_override
	spi: lpspi: Replace all "master" with "controller"
	spi: lpspi: Add slave mode support
	spi: lpspi: Let watermark change with send data length
	spi: lpspi: Add i.MX8 boards support for lpspi
	spi: lpspi: add the error info of transfer speed setting
	spi: fsl-lpspi: remove unneeded array
	spi: spi-fsl-lpspi: Fix scldiv calculation
	ALSA: line6: Fix racy access to midibuf
	usb: vhci-hcd: Do not drop references before new references are gained
	USB: serial: debug: do not echo input by default
	usb: gadget: core: Check for unset descriptor
	scsi: ufs: core: Fix hba->last_dme_cmd_tstamp timestamp updating logic
	tick/broadcast: Move per CPU pointer access into the atomic section
	ntp: Clamp maxerror and esterror to operating range
	driver core: Fix uevent_show() vs driver detach race
	ntp: Safeguard against time_constant overflow
	serial: core: check uartclk for zero to avoid divide by zero
	power: supply: axp288_charger: Fix constant_charge_voltage writes
	power: supply: axp288_charger: Round constant_charge_voltage writes down
	tracing: Fix overflow in get_free_elt()
	x86/mtrr: Check if fixed MTRRs exist before saving them
	drm/bridge: analogix_dp: properly handle zero sized AUX transactions
	drm/mgag200: Set DDC timeout in milliseconds
	kbuild: Fix '-S -c' in x86 stack protector scripts
	netfilter: nf_tables: set element extended ACK reporting support
	netfilter: nf_tables: use timestamp to check for set element timeout
	netfilter: nf_tables: prefer nft_chain_validate
	arm64: cpufeature: Fix the visibility of compat hwcaps
	media: uvcvideo: Use entity get_cur in uvc_ctrl_set
	drm/i915/gem: Fix Virtual Memory mapping boundaries calculation
	exec: Fix ToCToU between perm check and set-uid/gid usage
	nvme/pci: Add APST quirk for Lenovo N60z laptop
	Linux 4.19.320

Change-Id: I12efa55c04d97f29d34f1a49511948735871b2bd
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2024-08-28 09:03:40 +00:00

349 lines
8.0 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* arch-independent dma-mapping routines
*
* Copyright (c) 2006 SUSE Linux Products GmbH
* Copyright (c) 2006 Tejun Heo <teheo@suse.de>
*/
#include <linux/acpi.h>
#include <linux/dma-mapping.h>
#include <linux/export.h>
#include <linux/gfp.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
/*
* Managed DMA API
*/
struct dma_devres {
size_t size;
void *vaddr;
dma_addr_t dma_handle;
unsigned long attrs;
};
static void dmam_release(struct device *dev, void *res)
{
struct dma_devres *this = res;
dma_free_attrs(dev, this->size, this->vaddr, this->dma_handle,
this->attrs);
}
static int dmam_match(struct device *dev, void *res, void *match_data)
{
struct dma_devres *this = res, *match = match_data;
if (this->vaddr == match->vaddr) {
WARN_ON(this->size != match->size ||
this->dma_handle != match->dma_handle);
return 1;
}
return 0;
}
/**
* dmam_alloc_coherent - Managed dma_alloc_coherent()
* @dev: Device to allocate coherent memory for
* @size: Size of allocation
* @dma_handle: Out argument for allocated DMA handle
* @gfp: Allocation flags
*
* Managed dma_alloc_coherent(). Memory allocated using this function
* will be automatically released on driver detach.
*
* RETURNS:
* Pointer to allocated memory on success, NULL on failure.
*/
void *dmam_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
struct dma_devres *dr;
void *vaddr;
dr = devres_alloc(dmam_release, sizeof(*dr), gfp);
if (!dr)
return NULL;
vaddr = dma_alloc_coherent(dev, size, dma_handle, gfp);
if (!vaddr) {
devres_free(dr);
return NULL;
}
dr->vaddr = vaddr;
dr->dma_handle = *dma_handle;
dr->size = size;
devres_add(dev, dr);
return vaddr;
}
EXPORT_SYMBOL(dmam_alloc_coherent);
/**
* dmam_free_coherent - Managed dma_free_coherent()
* @dev: Device to free coherent memory for
* @size: Size of allocation
* @vaddr: Virtual address of the memory to free
* @dma_handle: DMA handle of the memory to free
*
* Managed dma_free_coherent().
*/
void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
struct dma_devres match_data = { size, vaddr, dma_handle };
WARN_ON(devres_destroy(dev, dmam_release, dmam_match, &match_data));
dma_free_coherent(dev, size, vaddr, dma_handle);
}
EXPORT_SYMBOL(dmam_free_coherent);
/**
* dmam_alloc_attrs - Managed dma_alloc_attrs()
* @dev: Device to allocate non_coherent memory for
* @size: Size of allocation
* @dma_handle: Out argument for allocated DMA handle
* @gfp: Allocation flags
* @attrs: Flags in the DMA_ATTR_* namespace.
*
* Managed dma_alloc_attrs(). Memory allocated using this function will be
* automatically released on driver detach.
*
* RETURNS:
* Pointer to allocated memory on success, NULL on failure.
*/
void *dmam_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t gfp, unsigned long attrs)
{
struct dma_devres *dr;
void *vaddr;
dr = devres_alloc(dmam_release, sizeof(*dr), gfp);
if (!dr)
return NULL;
vaddr = dma_alloc_attrs(dev, size, dma_handle, gfp, attrs);
if (!vaddr) {
devres_free(dr);
return NULL;
}
dr->vaddr = vaddr;
dr->dma_handle = *dma_handle;
dr->size = size;
dr->attrs = attrs;
devres_add(dev, dr);
return vaddr;
}
EXPORT_SYMBOL(dmam_alloc_attrs);
#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
static void dmam_coherent_decl_release(struct device *dev, void *res)
{
dma_release_declared_memory(dev);
}
/**
* dmam_declare_coherent_memory - Managed dma_declare_coherent_memory()
* @dev: Device to declare coherent memory for
* @phys_addr: Physical address of coherent memory to be declared
* @device_addr: Device address of coherent memory to be declared
* @size: Size of coherent memory to be declared
* @flags: Flags
*
* Managed dma_declare_coherent_memory().
*
* RETURNS:
* 0 on success, -errno on failure.
*/
int dmam_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
dma_addr_t device_addr, size_t size, int flags)
{
void *res;
int rc;
res = devres_alloc(dmam_coherent_decl_release, 0, GFP_KERNEL);
if (!res)
return -ENOMEM;
rc = dma_declare_coherent_memory(dev, phys_addr, device_addr, size,
flags);
if (!rc)
devres_add(dev, res);
else
devres_free(res);
return rc;
}
EXPORT_SYMBOL(dmam_declare_coherent_memory);
/**
* dmam_release_declared_memory - Managed dma_release_declared_memory().
* @dev: Device to release declared coherent memory for
*
* Managed dmam_release_declared_memory().
*/
void dmam_release_declared_memory(struct device *dev)
{
WARN_ON(devres_destroy(dev, dmam_coherent_decl_release, NULL, NULL));
}
EXPORT_SYMBOL(dmam_release_declared_memory);
#endif
/*
* Create scatter-list for the already allocated DMA buffer.
*/
int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t handle, size_t size)
{
struct page *page = virt_to_page(cpu_addr);
int ret;
ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
if (unlikely(ret))
return ret;
sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
return 0;
}
EXPORT_SYMBOL(dma_common_get_sgtable);
/*
* Create userspace mapping for the DMA-coherent memory.
*/
int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size)
{
int ret = -ENXIO;
#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP
unsigned long user_count = vma_pages(vma);
unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
unsigned long off = vma->vm_pgoff;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
return ret;
if (off < count && user_count <= (count - off))
ret = remap_pfn_range(vma, vma->vm_start,
page_to_pfn(virt_to_page(cpu_addr)) + off,
user_count << PAGE_SHIFT,
vma->vm_page_prot);
#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
return ret;
}
EXPORT_SYMBOL(dma_common_mmap);
#ifdef CONFIG_MMU
static struct vm_struct *__dma_common_pages_remap(struct page **pages,
size_t size, unsigned long vm_flags, pgprot_t prot,
const void *caller)
{
struct vm_struct *area;
area = get_vm_area_caller(size, vm_flags, caller);
if (!area)
return NULL;
if (map_vm_area(area, prot, pages)) {
vunmap(area->addr);
return NULL;
}
return area;
}
/*
* remaps an array of PAGE_SIZE pages into another vm_area
* Cannot be used in non-sleeping contexts
*/
void *dma_common_pages_remap(struct page **pages, size_t size,
unsigned long vm_flags, pgprot_t prot,
const void *caller)
{
struct vm_struct *area;
area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller);
if (!area)
return NULL;
area->pages = pages;
return area->addr;
}
/*
* remaps an allocated contiguous region into another vm_area.
* Cannot be used in non-sleeping contexts
*/
void *dma_common_contiguous_remap(struct page *page, size_t size,
unsigned long vm_flags,
pgprot_t prot, const void *caller)
{
unsigned long i;
struct page **pages;
struct vm_struct *area;
pages = kvmalloc(sizeof(struct page *) << get_order(size), GFP_KERNEL);
if (!pages)
return NULL;
for (i = 0; i < (size >> PAGE_SHIFT); i++)
pages[i] = nth_page(page, i);
area = __dma_common_pages_remap(pages, size, vm_flags, prot, caller);
kvfree(pages);
if (!area)
return NULL;
return area->addr;
}
/*
* unmaps a range previously mapped by dma_common_*_remap
*/
void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags,
bool no_warn)
{
struct vm_struct *area = find_vm_area(cpu_addr);
if (!area || (area->flags & vm_flags) != vm_flags) {
WARN(!no_warn, "trying to free invalid coherent area: %p\n",
cpu_addr);
return;
}
unmap_kernel_range((unsigned long)cpu_addr, PAGE_ALIGN(size));
vunmap(cpu_addr);
}
#endif
/*
* enables DMA API use for a device
*/
int dma_configure(struct device *dev)
{
if (dev->bus->dma_configure)
return dev->bus->dma_configure(dev);
return 0;
}
void dma_deconfigure(struct device *dev)
{
of_dma_deconfigure(dev);
acpi_dma_deconfigure(dev);
}