Files
kernel/sound/usb/card.c
Greg Kroah-Hartman 011b73c995 Merge 4.19.191 into android-4.19-stable
Changes in 4.19.191
	s390/disassembler: increase ebpf disasm buffer size
	ACPI: custom_method: fix potential use-after-free issue
	ACPI: custom_method: fix a possible memory leak
	ftrace: Handle commands when closing set_ftrace_filter file
	ARM: 9056/1: decompressor: fix BSS size calculation for LLVM ld.lld
	arm64: dts: marvell: armada-37xx: add syscon compatible to NB clk node
	arm64: dts: mt8173: fix property typo of 'phys' in dsi node
	ecryptfs: fix kernel panic with null dev_name
	mtd: spinand: core: add missing MODULE_DEVICE_TABLE()
	mtd: rawnand: atmel: Update ecc_stats.corrected counter
	spi: spi-ti-qspi: Free DMA resources
	scsi: qla2xxx: Fix crash in qla2xxx_mqueuecommand()
	mmc: sdhci-pci: Fix initialization of some SD cards for Intel BYT-based controllers
	mmc: block: Update ext_csd.cache_ctrl if it was written
	mmc: block: Issue a cache flush only when it's enabled
	mmc: core: Do a power cycle when the CMD11 fails
	mmc: core: Set read only for SD cards with permanent write protect bit
	erofs: add unsupported inode i_format check
	cifs: Return correct error code from smb2_get_enc_key
	btrfs: fix metadata extent leak after failure to create subvolume
	intel_th: pci: Add Rocket Lake CPU support
	fbdev: zero-fill colormap in fbcmap.c
	staging: wimax/i2400m: fix byte-order issue
	crypto: api - check for ERR pointers in crypto_destroy_tfm()
	usb: gadget: uvc: add bInterval checking for HS mode
	genirq/matrix: Prevent allocation counter corruption
	usb: gadget: f_uac1: validate input parameters
	usb: dwc3: gadget: Ignore EP queue requests during bus reset
	usb: xhci: Fix port minor revision
	PCI: PM: Do not read power state in pci_enable_device_flags()
	x86/build: Propagate $(CLANG_FLAGS) to $(REALMODE_FLAGS)
	tee: optee: do not check memref size on return from Secure World
	perf/arm_pmu_platform: Fix error handling
	usb: xhci-mtk: support quirk to disable usb2 lpm
	xhci: check control context is valid before dereferencing it.
	xhci: fix potential array out of bounds with several interrupters
	spi: dln2: Fix reference leak to master
	spi: omap-100k: Fix reference leak to master
	intel_th: Consistency and off-by-one fix
	phy: phy-twl4030-usb: Fix possible use-after-free in twl4030_usb_remove()
	btrfs: convert logic BUG_ON()'s in replace_path to ASSERT()'s
	scsi: lpfc: Fix incorrect dbde assignment when building target abts wqe
	scsi: lpfc: Fix pt2pt connection does not recover after LOGO
	scsi: target: pscsi: Fix warning in pscsi_complete_cmd()
	media: ite-cir: check for receive overflow
	media: drivers: media: pci: sta2x11: fix Kconfig dependency on GPIOLIB
	power: supply: bq27xxx: fix power_avg for newer ICs
	extcon: arizona: Fix some issues when HPDET IRQ fires after the jack has been unplugged
	media: media/saa7164: fix saa7164_encoder_register() memory leak bugs
	media: gspca/sq905.c: fix uninitialized variable
	power: supply: Use IRQF_ONESHOT
	drm/amdgpu : Fix asic reset regression issue introduce by 8f211fe8ac7c4f
	scsi: qla2xxx: Always check the return value of qla24xx_get_isp_stats()
	scsi: qla2xxx: Fix use after free in bsg
	scsi: scsi_dh_alua: Remove check for ASC 24h in alua_rtpg()
	media: em28xx: fix memory leak
	media: vivid: update EDID
	clk: socfpga: arria10: Fix memory leak of socfpga_clk on error return
	power: supply: generic-adc-battery: fix possible use-after-free in gab_remove()
	power: supply: s3c_adc_battery: fix possible use-after-free in s3c_adc_bat_remove()
	media: tc358743: fix possible use-after-free in tc358743_remove()
	media: adv7604: fix possible use-after-free in adv76xx_remove()
	media: i2c: adv7511-v4l2: fix possible use-after-free in adv7511_remove()
	media: i2c: adv7842: fix possible use-after-free in adv7842_remove()
	media: dvb-usb: fix memory leak in dvb_usb_adapter_init
	media: gscpa/stv06xx: fix memory leak
	drm/msm/mdp5: Configure PP_SYNC_HEIGHT to double the vtotal
	amdgpu: avoid incorrect %hu format string
	drm/amdgpu: fix NULL pointer dereference
	scsi: lpfc: Fix crash when a REG_RPI mailbox fails triggering a LOGO response
	scsi: lpfc: Remove unsupported mbox PORT_CAPABILITIES logic
	scsi: libfc: Fix a format specifier
	s390/archrandom: add parameter check for s390_arch_random_generate
	ALSA: emu8000: Fix a use after free in snd_emu8000_create_mixer
	ALSA: hda/conexant: Re-order CX5066 quirk table entries
	ALSA: sb: Fix two use after free in snd_sb_qsound_build
	ALSA: usb-audio: Explicitly set up the clock selector
	ALSA: usb-audio: More constifications
	ALSA: usb-audio: Add dB range mapping for Sennheiser Communications Headset PC 8
	ALSA: hda/realtek: Add quirk for Intel Clevo PCx0Dx
	btrfs: fix race when picking most recent mod log operation for an old root
	arm64/vdso: Discard .note.gnu.property sections in vDSO
	ubifs: Only check replay with inode type to judge if inode linked
	f2fs: fix to avoid out-of-bounds memory access
	mlxsw: spectrum_mr: Update egress RIF list before route's action
	openvswitch: fix stack OOB read while fragmenting IPv4 packets
	ACPI: GTDT: Don't corrupt interrupt mappings on watchdow probe failure
	NFS: Don't discard pNFS layout segments that are marked for return
	NFSv4: Don't discard segments marked for return in _pnfs_return_layout()
	jffs2: Fix kasan slab-out-of-bounds problem
	powerpc/eeh: Fix EEH handling for hugepages in ioremap space.
	powerpc: fix EDEADLOCK redefinition error in uapi/asm/errno.h
	intel_th: pci: Add Alder Lake-M support
	tpm: vtpm_proxy: Avoid reading host log when using a virtual device
	md/raid1: properly indicate failure when ending a failed write request
	dm raid: fix inconclusive reshape layout on fast raid4/5/6 table reload sequences
	security: commoncap: fix -Wstringop-overread warning
	Fix misc new gcc warnings
	jffs2: check the validity of dstlen in jffs2_zlib_compress()
	Revert 337f13046f ("futex: Allow FUTEX_CLOCK_REALTIME with FUTEX_WAIT op")
	posix-timers: Preserve return value in clock_adjtime32()
	arm64: vdso: remove commas between macro name and arguments
	ext4: fix check to prevent false positive report of incorrect used inodes
	ext4: do not set SB_ACTIVE in ext4_orphan_cleanup()
	ext4: fix error code in ext4_commit_super
	media: dvbdev: Fix memory leak in dvb_media_device_free()
	usb: gadget: dummy_hcd: fix gpf in gadget_setup
	usb: gadget: Fix double free of device descriptor pointers
	usb: gadget/function/f_fs string table fix for multiple languages
	usb: dwc3: gadget: Fix START_TRANSFER link state check
	usb: dwc2: Fix session request interrupt handler
	tty: fix memory leak in vc_deallocate
	rsi: Use resume_noirq for SDIO
	tracing: Map all PIDs to command lines
	tracing: Restructure trace_clock_global() to never block
	dm persistent data: packed struct should have an aligned() attribute too
	dm space map common: fix division bug in sm_ll_find_free_block()
	dm rq: fix double free of blk_mq_tag_set in dev remove after table load fails
	modules: mark ref_module static
	modules: mark find_symbol static
	modules: mark each_symbol_section static
	modules: unexport __module_text_address
	modules: unexport __module_address
	modules: rename the licence field in struct symsearch to license
	modules: return licensing information from find_symbol
	modules: inherit TAINT_PROPRIETARY_MODULE
	Bluetooth: verify AMP hci_chan before amp_destroy
	hsr: use netdev_err() instead of WARN_ONCE()
	bluetooth: eliminate the potential race condition when removing the HCI controller
	net/nfc: fix use-after-free llcp_sock_bind/connect
	ASoC: samsung: tm2_wm5110: check of of_parse return value
	MIPS: pci-mt7620: fix PLL lock check
	MIPS: pci-rt2880: fix slot 0 configuration
	FDDI: defxx: Bail out gracefully with unassigned PCI resource for CSR
	iio:accel:adis16201: Fix wrong axis assignment that prevents loading
	misc: lis3lv02d: Fix false-positive WARN on various HP models
	misc: vmw_vmci: explicitly initialize vmci_notify_bm_set_msg struct
	misc: vmw_vmci: explicitly initialize vmci_datagram payload
	md/bitmap: wait for external bitmap writes to complete during tear down
	md-cluster: fix use-after-free issue when removing rdev
	md: split mddev_find
	md: factor out a mddev_find_locked helper from mddev_find
	md: md_open returns -EBUSY when entering racing area
	md: Fix missing unused status line of /proc/mdstat
	ipw2x00: potential buffer overflow in libipw_wx_set_encodeext()
	cfg80211: scan: drop entry from hidden_list on overflow
	drm/radeon: fix copy of uninitialized variable back to userspace
	ALSA: hda/realtek: Re-order ALC882 Acer quirk table entries
	ALSA: hda/realtek: Re-order ALC882 Sony quirk table entries
	ALSA: hda/realtek: Re-order ALC882 Clevo quirk table entries
	ALSA: hda/realtek: Re-order ALC269 HP quirk table entries
	ALSA: hda/realtek: Re-order ALC269 Dell quirk table entries
	ALSA: hda/realtek: Re-order ALC269 Sony quirk table entries
	ALSA: hda/realtek: Re-order ALC269 Lenovo quirk table entries
	ALSA: hda/realtek: Remove redundant entry for ALC861 Haier/Uniwill devices
	x86/cpu: Initialize MSR_TSC_AUX if RDTSCP *or* RDPID is supported
	KVM: s390: split kvm_s390_logical_to_effective
	KVM: s390: fix guarded storage control register handling
	KVM: s390: split kvm_s390_real_to_abs
	ovl: fix missing revert_creds() on error path
	usb: gadget: pch_udc: Revert d3cb25a121 completely
	memory: gpmc: fix out of bounds read and dereference on gpmc_cs[]
	ARM: dts: exynos: correct fuel gauge interrupt trigger level on Midas family
	ARM: dts: exynos: correct MUIC interrupt trigger level on Midas family
	ARM: dts: exynos: correct PMIC interrupt trigger level on Midas family
	ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid X/U3 family
	ARM: dts: exynos: correct PMIC interrupt trigger level on SMDK5250
	ARM: dts: exynos: correct PMIC interrupt trigger level on Snow
	serial: stm32: fix incorrect characters on console
	serial: stm32: fix tx_empty condition
	usb: typec: tcpci: Check ROLE_CONTROL while interpreting CC_STATUS
	regmap: set debugfs_name to NULL after it is freed
	mtd: rawnand: fsmc: Fix error code in fsmc_nand_probe()
	mtd: rawnand: brcmnand: fix OOB R/W with Hamming ECC
	mtd: Handle possible -EPROBE_DEFER from parse_mtd_partitions()
	mtd: rawnand: qcom: Return actual error code instead of -ENODEV
	x86/microcode: Check for offline CPUs before requesting new microcode
	usb: gadget: pch_udc: Replace cpu_to_le32() by lower_32_bits()
	usb: gadget: pch_udc: Check if driver is present before calling ->setup()
	usb: gadget: pch_udc: Check for DMA mapping error
	crypto: qat - don't release uninitialized resources
	crypto: qat - ADF_STATUS_PF_RUNNING should be set after adf_dev_init
	fotg210-udc: Fix DMA on EP0 for length > max packet size
	fotg210-udc: Fix EP0 IN requests bigger than two packets
	fotg210-udc: Remove a dubious condition leading to fotg210_done
	fotg210-udc: Mask GRP2 interrupts we don't handle
	fotg210-udc: Don't DMA more than the buffer can take
	fotg210-udc: Complete OUT requests on short packets
	mtd: require write permissions for locking and badblock ioctls
	bus: qcom: Put child node before return
	soundwire: bus: Fix device found flag correctly
	phy: marvell: ARMADA375_USBCLUSTER_PHY should not default to y, unconditionally
	crypto: qat - fix error path in adf_isr_resource_alloc()
	usb: gadget: aspeed: fix dma map failure
	USB: gadget: udc: fix wrong pointer passed to IS_ERR() and PTR_ERR()
	soundwire: stream: fix memory leak in stream config error path
	mtd: rawnand: gpmi: Fix a double free in gpmi_nand_init
	irqchip/gic-v3: Fix OF_BAD_ADDR error handling
	staging: rtl8192u: Fix potential infinite loop
	staging: greybus: uart: fix unprivileged TIOCCSERIAL
	spi: Fix use-after-free with devm_spi_alloc_*
	soc: qcom: mdt_loader: Validate that p_filesz < p_memsz
	soc: qcom: mdt_loader: Detect truncated read of segments
	ACPI: CPPC: Replace cppc_attr with kobj_attribute
	crypto: qat - Fix a double free in adf_create_ring
	cpufreq: armada-37xx: Fix setting TBG parent for load levels
	clk: mvebu: armada-37xx-periph: remove .set_parent method for CPU PM clock
	cpufreq: armada-37xx: Fix the AVS value for load L1
	clk: mvebu: armada-37xx-periph: Fix switching CPU freq from 250 Mhz to 1 GHz
	clk: mvebu: armada-37xx-periph: Fix workaround for switching from L1 to L0
	cpufreq: armada-37xx: Fix driver cleanup when registration failed
	cpufreq: armada-37xx: Fix determining base CPU frequency
	usb: gadget: r8a66597: Add missing null check on return from platform_get_resource
	USB: cdc-acm: fix unprivileged TIOCCSERIAL
	tty: actually undefine superseded ASYNC flags
	tty: fix return value for unsupported ioctls
	firmware: qcom-scm: Fix QCOM_SCM configuration
	usbip: vudc: fix missing unlock on error in usbip_sockfd_store()
	platform/x86: pmc_atom: Match all Beckhoff Automation baytrail boards with critclk_systems DMI table
	x86/platform/uv: Fix !KEXEC build failure
	Drivers: hv: vmbus: Increase wait time for VMbus unload
	usb: dwc2: Fix host mode hibernation exit with remote wakeup flow.
	usb: dwc2: Fix hibernation between host and device modes.
	ttyprintk: Add TTY hangup callback.
	soc: aspeed: fix a ternary sign expansion bug
	media: vivid: fix assignment of dev->fbuf_out_flags
	media: omap4iss: return error code when omap4iss_get() failed
	media: m88rs6000t: avoid potential out-of-bounds reads on arrays
	drm/amdkfd: fix build error with AMD_IOMMU_V2=m
	x86/kprobes: Fix to check non boostable prefixes correctly
	pata_arasan_cf: fix IRQ check
	pata_ipx4xx_cf: fix IRQ check
	sata_mv: add IRQ checks
	ata: libahci_platform: fix IRQ check
	nvme: retrigger ANA log update if group descriptor isn't found
	vfio/mdev: Do not allow a mdev_type to have a NULL parent pointer
	clk: qcom: a53-pll: Add missing MODULE_DEVICE_TABLE
	clk: uniphier: Fix potential infinite loop
	scsi: jazz_esp: Add IRQ check
	scsi: sun3x_esp: Add IRQ check
	scsi: sni_53c710: Add IRQ check
	scsi: ibmvfc: Fix invalid state machine BUG_ON()
	mfd: stm32-timers: Avoid clearing auto reload register
	HSI: core: fix resource leaks in hsi_add_client_from_dt()
	x86/events/amd/iommu: Fix sysfs type mismatch
	sched/debug: Fix cgroup_path[] serialization
	drivers/block/null_blk/main: Fix a double free in null_init.
	HID: plantronics: Workaround for double volume key presses
	perf symbols: Fix dso__fprintf_symbols_by_name() to return the number of printed chars
	net: lapbether: Prevent racing when checking whether the netif is running
	powerpc/prom: Mark identical_pvr_fixup as __init
	powerpc: Fix HAVE_HARDLOCKUP_DETECTOR_ARCH build configuration
	ALSA: core: remove redundant spin_lock pair in snd_card_disconnect
	bug: Remove redundant condition check in report_bug
	nfc: pn533: prevent potential memory corruption
	net: hns3: Limiting the scope of vector_ring_chain variable
	ALSA: usb-audio: Add error checks for usb_driver_claim_interface() calls
	liquidio: Fix unintented sign extension of a left shift of a u16
	powerpc/64s: Fix pte update for kernel memory on radix
	powerpc/perf: Fix PMU constraint check for EBB events
	powerpc: iommu: fix build when neither PCI or IBMVIO is set
	mac80211: bail out if cipher schemes are invalid
	mt7601u: fix always true expression
	IB/hfi1: Fix error return code in parse_platform_config()
	net: thunderx: Fix unintentional sign extension issue
	RDMA/srpt: Fix error return code in srpt_cm_req_recv()
	i2c: cadence: add IRQ check
	i2c: emev2: add IRQ check
	i2c: jz4780: add IRQ check
	i2c: sh7760: add IRQ check
	ASoC: ak5558: correct reset polarity
	drm/i915/gvt: Fix error code in intel_gvt_init_device()
	MIPS: pci-legacy: stop using of_pci_range_to_resource
	powerpc/pseries: extract host bridge from pci_bus prior to bus removal
	rtlwifi: 8821ae: upgrade PHY and RF parameters
	i2c: sh7760: fix IRQ error path
	mwl8k: Fix a double Free in mwl8k_probe_hw
	vsock/vmci: log once the failed queue pair allocation
	RDMA/i40iw: Fix error unwinding when i40iw_hmc_sd_one fails
	ALSA: usb: midi: don't return -ENOMEM when usb_urb_ep_type_check fails
	net: davinci_emac: Fix incorrect masking of tx and rx error channel
	ath9k: Fix error check in ath9k_hw_read_revisions() for PCI devices
	ath10k: Fix ath10k_wmi_tlv_op_pull_peer_stats_info() unlock without lock
	powerpc/52xx: Fix an invalid ASM expression ('addi' used instead of 'add')
	bnxt_en: fix ternary sign extension bug in bnxt_show_temp()
	ARM: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for RTL8211E
	arm64: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for RTL8211E
	net: geneve: modify IP header check in geneve6_xmit_skb and geneve_xmit_skb
	net:emac/emac-mac: Fix a use after free in emac_mac_tx_buf_send
	RDMA/bnxt_re: Fix a double free in bnxt_qplib_alloc_res
	net:nfc:digital: Fix a double free in digital_tg_recv_dep_req
	kfifo: fix ternary sign extension bugs
	mm/sparse: add the missing sparse_buffer_fini() in error branch
	mm/memory-failure: unnecessary amount of unmapping
	net: Only allow init netns to set default tcp cong to a restricted algo
	smp: Fix smp_call_function_single_async prototype
	Revert "net/sctp: fix race condition in sctp_destroy_sock"
	sctp: delay auto_asconf init until binding the first addr
	Revert "of/fdt: Make sure no-map does not remove already reserved regions"
	Revert "fdt: Properly handle "no-map" field in the memory region"
	tpm: fix error return code in tpm2_get_cc_attrs_tbl()
	fs: dlm: fix debugfs dump
	tipc: convert dest node's address to network order
	ASoC: Intel: bytcr_rt5640: Enable jack-detect support on Asus T100TAF
	net: stmmac: Set FIFO sizes for ipq806x
	i2c: bail out early when RDWR parameters are wrong
	ALSA: hdsp: don't disable if not enabled
	ALSA: hdspm: don't disable if not enabled
	ALSA: rme9652: don't disable if not enabled
	Bluetooth: Set CONF_NOT_COMPLETE as l2cap_chan default
	Bluetooth: initialize skb_queue_head at l2cap_chan_create()
	net: bridge: when suppression is enabled exclude RARP packets
	Bluetooth: check for zapped sk before connecting
	ip6_vti: proper dev_{hold|put} in ndo_[un]init methods
	ASoC: Intel: bytcr_rt5640: Add quirk for the Chuwi Hi8 tablet
	i2c: Add I2C_AQ_NO_REP_START adapter quirk
	mac80211: clear the beacon's CRC after channel switch
	pinctrl: samsung: use 'int' for register masks in Exynos
	cuse: prevent clone
	selftests: Set CC to clang in lib.mk if LLVM is set
	kconfig: nconf: stop endless search loops
	sctp: Fix out-of-bounds warning in sctp_process_asconf_param()
	powerpc/smp: Set numa node before updating mask
	ASoC: rt286: Generalize support for ALC3263 codec
	ethtool: ioctl: Fix out-of-bounds warning in store_link_ksettings_for_user()
	samples/bpf: Fix broken tracex1 due to kprobe argument change
	powerpc/pseries: Stop calling printk in rtas_stop_self()
	wl3501_cs: Fix out-of-bounds warnings in wl3501_send_pkt
	wl3501_cs: Fix out-of-bounds warnings in wl3501_mgmt_join
	powerpc/iommu: Annotate nested lock for lockdep
	net: ethernet: mtk_eth_soc: fix RX VLAN offload
	ia64: module: fix symbolizer crash on fdescr
	ASoC: rt286: Make RT286_SET_GPIO_* readable and writable
	f2fs: fix a redundant call to f2fs_balance_fs if an error occurs
	PCI: iproc: Fix return value of iproc_msi_irq_domain_alloc()
	PCI: Release OF node in pci_scan_device()'s error path
	ARM: 9064/1: hw_breakpoint: Do not directly check the event's overflow_handler hook
	rpmsg: qcom_glink_native: fix error return code of qcom_glink_rx_data()
	NFSv4.2: Always flush out writes in nfs42_proc_fallocate()
	NFS: Deal correctly with attribute generation counter overflow
	PCI: endpoint: Fix missing destroy_workqueue()
	pNFS/flexfiles: fix incorrect size check in decode_nfs_fh()
	NFSv4.2 fix handling of sr_eof in SEEK's reply
	rtc: ds1307: Fix wday settings for rx8130
	net: hns3: disable phy loopback setting in hclge_mac_start_phy
	sctp: do asoc update earlier in sctp_sf_do_dupcook_a
	ethernet:enic: Fix a use after free bug in enic_hard_start_xmit
	sctp: fix a SCTP_MIB_CURRESTAB leak in sctp_sf_do_dupcook_b
	netfilter: xt_SECMARK: add new revision to fix structure layout
	drm/radeon: Fix off-by-one power_state index heap overwrite
	drm/radeon: Avoid power table parsing memory leaks
	khugepaged: fix wrong result value for trace_mm_collapse_huge_page_isolate()
	mm/hugeltb: handle the error case in hugetlb_fix_reserve_counts()
	ksm: fix potential missing rmap_item for stable_node
	net: fix nla_strcmp to handle more then one trailing null character
	smc: disallow TCP_ULP in smc_setsockopt()
	netfilter: nfnetlink_osf: Fix a missing skb_header_pointer() NULL check
	sched/fair: Fix unfairness caused by missing load decay
	kernel: kexec_file: fix error return code of kexec_calculate_store_digests()
	netfilter: nftables: avoid overflows in nft_hash_buckets()
	i40e: Fix use-after-free in i40e_client_subtask()
	ARC: entry: fix off-by-one error in syscall number validation
	powerpc/64s: Fix crashes when toggling stf barrier
	powerpc/64s: Fix crashes when toggling entry flush barrier
	hfsplus: prevent corruption in shrinking truncate
	squashfs: fix divide error in calculate_skip()
	userfaultfd: release page in error path to avoid BUG_ON
	drm/radeon/dpm: Disable sclk switching on Oland when two 4K 60Hz monitors are connected
	iio: proximity: pulsedlight: Fix rumtime PM imbalance on error
	usb: fotg210-hcd: Fix an error message
	ACPI: scan: Fix a memory leak in an error handling path
	blk-mq: Swap two calls in blk_mq_exit_queue()
	usb: dwc3: omap: improve extcon initialization
	usb: dwc3: pci: Enable usb2-gadget-lpm-disable for Intel Merrifield
	usb: xhci: Increase timeout for HC halt
	usb: dwc2: Fix gadget DMA unmap direction
	usb: core: hub: fix race condition about TRSMRCY of resume
	usb: dwc3: gadget: Return success always for kick transfer in ep queue
	xhci: Do not use GFP_KERNEL in (potentially) atomic context
	xhci: Add reset resume quirk for AMD xhci controller.
	iio: gyro: mpu3050: Fix reported temperature value
	iio: tsl2583: Fix division by a zero lux_val
	cdc-wdm: untangle a circular dependency between callback and softint
	KVM: x86: Cancel pvclock_gtod_work on module removal
	FDDI: defxx: Make MMIO the configuration default except for EISA
	MIPS: Reinstate platform `__div64_32' handler
	MIPS: Avoid DIVU in `__div64_32' is result would be zero
	MIPS: Avoid handcoded DIVU in `__div64_32' altogether
	thermal/core/fair share: Lock the thermal zone while looping over instances
	kobject_uevent: remove warning in init_uevent_argv()
	netfilter: conntrack: Make global sysctls readonly in non-init netns
	clk: exynos7: Mark aclk_fsys1_200 as critical
	nvme: do not try to reconfigure APST when the controller is not live
	x86/msr: Fix wr/rdmsr_safe_regs_on_cpu() prototypes
	kgdb: fix gcc-11 warning on indentation
	usb: sl811-hcd: improve misleading indentation
	cxgb4: Fix the -Wmisleading-indentation warning
	isdn: capi: fix mismatched prototypes
	pinctrl: ingenic: Improve unreachable code generation
	xsk: Simplify detection of empty and full rings
	PCI: thunder: Fix compile testing
	ARM: 9066/1: ftrace: pause/unpause function graph tracer in cpu_suspend()
	ACPI / hotplug / PCI: Fix reference count leak in enable_slot()
	Input: elants_i2c - do not bind to i2c-hid compatible ACPI instantiated devices
	Input: silead - add workaround for x86 BIOS-es which bring the chip up in a stuck state
	um: Mark all kernel symbols as local
	ARM: 9075/1: kernel: Fix interrupted SMC calls
	scripts/recordmcount.pl: Fix RISC-V regex for clang
	riscv: Workaround mcount name prior to clang-13
	ceph: fix fscache invalidation
	scsi: target: tcmu: Return from tcmu_handle_completions() if cmd_id not found
	gpiolib: acpi: Add quirk to ignore EC wakeups on Dell Venue 10 Pro 5055
	ALSA: hda: generic: change the DAC ctl name for LO+SPK or LO+HP
	block: reexpand iov_iter after read/write
	lib: stackdepot: turn depot_lock spinlock to raw_spinlock
	net: stmmac: Do not enable RX FIFO overflow interrupts
	ip6_gre: proper dev_{hold|put} in ndo_[un]init methods
	sit: proper dev_{hold|put} in ndo_[un]init methods
	ip6_tunnel: sit: proper dev_{hold|put} in ndo_[un]init methods
	ipv6: remove extra dev_hold() for fallback tunnels
	iomap: fix sub-page uptodate handling
	KVM: arm64: Initialize VCPU mdcr_el2 before loading it
	tweewide: Fix most Shebang lines
	scripts: switch explicitly to Python 3
	Linux 4.19.191

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I2ea4fc6350bb5c5b5ae38ec7ad52ec20cf3b7aae
2021-05-22 11:54:36 +02:00

999 lines
27 KiB
C

/*
* (Tentative) USB Audio Driver for ALSA
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* Many codes borrowed from audio.c by
* Alan Cox (alan@lxorguk.ukuu.org.uk)
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* Audio Class 3.0 support by Ruslan Bilovol <ruslan.bilovol@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* NOTES:
*
* - the linked URBs would be preferred but not used so far because of
* the instability of unlinking.
* - type II is not supported properly. there is no device which supports
* this type *correctly*. SB extigy looks as if it supports, but it's
* indeed an AC3 stream packed in SPDIF frames (i.e. no real AC3 stream).
*/
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/usb.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
#include <linux/usb/audio-v3.h>
#include <linux/module.h>
#include <sound/control.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include "usbaudio.h"
#include "card.h"
#include "midi.h"
#include "mixer.h"
#include "proc.h"
#include "quirks.h"
#include "endpoint.h"
#include "helper.h"
#include "debug.h"
#include "pcm.h"
#include "format.h"
#include "power.h"
#include "stream.h"
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("USB Audio");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
/* Vendor/product IDs for this card */
static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
static bool ignore_ctl_error;
static bool autoclock = true;
static char *quirk_alias[SNDRV_CARDS];
bool snd_usb_use_vmalloc = true;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for the USB audio adapter.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable USB audio adapter.");
module_param_array(vid, int, NULL, 0444);
MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
module_param_array(pid, int, NULL, 0444);
MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
module_param_array(device_setup, int, NULL, 0444);
MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
module_param(ignore_ctl_error, bool, 0444);
MODULE_PARM_DESC(ignore_ctl_error,
"Ignore errors from USB controller for mixer interfaces.");
module_param(autoclock, bool, 0444);
MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
module_param_array(quirk_alias, charp, NULL, 0444);
MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);
MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");
/*
* we keep the snd_usb_audio_t instances by ourselves for merging
* the all interfaces on the same card as one sound device.
*/
static DEFINE_MUTEX(register_mutex);
static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
static struct usb_driver usb_audio_driver;
/**
* find_snd_usb_substream - helper API to find usb substream context
* information using card number, pcm device number and direction.
* @card_num: card number
* @pcm_idx: pcm device number
* @direction: SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE
* @uchip: substream context.
* disconnect_cb: callback to use for cleanup on disconnect.
*/
struct snd_usb_substream *find_snd_usb_substream(unsigned int card_num,
unsigned int pcm_idx, unsigned int direction, struct snd_usb_audio
**uchip, void (*disconnect_cb)(struct snd_usb_audio *chip))
{
int idx;
struct snd_usb_stream *as;
struct snd_usb_substream *subs = NULL;
struct snd_usb_audio *chip = NULL;
mutex_lock(&register_mutex);
/*
* legacy audio snd card number assignment is dynamic. Hence
* search using chip->card->number
*/
for (idx = 0; idx < SNDRV_CARDS; idx++) {
if (!usb_chip[idx] || !usb_chip[idx]->card)
continue;
if (usb_chip[idx]->card->number == card_num) {
chip = usb_chip[idx];
break;
}
}
if (!chip || atomic_read(&chip->shutdown)) {
pr_debug("%s: instance of usb card # %d does not exist\n",
__func__, card_num);
goto err;
}
if (pcm_idx >= chip->pcm_devs) {
usb_audio_err(chip, "%s: invalid pcm dev number %u > %d\n",
__func__, pcm_idx, chip->pcm_devs);
goto err;
}
if (direction > SNDRV_PCM_STREAM_CAPTURE) {
usb_audio_err(chip, "%s: invalid direction %u\n", __func__,
direction);
goto err;
}
list_for_each_entry(as, &chip->pcm_list, list) {
if (as->pcm_index == pcm_idx) {
subs = &as->substream[direction];
if (subs->interface < 0 && !subs->data_endpoint &&
!subs->sync_endpoint) {
usb_audio_err(chip, "%s: stream disconnected, bail out\n",
__func__);
subs = NULL;
goto err;
}
goto done;
}
}
done:
chip->card_num = card_num;
chip->disconnect_cb = disconnect_cb;
err:
*uchip = chip;
if (!subs)
pr_err("%s: substream instance not found\n", __func__);
mutex_unlock(&register_mutex);
return subs;
}
EXPORT_SYMBOL_GPL(find_snd_usb_substream);
/*
* disconnect streams
* called from usb_audio_disconnect()
*/
static void snd_usb_stream_disconnect(struct snd_usb_stream *as)
{
int idx;
struct snd_usb_substream *subs;
for (idx = 0; idx < 2; idx++) {
subs = &as->substream[idx];
if (!subs->num_formats)
continue;
subs->interface = -1;
subs->data_endpoint = NULL;
subs->sync_endpoint = NULL;
}
}
static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int interface)
{
struct usb_device *dev = chip->dev;
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
struct usb_interface *iface = usb_ifnum_to_if(dev, interface);
if (!iface) {
dev_err(&dev->dev, "%u:%d : does not exist\n",
ctrlif, interface);
return -EINVAL;
}
alts = &iface->altsetting[0];
altsd = get_iface_desc(alts);
/*
* Android with both accessory and audio interfaces enabled gets the
* interface numbers wrong.
*/
if ((chip->usb_id == USB_ID(0x18d1, 0x2d04) ||
chip->usb_id == USB_ID(0x18d1, 0x2d05)) &&
interface == 0 &&
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
altsd->bInterfaceSubClass == USB_SUBCLASS_VENDOR_SPEC) {
interface = 2;
iface = usb_ifnum_to_if(dev, interface);
if (!iface)
return -EINVAL;
alts = &iface->altsetting[0];
altsd = get_iface_desc(alts);
}
if (usb_interface_claimed(iface)) {
dev_dbg(&dev->dev, "%d:%d: skipping, already claimed\n",
ctrlif, interface);
return -EINVAL;
}
if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {
int err = __snd_usbmidi_create(chip->card, iface,
&chip->midi_list, NULL,
chip->usb_id);
if (err < 0) {
dev_err(&dev->dev,
"%u:%d: cannot create sequencer device\n",
ctrlif, interface);
return -EINVAL;
}
return usb_driver_claim_interface(&usb_audio_driver, iface,
USB_AUDIO_IFACE_UNUSED);
}
if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING) {
dev_dbg(&dev->dev,
"%u:%d: skipping non-supported interface %d\n",
ctrlif, interface, altsd->bInterfaceClass);
/* skip non-supported classes */
return -EINVAL;
}
if (snd_usb_get_speed(dev) == USB_SPEED_LOW) {
dev_err(&dev->dev, "low speed audio streaming not supported\n");
return -EINVAL;
}
if (! snd_usb_parse_audio_interface(chip, interface)) {
usb_set_interface(dev, interface, 0); /* reset the current interface */
return usb_driver_claim_interface(&usb_audio_driver, iface,
USB_AUDIO_IFACE_UNUSED);
}
return 0;
}
/*
* parse audio control descriptor and create pcm/midi streams
*/
static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
{
struct usb_device *dev = chip->dev;
struct usb_host_interface *host_iface;
struct usb_interface_descriptor *altsd;
int i, protocol;
/* find audiocontrol interface */
host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
altsd = get_iface_desc(host_iface);
protocol = altsd->bInterfaceProtocol;
switch (protocol) {
default:
dev_warn(&dev->dev,
"unknown interface protocol %#02x, assuming v1\n",
protocol);
/* fall through */
case UAC_VERSION_1: {
struct uac1_ac_header_descriptor *h1;
int rest_bytes;
h1 = snd_usb_find_csint_desc(host_iface->extra,
host_iface->extralen,
NULL, UAC_HEADER);
if (!h1 || h1->bLength < sizeof(*h1)) {
dev_err(&dev->dev, "cannot find UAC_HEADER\n");
return -EINVAL;
}
rest_bytes = (void *)(host_iface->extra +
host_iface->extralen) - (void *)h1;
/* just to be sure -- this shouldn't hit at all */
if (rest_bytes <= 0) {
dev_err(&dev->dev, "invalid control header\n");
return -EINVAL;
}
if (rest_bytes < sizeof(*h1)) {
dev_err(&dev->dev, "too short v1 buffer descriptor\n");
return -EINVAL;
}
if (!h1->bInCollection) {
dev_info(&dev->dev, "skipping empty audio interface (v1)\n");
return -EINVAL;
}
if (rest_bytes < h1->bLength) {
dev_err(&dev->dev, "invalid buffer length (v1)\n");
return -EINVAL;
}
if (h1->bLength < sizeof(*h1) + h1->bInCollection) {
dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n");
return -EINVAL;
}
for (i = 0; i < h1->bInCollection; i++)
snd_usb_create_stream(chip, ctrlif, h1->baInterfaceNr[i]);
break;
}
case UAC_VERSION_2:
case UAC_VERSION_3: {
struct usb_interface_assoc_descriptor *assoc =
usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
if (!assoc) {
/*
* Firmware writers cannot count to three. So to find
* the IAD on the NuForce UDH-100, also check the next
* interface.
*/
struct usb_interface *iface =
usb_ifnum_to_if(dev, ctrlif + 1);
if (iface &&
iface->intf_assoc &&
iface->intf_assoc->bFunctionClass == USB_CLASS_AUDIO &&
iface->intf_assoc->bFunctionProtocol == UAC_VERSION_2)
assoc = iface->intf_assoc;
}
if (!assoc) {
dev_err(&dev->dev, "Audio class v2/v3 interfaces need an interface association\n");
return -EINVAL;
}
if (protocol == UAC_VERSION_3) {
int badd = assoc->bFunctionSubClass;
if (badd != UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0 &&
(badd < UAC3_FUNCTION_SUBCLASS_GENERIC_IO ||
badd > UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE)) {
dev_err(&dev->dev,
"Unsupported UAC3 BADD profile\n");
return -EINVAL;
}
chip->badd_profile = badd;
}
for (i = 0; i < assoc->bInterfaceCount; i++) {
int intf = assoc->bFirstInterface + i;
if (intf != ctrlif)
snd_usb_create_stream(chip, ctrlif, intf);
}
break;
}
}
return 0;
}
/*
* free the chip instance
*
* here we have to do not much, since pcm and controls are already freed
*
*/
static void snd_usb_audio_free(struct snd_card *card)
{
struct snd_usb_audio *chip = card->private_data;
struct snd_usb_endpoint *ep, *n;
list_for_each_entry_safe(ep, n, &chip->ep_list, list)
snd_usb_endpoint_free(ep);
mutex_destroy(&chip->dev_lock);
mutex_destroy(&chip->mutex);
if (!atomic_read(&chip->shutdown))
dev_set_drvdata(&chip->dev->dev, NULL);
}
static void usb_audio_make_shortname(struct usb_device *dev,
struct snd_usb_audio *chip,
const struct snd_usb_audio_quirk *quirk)
{
struct snd_card *card = chip->card;
if (quirk && quirk->product_name && *quirk->product_name) {
strlcpy(card->shortname, quirk->product_name,
sizeof(card->shortname));
return;
}
/* retrieve the device string as shortname */
if (!dev->descriptor.iProduct ||
usb_string(dev, dev->descriptor.iProduct,
card->shortname, sizeof(card->shortname)) <= 0) {
/* no name available from anywhere, so use ID */
sprintf(card->shortname, "USB Device %#04x:%#04x",
USB_ID_VENDOR(chip->usb_id),
USB_ID_PRODUCT(chip->usb_id));
}
strim(card->shortname);
}
static void usb_audio_make_longname(struct usb_device *dev,
struct snd_usb_audio *chip,
const struct snd_usb_audio_quirk *quirk)
{
struct snd_card *card = chip->card;
int len;
/* shortcut - if any pre-defined string is given, use it */
if (quirk && quirk->profile_name && *quirk->profile_name) {
strlcpy(card->longname, quirk->profile_name,
sizeof(card->longname));
return;
}
if (quirk && quirk->vendor_name && *quirk->vendor_name) {
len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname));
} else {
/* retrieve the vendor and device strings as longname */
if (dev->descriptor.iManufacturer)
len = usb_string(dev, dev->descriptor.iManufacturer,
card->longname, sizeof(card->longname));
else
len = 0;
/* we don't really care if there isn't any vendor string */
}
if (len > 0) {
strim(card->longname);
if (*card->longname)
strlcat(card->longname, " ", sizeof(card->longname));
}
strlcat(card->longname, card->shortname, sizeof(card->longname));
len = strlcat(card->longname, " at ", sizeof(card->longname));
if (len < sizeof(card->longname))
usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
switch (snd_usb_get_speed(dev)) {
case USB_SPEED_LOW:
strlcat(card->longname, ", low speed", sizeof(card->longname));
break;
case USB_SPEED_FULL:
strlcat(card->longname, ", full speed", sizeof(card->longname));
break;
case USB_SPEED_HIGH:
strlcat(card->longname, ", high speed", sizeof(card->longname));
break;
case USB_SPEED_SUPER:
strlcat(card->longname, ", super speed", sizeof(card->longname));
break;
case USB_SPEED_SUPER_PLUS:
strlcat(card->longname, ", super speed plus", sizeof(card->longname));
break;
default:
break;
}
}
/*
* create a chip instance and set its names.
*/
static int snd_usb_audio_create(struct usb_interface *intf,
struct usb_device *dev, int idx,
const struct snd_usb_audio_quirk *quirk,
unsigned int usb_id,
struct snd_usb_audio **rchip)
{
struct snd_card *card;
struct snd_usb_audio *chip;
int err;
char component[14];
*rchip = NULL;
switch (snd_usb_get_speed(dev)) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
case USB_SPEED_WIRELESS:
case USB_SPEED_SUPER:
case USB_SPEED_SUPER_PLUS:
break;
default:
dev_err(&dev->dev, "unknown device speed %d\n", snd_usb_get_speed(dev));
return -ENXIO;
}
err = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,
sizeof(*chip), &card);
if (err < 0) {
dev_err(&dev->dev, "cannot create card instance %d\n", idx);
return err;
}
chip = card->private_data;
mutex_init(&chip->mutex);
mutex_init(&chip->dev_lock);
init_waitqueue_head(&chip->shutdown_wait);
chip->index = idx;
chip->dev = dev;
chip->card = card;
chip->setup = device_setup[idx];
chip->autoclock = autoclock;
atomic_set(&chip->active, 1); /* avoid autopm during probing */
atomic_set(&chip->usage_count, 0);
atomic_set(&chip->shutdown, 0);
chip->usb_id = usb_id;
INIT_LIST_HEAD(&chip->pcm_list);
INIT_LIST_HEAD(&chip->ep_list);
INIT_LIST_HEAD(&chip->midi_list);
INIT_LIST_HEAD(&chip->mixer_list);
card->private_free = snd_usb_audio_free;
strcpy(card->driver, "USB-Audio");
sprintf(component, "USB%04x:%04x",
USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
snd_component_add(card, component);
usb_audio_make_shortname(dev, chip, quirk);
usb_audio_make_longname(dev, chip, quirk);
snd_usb_audio_create_proc(chip);
*rchip = chip;
return 0;
}
/* look for a matching quirk alias id */
static bool get_alias_id(struct usb_device *dev, unsigned int *id)
{
int i;
unsigned int src, dst;
for (i = 0; i < ARRAY_SIZE(quirk_alias); i++) {
if (!quirk_alias[i] ||
sscanf(quirk_alias[i], "%x:%x", &src, &dst) != 2 ||
src != *id)
continue;
dev_info(&dev->dev,
"device (%04x:%04x): applying quirk alias %04x:%04x\n",
USB_ID_VENDOR(*id), USB_ID_PRODUCT(*id),
USB_ID_VENDOR(dst), USB_ID_PRODUCT(dst));
*id = dst;
return true;
}
return false;
}
static const struct usb_device_id usb_audio_ids[]; /* defined below */
/* look for the corresponding quirk */
static const struct snd_usb_audio_quirk *
get_alias_quirk(struct usb_device *dev, unsigned int id)
{
const struct usb_device_id *p;
for (p = usb_audio_ids; p->match_flags; p++) {
/* FIXME: this checks only vendor:product pair in the list */
if ((p->match_flags & USB_DEVICE_ID_MATCH_DEVICE) ==
USB_DEVICE_ID_MATCH_DEVICE &&
p->idVendor == USB_ID_VENDOR(id) &&
p->idProduct == USB_ID_PRODUCT(id))
return (const struct snd_usb_audio_quirk *)p->driver_info;
}
return NULL;
}
/*
* probe the active usb device
*
* note that this can be called multiple times per a device, when it
* includes multiple audio control interfaces.
*
* thus we check the usb device pointer and creates the card instance
* only at the first time. the successive calls of this function will
* append the pcm interface to the corresponding card.
*/
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *usb_id)
{
struct usb_device *dev = interface_to_usbdev(intf);
const struct snd_usb_audio_quirk *quirk =
(const struct snd_usb_audio_quirk *)usb_id->driver_info;
struct snd_usb_audio *chip;
int i, err;
struct usb_host_interface *alts;
int ifnum;
u32 id;
alts = &intf->altsetting[0];
ifnum = get_iface_desc(alts)->bInterfaceNumber;
id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
if (get_alias_id(dev, &id))
quirk = get_alias_quirk(dev, id);
if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
return -ENXIO;
err = snd_usb_apply_boot_quirk(dev, intf, quirk, id);
if (err < 0)
return err;
/*
* found a config. now register to ALSA
*/
/* check whether it's already registered */
chip = NULL;
mutex_lock(&register_mutex);
for (i = 0; i < SNDRV_CARDS; i++) {
if (usb_chip[i] && usb_chip[i]->dev == dev) {
if (atomic_read(&usb_chip[i]->shutdown)) {
dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n");
err = -EIO;
goto __error;
}
chip = usb_chip[i];
atomic_inc(&chip->active); /* avoid autopm */
break;
}
}
if (! chip) {
/* it's a fresh one.
* now look for an empty slot and create a new card instance
*/
for (i = 0; i < SNDRV_CARDS; i++)
if (!usb_chip[i] &&
(vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
(pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
if (enable[i]) {
err = snd_usb_audio_create(intf, dev, i, quirk,
id, &chip);
if (err < 0)
goto __error;
chip->pm_intf = intf;
break;
} else if (vid[i] != -1 || pid[i] != -1) {
dev_info(&dev->dev,
"device (%04x:%04x) is disabled\n",
USB_ID_VENDOR(id),
USB_ID_PRODUCT(id));
err = -ENOENT;
goto __error;
}
}
if (!chip) {
dev_err(&dev->dev, "no available usb audio device\n");
err = -ENODEV;
goto __error;
}
}
dev_set_drvdata(&dev->dev, chip);
/*
* For devices with more than one control interface, we assume the
* first contains the audio controls. We might need a more specific
* check here in the future.
*/
if (!chip->ctrl_intf)
chip->ctrl_intf = alts;
chip->txfr_quirk = 0;
err = 1; /* continue */
if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
/* need some special handlings */
err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk);
if (err < 0)
goto __error;
}
if (err > 0) {
/* create normal USB audio interfaces */
err = snd_usb_create_streams(chip, ifnum);
if (err < 0)
goto __error;
err = snd_usb_create_mixer(chip, ifnum, ignore_ctl_error);
if (err < 0)
goto __error;
}
/* we are allowed to call snd_card_register() many times, but first
* check to see if a device needs to skip it or do anything special
*/
if (!snd_usb_registration_quirk(chip, ifnum)) {
err = snd_card_register(chip->card);
if (err < 0)
goto __error;
}
usb_chip[chip->index] = chip;
chip->num_interfaces++;
usb_set_intfdata(intf, chip);
atomic_dec(&chip->active);
mutex_unlock(&register_mutex);
return 0;
__error:
if (chip) {
/* chip->active is inside the chip->card object,
* decrement before memory is possibly returned.
*/
atomic_dec(&chip->active);
if (!chip->num_interfaces)
snd_card_free(chip->card);
}
mutex_unlock(&register_mutex);
return err;
}
/*
* we need to take care of counter, since disconnection can be called also
* many times as well as usb_audio_probe().
*/
static void usb_audio_disconnect(struct usb_interface *intf)
{
struct snd_usb_audio *chip = usb_get_intfdata(intf);
struct snd_card *card;
struct list_head *p;
if (chip == USB_AUDIO_IFACE_UNUSED)
return;
card = chip->card;
mutex_lock(&register_mutex);
if (atomic_inc_return(&chip->shutdown) == 1) {
struct snd_usb_stream *as;
struct snd_usb_endpoint *ep;
struct usb_mixer_interface *mixer;
/* wait until all pending tasks done;
* they are protected by snd_usb_lock_shutdown()
*/
wait_event(chip->shutdown_wait,
!atomic_read(&chip->usage_count));
snd_card_disconnect(card);
/* release the pcm resources */
list_for_each_entry(as, &chip->pcm_list, list) {
snd_usb_stream_disconnect(as);
}
/* release the endpoint resources */
list_for_each_entry(ep, &chip->ep_list, list) {
snd_usb_endpoint_release(ep);
}
/* release the midi resources */
list_for_each(p, &chip->midi_list) {
snd_usbmidi_disconnect(p);
}
/* release mixer resources */
list_for_each_entry(mixer, &chip->mixer_list, list) {
snd_usb_mixer_disconnect(mixer);
}
}
chip->num_interfaces--;
if (chip->num_interfaces <= 0) {
usb_chip[chip->index] = NULL;
mutex_unlock(&register_mutex);
snd_card_free_when_closed(card);
} else {
mutex_unlock(&register_mutex);
}
}
/* lock the shutdown (disconnect) task and autoresume */
int snd_usb_lock_shutdown(struct snd_usb_audio *chip)
{
int err;
atomic_inc(&chip->usage_count);
if (atomic_read(&chip->shutdown)) {
err = -EIO;
goto error;
}
err = snd_usb_autoresume(chip);
if (err < 0)
goto error;
return 0;
error:
if (atomic_dec_and_test(&chip->usage_count))
wake_up(&chip->shutdown_wait);
return err;
}
/* autosuspend and unlock the shutdown */
void snd_usb_unlock_shutdown(struct snd_usb_audio *chip)
{
snd_usb_autosuspend(chip);
if (atomic_dec_and_test(&chip->usage_count))
wake_up(&chip->shutdown_wait);
}
#ifdef CONFIG_PM
int snd_usb_autoresume(struct snd_usb_audio *chip)
{
if (atomic_read(&chip->shutdown))
return -EIO;
if (atomic_inc_return(&chip->active) == 1)
return usb_autopm_get_interface(chip->pm_intf);
return 0;
}
void snd_usb_autosuspend(struct snd_usb_audio *chip)
{
if (atomic_read(&chip->shutdown))
return;
if (atomic_dec_and_test(&chip->active))
usb_autopm_put_interface(chip->pm_intf);
}
static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
{
struct snd_usb_audio *chip = usb_get_intfdata(intf);
struct snd_usb_stream *as;
struct usb_mixer_interface *mixer;
struct list_head *p;
if (chip == USB_AUDIO_IFACE_UNUSED)
return 0;
if (!chip->num_suspended_intf++) {
list_for_each_entry(as, &chip->pcm_list, list) {
snd_pcm_suspend_all(as->pcm);
snd_usb_pcm_suspend(as);
as->substream[0].need_setup_ep =
as->substream[1].need_setup_ep = true;
}
list_for_each(p, &chip->midi_list)
snd_usbmidi_suspend(p);
list_for_each_entry(mixer, &chip->mixer_list, list)
snd_usb_mixer_suspend(mixer);
}
if (!PMSG_IS_AUTO(message) && !chip->system_suspend) {
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
chip->system_suspend = chip->num_suspended_intf;
}
return 0;
}
static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
{
struct snd_usb_audio *chip = usb_get_intfdata(intf);
struct snd_usb_stream *as;
struct usb_mixer_interface *mixer;
struct list_head *p;
int err = 0;
if (chip == USB_AUDIO_IFACE_UNUSED)
return 0;
atomic_inc(&chip->active); /* avoid autopm */
if (chip->num_suspended_intf > 1)
goto out;
list_for_each_entry(as, &chip->pcm_list, list) {
err = snd_usb_pcm_resume(as);
if (err < 0)
goto err_out;
}
/*
* ALSA leaves material resumption to user space
* we just notify and restart the mixers
*/
list_for_each_entry(mixer, &chip->mixer_list, list) {
err = snd_usb_mixer_resume(mixer, reset_resume);
if (err < 0)
goto err_out;
}
list_for_each(p, &chip->midi_list) {
snd_usbmidi_resume(p);
}
out:
if (chip->num_suspended_intf == chip->system_suspend) {
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
chip->system_suspend = 0;
}
chip->num_suspended_intf--;
err_out:
atomic_dec(&chip->active); /* allow autopm after this point */
return err;
}
static int usb_audio_resume(struct usb_interface *intf)
{
return __usb_audio_resume(intf, false);
}
static int usb_audio_reset_resume(struct usb_interface *intf)
{
return __usb_audio_resume(intf, true);
}
#else
#define usb_audio_suspend NULL
#define usb_audio_resume NULL
#define usb_audio_reset_resume NULL
#endif /* CONFIG_PM */
static const struct usb_device_id usb_audio_ids [] = {
#include "quirks-table.h"
{ .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, usb_audio_ids);
/*
* entry point for linux usb interface
*/
static struct usb_driver usb_audio_driver = {
.name = "snd-usb-audio",
.probe = usb_audio_probe,
.disconnect = usb_audio_disconnect,
.suspend = usb_audio_suspend,
.resume = usb_audio_resume,
.reset_resume = usb_audio_reset_resume,
.id_table = usb_audio_ids,
.supports_autosuspend = 1,
};
module_usb_driver(usb_audio_driver);