* refs/heads/tmp-a9d0273:
Linux 4.9.84
crypto: s5p-sss - Fix kernel Oops in AES-ECB mode
KVM: nVMX: invvpid handling improvements
KVM: VMX: clean up declaration of VPID/EPT invalidation types
KVM: async_pf: Fix #DF due to inject "Page not Present" and "Page Ready" exceptions simultaneously
x86/microcode/AMD: Change load_microcode_amd()'s param to bool to fix preemptibility bug
usb: phy: msm add regulator dependency
arm64: fix warning about swapper_pg_dir overflow
idle: i7300: add PCI dependency
spi: bcm-qspi: shut up warning about cfi header inclusion
binfmt_elf: compat: avoid unused function warning
arm64: sunxi: always enable reset controller
drm/i915: hide unused intel_panel_set_backlight function
kasan: rework Kconfig settings
clk: meson: gxbb: fix build error without RESET_CONTROLLER
ISDN: eicon: reduce stack size of sig_ind function
tw5864: use dev_warn instead of WARN to shut up warning
em28xx: only use mt9v011 if camera support is enabled
go7007: add MEDIA_CAMERA_SUPPORT dependency
tc358743: fix register i2c_rd/wr functions
shmem: fix compilation warnings on unused functions
KVM: add X86_LOCAL_APIC dependency
Input: tca8418_keypad - hide gcc-4.9 -Wmaybe-uninitialized warning
drm/nouveau: hide gcc-4.9 -Wmaybe-uninitialized
rbd: silence bogus -Wmaybe-uninitialized warning
drm: exynos: mark pm functions as __maybe_unused
security/keys: BIG_KEY requires CONFIG_CRYPTO
cw1200: fix bogus maybe-uninitialized warning
reiserfs: avoid a -Wmaybe-uninitialized warning
ALSA: hda/ca0132 - fix possible NULL pointer use
arm64: Kconfig: select COMPAT_BINFMT_ELF only when BINFMT_ELF is set
scsi: advansys: fix uninitialized data access
x86/vm86: Fix unused variable warning if THP is disabled
x86/platform: Add PCI dependency for PUNIT_ATOM_DEBUG
dmaengine: zx: fix build warning
x86: add MULTIUSER dependency for KVM
thermal: fix INTEL_SOC_DTS_IOSF_CORE dependencies
x86/build: Silence the build with "make -s"
tools build: Add tools tree support for 'make -s'
x86/fpu/math-emu: Fix possible uninitialized variable use
arm64: define BUG() instruction without CONFIG_BUG
gpio: xgene: mark PM functions as __maybe_unused
x86/ras/inject: Make it depend on X86_LOCAL_APIC=y
scsi: advansys: fix build warning for PCI=n
video: fbdev: via: remove possibly unused variables
perf: xgene: Include module.h
PCI: Change pci_host_common_probe() visibility
usb: musb: fix compilation warning on unused function
platform/x86: intel_mid_thermal: Fix suspend handlers unused warning
gpio: intel-mid: Fix build warning when !CONFIG_PM
PCI: vmd: Fix suspend handlers defined-but-not-used warning
perf/x86: Shut up false-positive -Wmaybe-uninitialized warning
vmxnet3: prevent building with 64K pages
clk: sunxi-ng: fix build error without CONFIG_RESET_CONTROLLER
shmem: avoid maybe-uninitialized warning
drm/i915: fix intel_backlight_device_register declaration
crypto: talitos - fix Kernel Oops on hashing an empty file
powerpc/64s: Improve RFI L1-D cache flush fallback
powerpc/64s: Simple RFI macro conversions
powerpc/64s: Fix conversion of slb_miss_common to use RFI_TO_USER/KERNEL
hippi: Fix a Fix a possible sleep-in-atomic bug in rr_close
xen: XEN_ACPI_PROCESSOR is Dom0-only
platform/x86: dell-laptop: Fix keyboard max lighting for Dell Latitude E6410
x86/mm/kmmio: Fix mmiotrace for page unaligned addresses
mm/early_ioremap: Fix boot hang with earlyprintk=efi,keep
usb: dwc3: of-simple: fix missing clk_disable_unprepare
usb: dwc3: gadget: Wait longer for controller to end command processing
dmaengine: jz4740: disable/unprepare clk if probe fails
drm/armada: fix leak of crtc structure
xfrm: Fix stack-out-of-bounds with misconfigured transport mode policies.
spi: sun4i: disable clocks in the remove function
ASoC: rockchip: disable clock on error
clk: fix a panic error caused by accessing NULL pointer
dmaengine: at_hdmac: fix potential NULL pointer dereference in atc_prep_dma_interleaved
dmaengine: ioat: Fix error handling path
gianfar: Disable EEE autoneg by default
509: fix printing uninitialized stack memory when OID is empty
net: ethernet: arc: fix error handling in emac_rockchip_probe
brcmfmac: Avoid build error with make W=1
btrfs: Fix possible off-by-one in btrfs_search_path_in_tree
net_sched: red: Avoid illegal values
net_sched: red: Avoid devision by zero
gianfar: fix a flooded alignment reports because of padding issue.
ARM: dts: Fix elm interrupt compiler warning
s390/dasd: prevent prefix I/O error
powerpc/perf: Fix oops when grouping different pmu events
m68k: add missing SOFTIRQENTRY_TEXT linker section
ipvlan: Add the skb->mark as flow4's member to lookup route
scripts/kernel-doc: Don't fail with status != 0 if error encountered with -none
sctp: only update outstanding_bytes for transmitted queue when doing prsctp_prune
RDMA/cma: Make sure that PSN is not over max allowed
i40iw: Correct ARP index mask
pinctrl: sunxi: Fix A64 UART mux value
pinctrl: sunxi: Fix A80 interrupt pin bank
media: s5k6aa: describe some function parameters
perf bench numa: Fixup discontiguous/sparse numa nodes
perf top: Fix window dimensions change handling
ARM: dts: am437x-cm-t43: Correct the dmas property of spi0
ARM: dts: am4372: Correct the interrupts_properties of McASP
ARM: dts: logicpd-somlv: Fix wl127x pinmux
ARM: dts: logicpd-som-lv: Fix gpmc addresses for NAND and enet
ARM: dts: Fix omap4 hang with GPS connected to USB by using wakeupgen
ARM: AM33xx: PRM: Remove am33xx_pwrdm_read_prev_pwrst function
ARM: OMAP2+: Fix SRAM virt to phys translation for save_secure_ram_context
usb: build drivers/usb/common/ when USB_SUPPORT is set
usbip: keep usbip_device sockfd state in sync with tcp_socket
staging: iio: ad5933: switch buffer mode to software
staging: iio: adc: ad7192: fix external frequency setting
binder: check for binder_thread allocation failure in binder_poll()
staging: android: ashmem: Fix a race condition in pin ioctls
dn_getsockoptdecnet: move nf_{get/set}sockopt outside sock lock
arm64: dts: add #cooling-cells to CPU nodes
ARM: 8743/1: bL_switcher: add MODULE_LICENSE tag
video: fbdev/mmp: add MODULE_LICENSE
ASoC: ux500: add MODULE_LICENSE tag
crypto: hash - prevent using keyed hashes without setting key
crypto: hash - annotate algorithms taking optional key
net: avoid skb_warn_bad_offload on IS_ERR
rds: tcp: atomically purge entries from rds_tcp_conn_list during netns delete
netfilter: xt_RATEEST: acquire xt_rateest_mutex for hash insert
netfilter: xt_cgroup: initialize info->priv in cgroup_mt_check_v1()
netfilter: on sockopt() acquire sock lock only in the required scope
netfilter: ipt_CLUSTERIP: fix out-of-bounds accesses in clusterip_tg_check()
netfilter: x_tables: avoid out-of-bounds reads in xt_request_find_{match|target}
netfilter: x_tables: fix int overflow in xt_alloc_table_info()
kcov: detect double association with a single task
KVM: x86: fix escape of guest dr6 to the host
blk_rq_map_user_iov: fix error override
staging: android: ion: Switch from WARN to pr_warn
staging: android: ion: Add __GFP_NOWARN for system contig heap
crypto: x86/twofish-3way - Fix %rbp usage
selinux: skip bounded transition processing if the policy isn't loaded
selinux: ensure the context is NUL terminated in security_context_to_sid_core()
Provide a function to create a NUL-terminated string from unterminated data
ptr_ring: fail early if queue occupies more than KMALLOC_MAX_SIZE
drm: Require __GFP_NOFAIL for the legacy drm_modeset_lock_all
blktrace: fix unlocked registration of tracepoints
sctp: set frag_point in sctp_setsockopt_maxseg correctly
xfrm: check id proto in validate_tmpl()
xfrm: Fix stack-out-of-bounds read on socket policy lookup.
mm,vmscan: Make unregister_shrinker() no-op if register_shrinker() failed.
xfrm: skip policies marked as dead while rehashing
cfg80211: check dev_set_name() return value
kcm: Only allow TCP sockets to be attached to a KCM mux
kcm: Check if sk_user_data already set in kcm_attach
vhost: use mutex_lock_nested() in vhost_dev_lock_vqs()
ANDROID: sdcardfs: Hold i_mutex for i_size_write
UPSTREAM: ANDROID: binder: synchronize_rcu() when using POLLFREE.
BACKPORT, FROMGIT: crypto: speck - add test vectors for Speck64-XTS
BACKPORT, FROMGIT: crypto: speck - add test vectors for Speck128-XTS
BACKPORT, FROMGIT: crypto: arm/speck - add NEON-accelerated implementation of Speck-XTS
FROMGIT: crypto: speck - export common helpers
BACKPORT, FROMGIT: crypto: speck - add support for the Speck block cipher
f2fs: updates on v4.16-rc1
Linux 4.9.83
media: r820t: fix r820t_write_reg for KASAN
ARM: dts: Delete bogus reference to the charlcd
arm: dts: mt2701: Add reset-cells
ARM: dts: s5pv210: add interrupt-parent for ohci
arm64: dts: msm8916: Add missing #phy-cells
ARM: pxa/tosa-bt: add MODULE_LICENSE tag
ARM: dts: exynos: fix RTC interrupt for exynos5410
vfs: don't do RCU lookup of empty pathnames
x86: fix build warnign with 32-bit PAE
x86/cpu: Change type of x86_cache_size variable to unsigned int
x86/spectre: Fix an error message
x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping
selftests/x86/mpx: Fix incorrect bounds with old _sigfault
x86/speculation: Add <asm/msr-index.h> dependency
nospec: Move array_index_nospec() parameter checking into separate macro
x86/speculation: Fix up array_index_nospec_mask() asm constraint
selftests/x86: Do not rely on "int $0x80" in single_step_syscall.c
selftests/x86: Do not rely on "int $0x80" in test_mremap_vdso.c
selftests/x86/pkeys: Remove unused functions
x86/speculation: Clean up various Spectre related details
X86/nVMX: Properly set spec_ctrl and pred_cmd before merging MSRs
KVM/x86: Reduce retpoline performance impact in slot_handle_level_range(), by always inlining iterator helper methods
x86/speculation: Correct Speculation Control microcode blacklist again
x86/speculation: Update Speculation Control microcode blacklist
compiler-gcc.h: Introduce __optimize function attribute
x86/entry/64/compat: Clear registers for compat syscalls, to reduce speculation attack surface
arm: spear13xx: Fix spics gpio controller's warning
arm: spear13xx: Fix dmas cells
arm: spear600: Add missing interrupt-parent of rtc
ARM: dts: nomadik: add interrupt-parent for clcd
ARM: dts: STi: Add gpio polarity for "hdmi,hpd-gpio" property
ARM: lpc3250: fix uda1380 gpio numbers
arm64: dts: msm8916: Correct ipc references for smsm
s390: fix handling of -1 in set{,fs}[gu]id16 syscalls
ocfs2: try a blocking lock before return AOP_TRUNCATED_PAGE
PM / devfreq: Propagate error from devfreq_add_device()
cpufreq: powernv: Dont assume distinct pstate values for nominal and pmin
RDMA/rxe: Fix a race condition related to the QP error state
kselftest: fix OOM in memory compaction test
IB/mlx4: Fix incorrectly releasing steerable UD QPs when have only ETH ports
IB/qib: Fix comparison error with qperf compare/swap test
powerpc: fix build errors in stable tree
dm: correctly handle chained bios in dec_pending()
usb: Move USB_UHCI_BIG_ENDIAN_* out of USB_SUPPORT
mvpp2: fix multicast address filter
ALSA: seq: Fix racy pool initializations
ALSA: usb-audio: add implicit fb quirk for Behringer UFX1204
ALSA: hda/realtek: PCI quirk for Fujitsu U7x7
ALSA: hda/realtek - Enable Thinkpad Dock device for ALC298 platform
ALSA: usb-audio: Fix UAC2 get_ctl request with a RANGE attribute
ALSA: hda - Fix headset mic detection problem for two Dell machines
mtd: nand: vf610: set correct ooblayout
9p/trans_virtio: discard zero-length reply
Btrfs: fix unexpected -EEXIST when creating new inode
Btrfs: fix btrfs_evict_inode to handle abnormal inodes correctly
Btrfs: fix extent state leak from tree log
Btrfs: fix crash due to not cleaning up tree log block's dirty bits
Btrfs: fix deadlock in run_delalloc_nocow
target/iscsi: avoid NULL dereference in CHAP auth error path
rtlwifi: rtl8821ae: Fix connection lost problem correctly
console/dummy: leave .con_font_get set to NULL
video: fbdev: atmel_lcdfb: fix display-timings lookup
PCI: keystone: Fix interrupt-controller-node lookup
MIPS: Fix typo BIG_ENDIAN to CPU_BIG_ENDIAN
mm: Fix memory size alignment in devm_memremap_pages_release()
mm: hide a #warning for COMPILE_TEST
ext4: correct documentation for grpid mount option
ext4: save error to disk in __ext4_grp_locked_error()
ext4: fix a race in the ext4 shutdown path
jbd2: fix sphinx kernel-doc build warnings
mbcache: initialize entry->e_referenced in mb_cache_entry_create()
rtc-opal: Fix handling of firmware error codes, prevent busy loops
drm/radeon: adjust tested variable
drm/radeon: Add dpm quirk for Jet PRO (v2)
scsi: smartpqi: allow static build ("built-in")
BACKPORT: tee: shm: Potential NULL dereference calling tee_shm_register()
BACKPORT: tee: shm: don't put_page on null shm->pages
BACKPORT: tee: shm: make function __tee_shm_alloc static
BACKPORT: tee: optee: check type of registered shared memory
BACKPORT: tee: add start argument to shm_register callback
BACKPORT: tee: optee: fix header dependencies
BACKPORT: tee: shm: inline tee_shm_get_id()
BACKPORT: tee: use reference counting for tee_context
BACKPORT: tee: optee: enable dynamic SHM support
BACKPORT: tee: optee: add optee-specific shared pool implementation
BACKPORT: tee: optee: store OP-TEE capabilities in private data
BACKPORT: tee: optee: add registered buffers handling into RPC calls
BACKPORT: tee: optee: add registered shared parameters handling
BACKPORT: tee: optee: add shared buffer registration functions
BACKPORT: tee: optee: add page list manipulation functions
BACKPORT: tee: optee: Update protocol definitions
BACKPORT: tee: shm: add page accessor functions
BACKPORT: tee: shm: add accessors for buffer size and page offset
BACKPORT: tee: add register user memory
BACKPORT: tee: flexible shared memory pool creation
BACKPORT: optee: support asynchronous supplicant requests
BACKPORT: tee: add TEE_IOCTL_PARAM_ATTR_META
BACKPORT: tee: add tee_param_is_memref() for driver use
UPSTREAM: tcp: fix access to sk->sk_state in tcp_poll()
BACKPORT: tcp: fix potential double free issue for fastopen_req
BACKPORT: xfrm: Fix return value check of copy_sec_ctx.
time: Fix ktime_get_raw() incorrect base accumulation
FROMLIST: coresight: ETM: Add support for ARM Cortex-A73
FROMLIST: coresight: tmc: implementing TMC-ETR AUX space API
UPSTREAM: coresight: etm_perf: Fix using uninitialised work
UPSTREAM: coresight: fix kernel panic caused by invalid CPU
UPSTREAM: coresight: Fix disabling of CoreSight TPIU
UPSTREAM: coresight: perf: Add a missing call to etm_free_aux
UPSTREAM: coresight: tmc: Remove duplicate memset
UPSTREAM: coresight: tmc: Get rid of mode parameter for helper routines
UPSTREAM: coresight: tmc: Cleanup operation mode handling
UPSTREAM: coresight: reset "enable_sink" flag when need be
sched/fair: prevent possible infinite loop in sched_group_energy
ANDROID: qtaguid: Fix the UAF probelm with tag_ref_tree
UPSTREAM: ANDROID: binder: remove waitqueue when thread exits.
ANDROID: sdcardfs: Protect set_top
ANDROID: fsnotify: Notify lower fs of open
Revert "ANDROID: sdcardfs: notify lower file of opens"
ANDROID: sdcardfs: Use lower getattr times/size
ANDROID: sched: EAS: check energy_aware() before calling select_energy_cpu_brute() in up-migrate path
UPSTREAM: eventpoll.h: add missing epoll event masks
BACKPORT: thermal/drivers/hisi: Add support for hi3660 SoC
BACKPORT: thermal/drivers/hisi: Prepare to add support for other hisi platforms
BACKPORT: thermal/drivers/hisi: Add platform prefix to function name
BACKPORT: thermal/drivers/hisi: Put platform code together
BACKPORT: thermal/drivers/hisi: Use round up step value
BACKPORT: thermal/drivers/hisi: Move the clk setup in the corresponding functions
BACKPORT: thermal/drivers/hisi: Remove mutex_lock in the code
BACKPORT: thermal/drivers/hisi: Remove thermal data back pointer
BACKPORT: thermal/drivers/hisi: Convert long to int
BACKPORT: thermal/drivers/hisi: Rename and remove unused field
BACKPORT: thermal/drivers/hisi: Remove costly sensor inspection
BACKPORT: thermal/drivers/hisi: Fix configuration register setting
BACKPORT: thermal/drivers/hisi: Encapsulate register writes into helpers
BACKPORT: thermal/drivers/hisi: Remove pointless lock
BACKPORT: thermal/drivers/hisi: Remove the multiple sensors support
BACKPORT: thermal: hisilicon: constify thermal_zone_of_device_ops structures
ANDROID: xattr: Pass EOPNOTSUPP to permission2
ANDROID: sdcardfs: Move default_normal to superblock
UPSTREAM: tcp: fix a request socket leak
UPSTREAM: tcp: fix possible deadlock in TCP stack vs BPF filter
UPSTREAM: tcp: Add a tcp_filter hook before handle ack packet
FROMLIST: arm64: kpti: Fix the interaction between ASID switching and software PAN
FROMLIST: arm64: Move post_ttbr_update_workaround to C code
fscrypt: updates on 4.15-rc4
ANDROID: uid_sys_stats: fix the comment
BACKPORT: optee: fix invalid of_node_put() in optee_driver_init()
BACKPORT: tee: optee: sync with new naming of interrupts
BACKPORT: tee: indicate privileged dev in gen_caps
BACKPORT: tee: optee: interruptible RPC sleep
BACKPORT: tee: optee: add const to tee_driver_ops and tee_desc structures
BACKPORT: tee: tee_shm: Constify dma_buf_ops structures.
BACKPORT: tee: add forward declaration for struct device
BACKPORT: tee: optee: fix uninitialized symbol 'parg'
BACKPORT: tee.txt: standardize document format
BACKPORT: tee: add ARM_SMCCC dependency
clocksource: arch_timer: make virtual counter access configurable
arm64: issue isb when trapping CNTVCT_EL0 access
BACKPORT: arm64: Add CNTFRQ_EL0 trap handler
BACKPORT: arm64: Add CNTVCT_EL0 trap handler
ANDROID: sdcardfs: Fix missing break on default_normal
ANDROID: arm64: kaslr: fixup Falkor workaround for 4.9
ANDROID: usb: f_fs: Prevent gadget unbind if it is already unbound
arm64: Kconfig: Reword UNMAP_KERNEL_AT_EL0 kconfig entry
arm64: use RET instruction for exiting the trampoline
UPSTREAM: arm64: kaslr: Put kernel vectors address in separate data page
UPSTREAM: arm64: mm: Introduce TTBR_ASID_MASK for getting at the ASID in the TTBR
UPSTREAM: arm64: Kconfig: Add CONFIG_UNMAP_KERNEL_AT_EL0
UPSTREAM: arm64: entry: Add fake CPU feature for unmapping the kernel at EL0
UPSTREAM: arm64: tls: Avoid unconditional zeroing of tpidrro_el0 for native tasks
UPSTREAM: arm64: erratum: Work around Falkor erratum #E1003 in trampoline code
UPSTREAM: arm64: entry: Hook up entry trampoline to exception vectors
UPSTREAM: arm64: entry: Explicitly pass exception level to kernel_ventry macro
UPSTREAM: arm64: mm: Map entry trampoline into trampoline and kernel page tables
UPSTREAM: arm64: entry: Add exception trampoline page for exceptions from EL0
UPSTREAM: arm64: mm: Invalidate both kernel and user ASIDs when performing TLBI
UPSTREAM: arm64: mm: Add arm64_kernel_unmapped_at_el0 helper
UPSTREAM: arm64: mm: Allocate ASIDs in pairs
UPSTREAM: arm64: mm: Fix and re-enable ARM64_SW_TTBR0_PAN
UPSTREAM: arm64: mm: Rename post_ttbr0_update_workaround
UPSTREAM: arm64: mm: Move ASID from TTBR0 to TTBR1
UPSTREAM: arm64: mm: Temporarily disable ARM64_SW_TTBR0_PAN
UPSTREAM: arm64: mm: Use non-global mappings for kernel space
UPSTREAM: arm64: factor out entry stack manipulation
ANDROID: sdcardfs: Add default_normal option
ANDROID: sdcardfs: notify lower file of opens
blkdev: Refactoring block io latency histogram codes
UPSTREAM: netfilter: conntrack: use power efficient workqueue
ANDROID: binder: Remove obsolete proc waitqueue.
UPSTREAM: arm64: setup: introduce kaslr_offset()
UPSTREAM: kcov: fix comparison callback signature
UPSTREAM: kcov: support comparison operands collection
UPSTREAM: kcov: remove pointless current != NULL check
UPSTREAM: kcov: support compat processes
UPSTREAM: kcov: simplify interrupt check
UPSTREAM: kcov: make kcov work properly with KASLR enabled
UPSTREAM: kcov: add more missing includes
BACKPORT: irq: Make the irqentry text section unconditional
UPSTREAM: kasan: make get_wild_bug_type() static
UPSTREAM: kasan: separate report parts by empty lines
UPSTREAM: kasan: improve double-free report format
UPSTREAM: kasan: print page description after stacks
UPSTREAM: kasan: improve slab object description
UPSTREAM: kasan: change report header
UPSTREAM: kasan: simplify address description logic
UPSTREAM: kasan: change allocation and freeing stack traces headers
UPSTREAM: kasan: unify report headers
UPSTREAM: kasan: introduce helper functions for determining bug type
BACKPORT: kasan: report only the first error by default
UPSTREAM: kasan: fix races in quarantine_remove_cache()
UPSTREAM: kasan: resched in quarantine_remove_cache()
UPSTREAM: kasan, sched/headers: Uninline kasan_enable/disable_current()
UPSTREAM: kasan: drain quarantine of memcg slab objects
UPSTREAM: kasan: eliminate long stalls during quarantine reduction
UPSTREAM: kasan: support panic_on_warn
ANDROID: dma-buf/sw_sync: Rename active_list to link
ANDROID: initramfs: call free_initrd() when skipping init
BACKPORT: Documentation: tee subsystem and op-tee driver
BACKPORT: tee: add OP-TEE driver
BACKPORT: tee: generic TEE subsystem
BACKPORT: dt/bindings: add bindings for optee
BACKPORT: schedutil: Reset cached freq if it is not in sync with next_freq
sched: EAS/WALT: Don't take into account of running task's util
sched: EAS/WALT: take into account of waking task's load
sched: EAS: upmigrate misfit current task
sched: avoid pushing tasks to an offline CPU
sched: Extend active balance to accept 'push_task' argument
sched: walt: Correct WALT window size initialization
sched: WALT: account cumulative window demand
sched: EAS/WALT: finish accounting prior to task_tick
sched/fair: prevent meaningless active migration
sched: walt: Leverage existing helper APIs to apply invariance
UPSTREAM: net: xfrm: allow clearing socket xfrm policies.
UPSTREAM: time: Clean up CLOCK_MONOTONIC_RAW time handling
UPSTREAM: arm64: vdso: fix clock_getres for 4GiB-aligned res
f2fs: updates on 4.15-rc1
UPSTREAM: android: binder: fix type mismatch warning
BACKPORT: arm64: Use __pa_symbol for empty_zero_page
UPSTREAM: arm64: Use __pa_symbol for kernel symbols
UPSTREAM: mm: Introduce lm_alias
FROMLIST: binder: fix proc->files use-after-free
BACKPORT: xfrm: Clear sk_dst_cache when applying per-socket policy.
sched: WALT: fix potential overflow
sched: Update task->on_rq when tasks are moving between runqueues
sched: WALT: fix window mis-alignment
sched: EAS: kill incorrect nohz idle cpu kick
sched: EAS: fix incorrect energy delta calculation due to rounding error
sched: EAS/WALT: use cr_avg instead of prev_runnable_sum
sched: WALT: fix broken cumulative runnable average accounting
sched: deadline: WALT: account cumulative runnable avg
ANDROID: binder: clarify deferred thread work.
BACKPORT: net/tcp-fastopen: Add new API support
UPSTREAM: net: Remove __sk_dst_reset() in tcp_v6_connect()
UPSTREAM: net/tcp-fastopen: refactor cookie check logic
sched: compute task utilisation with WALT consistently
FROMLIST: arm64: Avoid aligning normal memory pointers in __memcpy_{to,from}io
UPSTREAM: security: bpf: replace include of linux/bpf.h with forward declarations
UPSTREAM: selinux: bpf: Add addtional check for bpf object file receive
UPSTREAM: selinux: bpf: Add selinux check for eBPF syscall operations
BACKPORT: security: bpf: Add LSM hooks for bpf object related syscall
BACKPORT: bpf: Add file mode configuration into bpf maps
cpufreq: Drop schedfreq governor
ANDROID: Revert "arm64: move ELF_ET_DYN_BASE to 4GB / 4MB"
ANDROID: Revert "arm: move ELF_ET_DYN_BASE to 4MB"
sched: EAS: Fix the condition to distinguish energy before/after
sched: EAS: update trg_cpu to backup_cpu if no energy saving for target_cpu
sched/fair: consider task utilization in group_max_util()
sched/fair: consider task utilization in group_norm_util()
sched/fair: enforce EAS mode
sched/fair: ignore backup CPU when not valid
sched/fair: trace energy_diff for non boosted tasks
UPSTREAM: sched/fair: Sync task util before slow-path wakeup
UPSTREAM: sched/core: Add missing update_rq_clock() call in set_user_nice()
UPSTREAM: sched/core: Add missing update_rq_clock() call for task_hot()
UPSTREAM: sched/core: Add missing update_rq_clock() in detach_task_cfs_rq()
UPSTREAM: sched/core: Add missing update_rq_clock() in post_init_entity_util_avg()
UPSTREAM: sched/fair: Fix task group initialization
cpufreq/sched: Consider max cpu capacity when choosing frequencies
cpufreq/sched: Use cpu max freq rather than policy max
sched/fair: remove erroneous RCU_LOCKDEP_WARN from start_cpu()
FROMLIST: ALSA: usx2y: Suppress kernel warning at page allocation failures
FROMLIST: kbuild: clang: fix build failures with sparse check
Revert "Revert "BACKPORT: efi/libstub/arm64: Set -fpie when building the EFI stub""
BACKPORT: efi/libstub: Unify command line param parsing
ANDROID: sched/walt: Fix divide by zero error in cpufreq notifier
ANDROID: binder: show high watermark of alloc->pages.
ANDROID: binder: Add thread->process_todo flag.
ANDROID: sched/fair: Select correct capacity state for energy_diff
ANDROID: cpufreq-dt: Set sane defaults for schedutil rate limits
BACKPORT: cpufreq: schedutil: Use policy-dependent transition delays
Revert "BACKPORT: efi/libstub/arm64: Set -fpie when building the EFI stub"
FROMLIST: android: binder: Fix null ptr dereference in debug msg
FROMLIST: android: binder: Change binder_shrinker to static
UPSTREAM: arm64: compat: Remove leftover variable declaration
ANDROID: HACK: arm64: use -mno-implicit-float instead of -mgeneral-regs-only
ANDROID: Kbuild, LLVMLinux: allow overriding clang target triple
CHROMIUM: arm64: Disable asm-operand-width warning for clang
CHROMIUM: kbuild: clang: Disable the 'duplicate-decl-specifier' warning
BACKPORT: x86/asm: Fix inline asm call constraints for Clang
BACKPORT: efi/libstub/arm64: Set -fpie when building the EFI stub
UPSTREAM: efi/libstub/arm64: Force 'hidden' visibility for section markers
UPSTREAM: efi/libstub/arm64: Use hidden attribute for struct screen_info reference
UPSTREAM: x86/build: Use cc-option to validate stack alignment parameter
UPSTREAM: x86/build: Fix stack alignment for CLang
UPSTREAM: compiler, clang: always inline when CONFIG_OPTIMIZE_INLINING is disabled
UPSTREAM: x86/boot: #undef memcpy() et al in string.c
UPSTREAM: llist: clang: introduce member_address_is_nonnull()
UPSTREAM: crypto: arm64/sha - avoid non-standard inline asm tricks
UPSTREAM: kbuild: clang: Disable 'address-of-packed-member' warning
UPSTREAM: x86/build: Specify stack alignment for clang
UPSTREAM: x86/build: Use __cc-option for boot code compiler options
UPSTREAM: kbuild: Add __cc-option macro
UPSTREAM: x86/mm/kaslr: Use the _ASM_MUL macro for multiplication to work around Clang incompatibility
UPSTREAM: crypto, x86: aesni - fix token pasting for clang
UPSTREAM: x86/kbuild: Use cc-option to enable -falign-{jumps/loops}
UPSTREAM: compiler, clang: properly override 'inline' for clang
UPSTREAM: compiler, clang: suppress warning for unused static inline functions
UPSTREAM: modules: mark __inittest/__exittest as __maybe_unused
UPSTREAM: kbuild: Add support to generate LLVM assembly files
UPSTREAM: kbuild: use -Oz instead of -Os when using clang
UPSTREAM: kbuild, LLVMLinux: Add -Werror to cc-option to support clang
UPSTREAM: kbuild: drop -Wno-unknown-warning-option from clang options
UPSTREAM: kbuild: fix asm-offset generation to work with clang
UPSTREAM: kbuild: consolidate redundant sed script ASM offset generation
UPSTREAM: kbuild: Consolidate header generation from ASM offset information
UPSTREAM: kbuild: clang: add -no-integrated-as to KBUILD_[AC]FLAGS
UPSTREAM: kbuild: Add better clang cross build support
FROMLIST: f2fs: expose some sectors to user in inline data or dentry case
UPSTREAM: sched/fair: Fix usage of find_idlest_group() when the local group is idlest
UPSTREAM: sched/fair: Fix usage of find_idlest_group() when no groups are allowed
UPSTREAM: sched/fair: Fix find_idlest_group() when local group is not allowed
UPSTREAM: sched/fair: Remove unnecessary comparison with -1
UPSTREAM: sched/fair: Move select_task_rq_fair() slow-path into its own function
UPSTREAM: sched/fair: Force balancing on NOHZ balance if local group has capacity
UPSTREAM: f2fs: fix potential panic during fstrim
f2fs: catch up to v4.14-rc1
UPSTREAM: sched: use load_avg for selecting idlest group
UPSTREAM: sched: fix find_idlest_group for fork
ANDROID: binder: fix node sched policy calculation
ANDROID: binder: init desired_prio.sched_policy before use it
BACKPORT: net: xfrm: support setting an output mark.
FROMLIST: tracing: Add support for preempt and irq enable/disable events
FROMLIST: tracing: Prepare to add preempt and irq trace events
Conflicts:
arch/arm64/Kconfig
arch/arm64/include/asm/assembler.h
arch/arm64/include/asm/cpucaps.h
arch/arm64/include/asm/efi.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/mmu.h
arch/arm64/include/asm/mmu_context.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/io.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/vdso.c
arch/arm64/mm/context.c
arch/arm64/mm/mmu.c
drivers/Kconfig
drivers/Makefile
drivers/cpufreq/Kconfig
drivers/hwtracing/coresight/coresight-etm4x.c
drivers/hwtracing/coresight/coresight-priv.h
drivers/hwtracing/coresight/coresight-tmc-etr.c
drivers/hwtracing/coresight/coresight.c
drivers/scsi/ufs/ufshcd.h
drivers/staging/android/ion/ion-ioctl.c
drivers/staging/android/ion/ion_system_heap.c
drivers/usb/dwc3/gadget.c
include/linux/sched.h
include/trace/events/sched.h
kernel/kcov.c
kernel/sched/core.c
kernel/sched/cpufreq_sched.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/fair.c
kernel/sched/sched.h
kernel/sched/walt.c
kernel/sched/walt.h
mm/kasan/report.c
security/security.c
security/selinux/hooks.c
Change-Id: I0ec8cbca6cb6384e22fbbe8def8a9d228229dc48
Signed-off-by: Blagovest Kolenichev <bkolenichev@codeaurora.org>
1334 lines
33 KiB
C
1334 lines
33 KiB
C
/*
|
|
* This is the linux wireless configuration interface.
|
|
*
|
|
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
|
* Copyright 2015 Intel Deutschland GmbH
|
|
*/
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/if.h>
|
|
#include <linux/module.h>
|
|
#include <linux/err.h>
|
|
#include <linux/list.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/nl80211.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/notifier.h>
|
|
#include <linux/device.h>
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/rtnetlink.h>
|
|
#include <linux/sched.h>
|
|
#include <net/genetlink.h>
|
|
#include <net/cfg80211.h>
|
|
#include "nl80211.h"
|
|
#include "core.h"
|
|
#include "sysfs.h"
|
|
#include "debugfs.h"
|
|
#include "wext-compat.h"
|
|
#include "rdev-ops.h"
|
|
|
|
/* name for sysfs, %d is appended */
|
|
#define PHY_NAME "phy"
|
|
|
|
MODULE_AUTHOR("Johannes Berg");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_DESCRIPTION("wireless configuration support");
|
|
MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
|
|
|
|
/* RCU-protected (and RTNL for writers) */
|
|
LIST_HEAD(cfg80211_rdev_list);
|
|
int cfg80211_rdev_list_generation;
|
|
|
|
/* for debugfs */
|
|
static struct dentry *ieee80211_debugfs_dir;
|
|
|
|
/* for the cleanup, scan and event works */
|
|
struct workqueue_struct *cfg80211_wq;
|
|
|
|
static bool cfg80211_disable_40mhz_24ghz;
|
|
module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
|
|
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
|
|
"Disable 40MHz support in the 2.4GHz band");
|
|
|
|
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
|
|
{
|
|
struct cfg80211_registered_device *result = NULL, *rdev;
|
|
|
|
ASSERT_RTNL();
|
|
|
|
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
|
if (rdev->wiphy_idx == wiphy_idx) {
|
|
result = rdev;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int get_wiphy_idx(struct wiphy *wiphy)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
|
|
return rdev->wiphy_idx;
|
|
}
|
|
|
|
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
|
|
{
|
|
struct cfg80211_registered_device *rdev;
|
|
|
|
ASSERT_RTNL();
|
|
|
|
rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
|
|
if (!rdev)
|
|
return NULL;
|
|
return &rdev->wiphy;
|
|
}
|
|
|
|
static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
|
|
const char *newname)
|
|
{
|
|
struct cfg80211_registered_device *rdev2;
|
|
int wiphy_idx, taken = -1, digits;
|
|
|
|
ASSERT_RTNL();
|
|
|
|
/* prohibit calling the thing phy%d when %d is not its number */
|
|
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
|
|
if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
|
|
/* count number of places needed to print wiphy_idx */
|
|
digits = 1;
|
|
while (wiphy_idx /= 10)
|
|
digits++;
|
|
/*
|
|
* deny the name if it is phy<idx> where <idx> is printed
|
|
* without leading zeroes. taken == strlen(newname) here
|
|
*/
|
|
if (taken == strlen(PHY_NAME) + digits)
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Ensure another device does not already have this name. */
|
|
list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
|
|
if (strcmp(newname, wiphy_name(&rdev2->wiphy)) == 0)
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
|
|
char *newname)
|
|
{
|
|
int result;
|
|
|
|
ASSERT_RTNL();
|
|
|
|
/* Ignore nop renames */
|
|
if (strcmp(newname, wiphy_name(&rdev->wiphy)) == 0)
|
|
return 0;
|
|
|
|
result = cfg80211_dev_check_name(rdev, newname);
|
|
if (result < 0)
|
|
return result;
|
|
|
|
result = device_rename(&rdev->wiphy.dev, newname);
|
|
if (result)
|
|
return result;
|
|
|
|
if (rdev->wiphy.debugfsdir &&
|
|
!debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
|
|
rdev->wiphy.debugfsdir,
|
|
rdev->wiphy.debugfsdir->d_parent,
|
|
newname))
|
|
pr_err("failed to rename debugfs dir to %s!\n", newname);
|
|
|
|
nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
|
|
struct net *net)
|
|
{
|
|
struct wireless_dev *wdev;
|
|
int err = 0;
|
|
|
|
if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
|
|
return -EOPNOTSUPP;
|
|
|
|
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
|
if (!wdev->netdev)
|
|
continue;
|
|
wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
|
|
err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
|
|
if (err)
|
|
break;
|
|
wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
|
|
}
|
|
|
|
if (err) {
|
|
/* failed -- clean up to old netns */
|
|
net = wiphy_net(&rdev->wiphy);
|
|
|
|
list_for_each_entry_continue_reverse(wdev,
|
|
&rdev->wiphy.wdev_list,
|
|
list) {
|
|
if (!wdev->netdev)
|
|
continue;
|
|
wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
|
|
err = dev_change_net_namespace(wdev->netdev, net,
|
|
"wlan%d");
|
|
WARN_ON(err);
|
|
wdev->netdev->features |= NETIF_F_NETNS_LOCAL;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
wiphy_net_set(&rdev->wiphy, net);
|
|
|
|
err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev));
|
|
WARN_ON(err);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
|
|
{
|
|
struct cfg80211_registered_device *rdev = data;
|
|
|
|
rdev_rfkill_poll(rdev);
|
|
}
|
|
|
|
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
|
struct wireless_dev *wdev)
|
|
{
|
|
ASSERT_RTNL();
|
|
|
|
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
|
|
return;
|
|
|
|
if (!wdev->p2p_started)
|
|
return;
|
|
|
|
rdev_stop_p2p_device(rdev, wdev);
|
|
wdev->p2p_started = false;
|
|
|
|
rdev->opencount--;
|
|
|
|
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
|
if (WARN_ON(!rdev->scan_req->notified))
|
|
rdev->scan_req->info.aborted = true;
|
|
___cfg80211_scan_done(rdev, false);
|
|
}
|
|
}
|
|
|
|
void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
|
|
struct wireless_dev *wdev)
|
|
{
|
|
ASSERT_RTNL();
|
|
|
|
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
|
|
return;
|
|
|
|
if (!wdev->nan_started)
|
|
return;
|
|
|
|
rdev_stop_nan(rdev, wdev);
|
|
wdev->nan_started = false;
|
|
|
|
rdev->opencount--;
|
|
}
|
|
|
|
void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
struct wireless_dev *wdev;
|
|
|
|
ASSERT_RTNL();
|
|
|
|
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
|
if (wdev->netdev) {
|
|
dev_close(wdev->netdev);
|
|
continue;
|
|
}
|
|
/* otherwise, check iftype */
|
|
switch (wdev->iftype) {
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
|
cfg80211_stop_p2p_device(rdev, wdev);
|
|
break;
|
|
case NL80211_IFTYPE_NAN:
|
|
cfg80211_stop_nan(rdev, wdev);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces);
|
|
|
|
static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
|
{
|
|
struct cfg80211_registered_device *rdev = data;
|
|
|
|
if (!blocked)
|
|
return 0;
|
|
|
|
rtnl_lock();
|
|
cfg80211_shutdown_all_interfaces(&rdev->wiphy);
|
|
rtnl_unlock();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cfg80211_rfkill_sync_work(struct work_struct *work)
|
|
{
|
|
struct cfg80211_registered_device *rdev;
|
|
|
|
rdev = container_of(work, struct cfg80211_registered_device, rfkill_sync);
|
|
cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill));
|
|
}
|
|
|
|
static void cfg80211_event_work(struct work_struct *work)
|
|
{
|
|
struct cfg80211_registered_device *rdev;
|
|
|
|
rdev = container_of(work, struct cfg80211_registered_device,
|
|
event_work);
|
|
|
|
rtnl_lock();
|
|
cfg80211_process_rdev_events(rdev);
|
|
rtnl_unlock();
|
|
}
|
|
|
|
void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
|
|
{
|
|
struct cfg80211_iface_destroy *item;
|
|
|
|
ASSERT_RTNL();
|
|
|
|
spin_lock_irq(&rdev->destroy_list_lock);
|
|
while ((item = list_first_entry_or_null(&rdev->destroy_list,
|
|
struct cfg80211_iface_destroy,
|
|
list))) {
|
|
struct wireless_dev *wdev, *tmp;
|
|
u32 nlportid = item->nlportid;
|
|
|
|
list_del(&item->list);
|
|
kfree(item);
|
|
spin_unlock_irq(&rdev->destroy_list_lock);
|
|
|
|
list_for_each_entry_safe(wdev, tmp,
|
|
&rdev->wiphy.wdev_list, list) {
|
|
if (nlportid == wdev->owner_nlportid)
|
|
rdev_del_virtual_intf(rdev, wdev);
|
|
}
|
|
|
|
spin_lock_irq(&rdev->destroy_list_lock);
|
|
}
|
|
spin_unlock_irq(&rdev->destroy_list_lock);
|
|
}
|
|
|
|
static void cfg80211_destroy_iface_wk(struct work_struct *work)
|
|
{
|
|
struct cfg80211_registered_device *rdev;
|
|
|
|
rdev = container_of(work, struct cfg80211_registered_device,
|
|
destroy_work);
|
|
|
|
rtnl_lock();
|
|
cfg80211_destroy_ifaces(rdev);
|
|
rtnl_unlock();
|
|
}
|
|
|
|
static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
|
|
{
|
|
struct cfg80211_registered_device *rdev;
|
|
|
|
rdev = container_of(work, struct cfg80211_registered_device,
|
|
sched_scan_stop_wk);
|
|
|
|
rtnl_lock();
|
|
|
|
__cfg80211_stop_sched_scan(rdev, false);
|
|
|
|
rtnl_unlock();
|
|
}
|
|
|
|
/* exported functions */
|
|
|
|
struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
|
|
const char *requested_name)
|
|
{
|
|
static atomic_t wiphy_counter = ATOMIC_INIT(0);
|
|
|
|
struct cfg80211_registered_device *rdev;
|
|
int alloc_size;
|
|
|
|
WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
|
|
WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
|
|
WARN_ON(ops->connect && !ops->disconnect);
|
|
WARN_ON(ops->join_ibss && !ops->leave_ibss);
|
|
WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf);
|
|
WARN_ON(ops->add_station && !ops->del_station);
|
|
WARN_ON(ops->add_mpath && !ops->del_mpath);
|
|
WARN_ON(ops->join_mesh && !ops->leave_mesh);
|
|
WARN_ON(ops->start_p2p_device && !ops->stop_p2p_device);
|
|
WARN_ON(ops->start_ap && !ops->stop_ap);
|
|
WARN_ON(ops->join_ocb && !ops->leave_ocb);
|
|
WARN_ON(ops->suspend && !ops->resume);
|
|
WARN_ON(ops->sched_scan_start && !ops->sched_scan_stop);
|
|
WARN_ON(ops->remain_on_channel && !ops->cancel_remain_on_channel);
|
|
WARN_ON(ops->tdls_channel_switch && !ops->tdls_cancel_channel_switch);
|
|
WARN_ON(ops->add_tx_ts && !ops->del_tx_ts);
|
|
|
|
alloc_size = sizeof(*rdev) + sizeof_priv;
|
|
|
|
rdev = kzalloc(alloc_size, GFP_KERNEL);
|
|
if (!rdev)
|
|
return NULL;
|
|
|
|
rdev->ops = ops;
|
|
|
|
rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
|
|
|
|
if (unlikely(rdev->wiphy_idx < 0)) {
|
|
/* ugh, wrapped! */
|
|
atomic_dec(&wiphy_counter);
|
|
kfree(rdev);
|
|
return NULL;
|
|
}
|
|
|
|
/* atomic_inc_return makes it start at 1, make it start at 0 */
|
|
rdev->wiphy_idx--;
|
|
|
|
/* give it a proper name */
|
|
if (requested_name && requested_name[0]) {
|
|
int rv;
|
|
|
|
rtnl_lock();
|
|
rv = cfg80211_dev_check_name(rdev, requested_name);
|
|
|
|
if (rv < 0) {
|
|
rtnl_unlock();
|
|
goto use_default_name;
|
|
}
|
|
|
|
rv = dev_set_name(&rdev->wiphy.dev, "%s", requested_name);
|
|
rtnl_unlock();
|
|
if (rv)
|
|
goto use_default_name;
|
|
} else {
|
|
int rv;
|
|
|
|
use_default_name:
|
|
/* NOTE: This is *probably* safe w/out holding rtnl because of
|
|
* the restrictions on phy names. Probably this call could
|
|
* fail if some other part of the kernel (re)named a device
|
|
* phyX. But, might should add some locking and check return
|
|
* value, and use a different name if this one exists?
|
|
*/
|
|
rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
|
|
if (rv < 0) {
|
|
kfree(rdev);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
INIT_LIST_HEAD(&rdev->wiphy.wdev_list);
|
|
INIT_LIST_HEAD(&rdev->beacon_registrations);
|
|
spin_lock_init(&rdev->beacon_registrations_lock);
|
|
spin_lock_init(&rdev->bss_lock);
|
|
INIT_LIST_HEAD(&rdev->bss_list);
|
|
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
|
|
INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results);
|
|
INIT_LIST_HEAD(&rdev->mlme_unreg);
|
|
spin_lock_init(&rdev->mlme_unreg_lock);
|
|
INIT_WORK(&rdev->mlme_unreg_wk, cfg80211_mlme_unreg_wk);
|
|
INIT_DELAYED_WORK(&rdev->dfs_update_channels_wk,
|
|
cfg80211_dfs_channels_update_work);
|
|
#ifdef CONFIG_CFG80211_WEXT
|
|
rdev->wiphy.wext = &cfg80211_wext_handler;
|
|
#endif
|
|
|
|
device_initialize(&rdev->wiphy.dev);
|
|
rdev->wiphy.dev.class = &ieee80211_class;
|
|
rdev->wiphy.dev.platform_data = rdev;
|
|
device_enable_async_suspend(&rdev->wiphy.dev);
|
|
|
|
INIT_LIST_HEAD(&rdev->destroy_list);
|
|
spin_lock_init(&rdev->destroy_list_lock);
|
|
INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
|
|
INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
|
|
|
|
#ifdef CONFIG_CFG80211_DEFAULT_PS
|
|
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
|
#endif
|
|
|
|
wiphy_net_set(&rdev->wiphy, &init_net);
|
|
|
|
rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
|
|
rdev->rfkill = rfkill_alloc(dev_name(&rdev->wiphy.dev),
|
|
&rdev->wiphy.dev, RFKILL_TYPE_WLAN,
|
|
&rdev->rfkill_ops, rdev);
|
|
|
|
if (!rdev->rfkill) {
|
|
kfree(rdev);
|
|
return NULL;
|
|
}
|
|
|
|
INIT_WORK(&rdev->rfkill_sync, cfg80211_rfkill_sync_work);
|
|
INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
|
|
INIT_WORK(&rdev->event_work, cfg80211_event_work);
|
|
|
|
init_waitqueue_head(&rdev->dev_wait);
|
|
|
|
/*
|
|
* Initialize wiphy parameters to IEEE 802.11 MIB default values.
|
|
* Fragmentation and RTS threshold are disabled by default with the
|
|
* special -1 value.
|
|
*/
|
|
rdev->wiphy.retry_short = 7;
|
|
rdev->wiphy.retry_long = 4;
|
|
rdev->wiphy.frag_threshold = (u32) -1;
|
|
rdev->wiphy.rts_threshold = (u32) -1;
|
|
rdev->wiphy.coverage_class = 0;
|
|
|
|
rdev->wiphy.max_num_csa_counters = 1;
|
|
|
|
rdev->wiphy.max_sched_scan_plans = 1;
|
|
rdev->wiphy.max_sched_scan_plan_interval = U32_MAX;
|
|
|
|
return &rdev->wiphy;
|
|
}
|
|
EXPORT_SYMBOL(wiphy_new_nm);
|
|
|
|
static int wiphy_verify_combinations(struct wiphy *wiphy)
|
|
{
|
|
const struct ieee80211_iface_combination *c;
|
|
int i, j;
|
|
|
|
for (i = 0; i < wiphy->n_iface_combinations; i++) {
|
|
u32 cnt = 0;
|
|
u16 all_iftypes = 0;
|
|
|
|
c = &wiphy->iface_combinations[i];
|
|
|
|
/*
|
|
* Combinations with just one interface aren't real,
|
|
* however we make an exception for DFS.
|
|
*/
|
|
if (WARN_ON((c->max_interfaces < 2) && !c->radar_detect_widths))
|
|
return -EINVAL;
|
|
|
|
/* Need at least one channel */
|
|
if (WARN_ON(!c->num_different_channels))
|
|
return -EINVAL;
|
|
|
|
/*
|
|
* Put a sane limit on maximum number of different
|
|
* channels to simplify channel accounting code.
|
|
*/
|
|
if (WARN_ON(c->num_different_channels >
|
|
CFG80211_MAX_NUM_DIFFERENT_CHANNELS))
|
|
return -EINVAL;
|
|
|
|
/* DFS only works on one channel. */
|
|
if (WARN_ON(c->radar_detect_widths &&
|
|
(c->num_different_channels > 1)))
|
|
return -EINVAL;
|
|
|
|
if (WARN_ON(!c->n_limits))
|
|
return -EINVAL;
|
|
|
|
for (j = 0; j < c->n_limits; j++) {
|
|
u16 types = c->limits[j].types;
|
|
|
|
/* interface types shouldn't overlap */
|
|
if (WARN_ON(types & all_iftypes))
|
|
return -EINVAL;
|
|
all_iftypes |= types;
|
|
|
|
if (WARN_ON(!c->limits[j].max))
|
|
return -EINVAL;
|
|
|
|
/* Shouldn't list software iftypes in combinations! */
|
|
if (WARN_ON(wiphy->software_iftypes & types))
|
|
return -EINVAL;
|
|
|
|
/* Only a single P2P_DEVICE can be allowed */
|
|
if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) &&
|
|
c->limits[j].max > 1))
|
|
return -EINVAL;
|
|
|
|
/* Only a single NAN can be allowed */
|
|
if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) &&
|
|
c->limits[j].max > 1))
|
|
return -EINVAL;
|
|
|
|
cnt += c->limits[j].max;
|
|
/*
|
|
* Don't advertise an unsupported type
|
|
* in a combination.
|
|
*/
|
|
if (WARN_ON((wiphy->interface_modes & types) != types))
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* You can't even choose that many! */
|
|
if (WARN_ON(cnt < c->max_interfaces))
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int wiphy_register(struct wiphy *wiphy)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
int res;
|
|
enum nl80211_band band;
|
|
struct ieee80211_supported_band *sband;
|
|
bool have_band = false;
|
|
int i;
|
|
u16 ifmodes = wiphy->interface_modes;
|
|
|
|
#ifdef CONFIG_PM
|
|
if (WARN_ON(wiphy->wowlan &&
|
|
(wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
|
|
!(wiphy->wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
|
|
return -EINVAL;
|
|
if (WARN_ON(wiphy->wowlan &&
|
|
!wiphy->wowlan->flags && !wiphy->wowlan->n_patterns &&
|
|
!wiphy->wowlan->tcp))
|
|
return -EINVAL;
|
|
#endif
|
|
if (WARN_ON((wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
|
|
(!rdev->ops->tdls_channel_switch ||
|
|
!rdev->ops->tdls_cancel_channel_switch)))
|
|
return -EINVAL;
|
|
|
|
if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN)) &&
|
|
(!rdev->ops->start_nan || !rdev->ops->stop_nan ||
|
|
!rdev->ops->add_nan_func || !rdev->ops->del_nan_func)))
|
|
return -EINVAL;
|
|
|
|
/*
|
|
* if a wiphy has unsupported modes for regulatory channel enforcement,
|
|
* opt-out of enforcement checking
|
|
*/
|
|
if (wiphy->interface_modes & ~(BIT(NL80211_IFTYPE_STATION) |
|
|
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
|
BIT(NL80211_IFTYPE_AP) |
|
|
BIT(NL80211_IFTYPE_P2P_GO) |
|
|
BIT(NL80211_IFTYPE_ADHOC) |
|
|
BIT(NL80211_IFTYPE_P2P_DEVICE) |
|
|
BIT(NL80211_IFTYPE_NAN) |
|
|
BIT(NL80211_IFTYPE_AP_VLAN) |
|
|
BIT(NL80211_IFTYPE_MONITOR)))
|
|
wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
|
|
|
|
if (WARN_ON((wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
|
|
(wiphy->regulatory_flags &
|
|
(REGULATORY_CUSTOM_REG |
|
|
REGULATORY_STRICT_REG |
|
|
REGULATORY_COUNTRY_IE_FOLLOW_POWER |
|
|
REGULATORY_COUNTRY_IE_IGNORE))))
|
|
return -EINVAL;
|
|
|
|
if (WARN_ON(wiphy->coalesce &&
|
|
(!wiphy->coalesce->n_rules ||
|
|
!wiphy->coalesce->n_patterns) &&
|
|
(!wiphy->coalesce->pattern_min_len ||
|
|
wiphy->coalesce->pattern_min_len >
|
|
wiphy->coalesce->pattern_max_len)))
|
|
return -EINVAL;
|
|
|
|
if (WARN_ON(wiphy->ap_sme_capa &&
|
|
!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
|
|
return -EINVAL;
|
|
|
|
if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
|
|
return -EINVAL;
|
|
|
|
if (WARN_ON(wiphy->addresses &&
|
|
!is_zero_ether_addr(wiphy->perm_addr) &&
|
|
memcmp(wiphy->perm_addr, wiphy->addresses[0].addr,
|
|
ETH_ALEN)))
|
|
return -EINVAL;
|
|
|
|
if (WARN_ON(wiphy->max_acl_mac_addrs &&
|
|
(!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) ||
|
|
!rdev->ops->set_mac_acl)))
|
|
return -EINVAL;
|
|
|
|
/* assure only valid behaviours are flagged by driver
|
|
* hence subtract 2 as bit 0 is invalid.
|
|
*/
|
|
if (WARN_ON(wiphy->bss_select_support &&
|
|
(wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2))))
|
|
return -EINVAL;
|
|
|
|
if (wiphy->addresses)
|
|
memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
|
|
|
|
/* sanity check ifmodes */
|
|
WARN_ON(!ifmodes);
|
|
ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1;
|
|
if (WARN_ON(ifmodes != wiphy->interface_modes))
|
|
wiphy->interface_modes = ifmodes;
|
|
|
|
res = wiphy_verify_combinations(wiphy);
|
|
if (res)
|
|
return res;
|
|
|
|
/* sanity check supported bands/channels */
|
|
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
|
sband = wiphy->bands[band];
|
|
if (!sband)
|
|
continue;
|
|
|
|
sband->band = band;
|
|
if (WARN_ON(!sband->n_channels))
|
|
return -EINVAL;
|
|
/*
|
|
* on 60GHz band, there are no legacy rates, so
|
|
* n_bitrates is 0
|
|
*/
|
|
if (WARN_ON(band != NL80211_BAND_60GHZ &&
|
|
!sband->n_bitrates))
|
|
return -EINVAL;
|
|
|
|
/*
|
|
* Since cfg80211_disable_40mhz_24ghz is global, we can
|
|
* modify the sband's ht data even if the driver uses a
|
|
* global structure for that.
|
|
*/
|
|
if (cfg80211_disable_40mhz_24ghz &&
|
|
band == NL80211_BAND_2GHZ &&
|
|
sband->ht_cap.ht_supported) {
|
|
sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
|
sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
|
|
}
|
|
|
|
/*
|
|
* Since we use a u32 for rate bitmaps in
|
|
* ieee80211_get_response_rate, we cannot
|
|
* have more than 32 legacy rates.
|
|
*/
|
|
if (WARN_ON(sband->n_bitrates > 32))
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < sband->n_channels; i++) {
|
|
sband->channels[i].orig_flags =
|
|
sband->channels[i].flags;
|
|
sband->channels[i].orig_mag = INT_MAX;
|
|
sband->channels[i].orig_mpwr =
|
|
sband->channels[i].max_power;
|
|
sband->channels[i].band = band;
|
|
}
|
|
|
|
have_band = true;
|
|
}
|
|
|
|
if (!have_band) {
|
|
WARN_ON(1);
|
|
return -EINVAL;
|
|
}
|
|
|
|
#ifdef CONFIG_PM
|
|
if (WARN_ON(rdev->wiphy.wowlan && rdev->wiphy.wowlan->n_patterns &&
|
|
(!rdev->wiphy.wowlan->pattern_min_len ||
|
|
rdev->wiphy.wowlan->pattern_min_len >
|
|
rdev->wiphy.wowlan->pattern_max_len)))
|
|
return -EINVAL;
|
|
#endif
|
|
|
|
/* check and set up bitrates */
|
|
ieee80211_set_bitrate_flags(wiphy);
|
|
|
|
rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH;
|
|
|
|
rtnl_lock();
|
|
res = device_add(&rdev->wiphy.dev);
|
|
if (res) {
|
|
rtnl_unlock();
|
|
return res;
|
|
}
|
|
|
|
/* set up regulatory info */
|
|
wiphy_regulatory_register(wiphy);
|
|
|
|
list_add_rcu(&rdev->list, &cfg80211_rdev_list);
|
|
cfg80211_rdev_list_generation++;
|
|
|
|
/* add to debugfs */
|
|
rdev->wiphy.debugfsdir =
|
|
debugfs_create_dir(wiphy_name(&rdev->wiphy),
|
|
ieee80211_debugfs_dir);
|
|
if (IS_ERR(rdev->wiphy.debugfsdir))
|
|
rdev->wiphy.debugfsdir = NULL;
|
|
|
|
cfg80211_debugfs_rdev_add(rdev);
|
|
nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY);
|
|
|
|
if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
|
|
struct regulatory_request request;
|
|
|
|
request.wiphy_idx = get_wiphy_idx(wiphy);
|
|
request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
|
|
request.alpha2[0] = '9';
|
|
request.alpha2[1] = '9';
|
|
|
|
nl80211_send_reg_change_event(&request);
|
|
}
|
|
|
|
/* Check that nobody globally advertises any capabilities they do not
|
|
* advertise on all possible interface types.
|
|
*/
|
|
if (wiphy->extended_capabilities_len &&
|
|
wiphy->num_iftype_ext_capab &&
|
|
wiphy->iftype_ext_capab) {
|
|
u8 supported_on_all, j;
|
|
const struct wiphy_iftype_ext_capab *capab;
|
|
|
|
capab = wiphy->iftype_ext_capab;
|
|
for (j = 0; j < wiphy->extended_capabilities_len; j++) {
|
|
if (capab[0].extended_capabilities_len > j)
|
|
supported_on_all =
|
|
capab[0].extended_capabilities[j];
|
|
else
|
|
supported_on_all = 0x00;
|
|
for (i = 1; i < wiphy->num_iftype_ext_capab; i++) {
|
|
if (j >= capab[i].extended_capabilities_len) {
|
|
supported_on_all = 0x00;
|
|
break;
|
|
}
|
|
supported_on_all &=
|
|
capab[i].extended_capabilities[j];
|
|
}
|
|
if (WARN_ON(wiphy->extended_capabilities[j] &
|
|
~supported_on_all))
|
|
break;
|
|
}
|
|
}
|
|
|
|
rdev->wiphy.registered = true;
|
|
rtnl_unlock();
|
|
|
|
res = rfkill_register(rdev->rfkill);
|
|
if (res) {
|
|
rfkill_destroy(rdev->rfkill);
|
|
rdev->rfkill = NULL;
|
|
wiphy_unregister(&rdev->wiphy);
|
|
return res;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(wiphy_register);
|
|
|
|
void wiphy_rfkill_start_polling(struct wiphy *wiphy)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
|
|
if (!rdev->ops->rfkill_poll)
|
|
return;
|
|
rdev->rfkill_ops.poll = cfg80211_rfkill_poll;
|
|
rfkill_resume_polling(rdev->rfkill);
|
|
}
|
|
EXPORT_SYMBOL(wiphy_rfkill_start_polling);
|
|
|
|
void wiphy_rfkill_stop_polling(struct wiphy *wiphy)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
|
|
rfkill_pause_polling(rdev->rfkill);
|
|
}
|
|
EXPORT_SYMBOL(wiphy_rfkill_stop_polling);
|
|
|
|
void wiphy_unregister(struct wiphy *wiphy)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
|
|
wait_event(rdev->dev_wait, ({
|
|
int __count;
|
|
rtnl_lock();
|
|
__count = rdev->opencount;
|
|
rtnl_unlock();
|
|
__count == 0; }));
|
|
|
|
if (rdev->rfkill)
|
|
rfkill_unregister(rdev->rfkill);
|
|
|
|
rtnl_lock();
|
|
nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
|
|
rdev->wiphy.registered = false;
|
|
|
|
WARN_ON(!list_empty(&rdev->wiphy.wdev_list));
|
|
|
|
/*
|
|
* First remove the hardware from everywhere, this makes
|
|
* it impossible to find from userspace.
|
|
*/
|
|
debugfs_remove_recursive(rdev->wiphy.debugfsdir);
|
|
list_del_rcu(&rdev->list);
|
|
synchronize_rcu();
|
|
|
|
/*
|
|
* If this device got a regulatory hint tell core its
|
|
* free to listen now to a new shiny device regulatory hint
|
|
*/
|
|
wiphy_regulatory_deregister(wiphy);
|
|
|
|
cfg80211_rdev_list_generation++;
|
|
device_del(&rdev->wiphy.dev);
|
|
|
|
rtnl_unlock();
|
|
|
|
flush_work(&rdev->scan_done_wk);
|
|
cancel_work_sync(&rdev->conn_work);
|
|
flush_work(&rdev->event_work);
|
|
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
|
flush_work(&rdev->destroy_work);
|
|
flush_work(&rdev->sched_scan_stop_wk);
|
|
flush_work(&rdev->mlme_unreg_wk);
|
|
|
|
#ifdef CONFIG_PM
|
|
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
|
|
rdev_set_wakeup(rdev, false);
|
|
#endif
|
|
cfg80211_rdev_free_wowlan(rdev);
|
|
cfg80211_rdev_free_coalesce(rdev);
|
|
}
|
|
EXPORT_SYMBOL(wiphy_unregister);
|
|
|
|
void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
|
|
{
|
|
struct cfg80211_internal_bss *scan, *tmp;
|
|
struct cfg80211_beacon_registration *reg, *treg;
|
|
rfkill_destroy(rdev->rfkill);
|
|
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
|
|
list_del(®->list);
|
|
kfree(reg);
|
|
}
|
|
list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
|
|
cfg80211_put_bss(&rdev->wiphy, &scan->pub);
|
|
kfree(rdev);
|
|
}
|
|
|
|
void wiphy_free(struct wiphy *wiphy)
|
|
{
|
|
put_device(&wiphy->dev);
|
|
}
|
|
EXPORT_SYMBOL(wiphy_free);
|
|
|
|
void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
|
|
if (rfkill_set_hw_state(rdev->rfkill, blocked))
|
|
schedule_work(&rdev->rfkill_sync);
|
|
}
|
|
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
|
|
|
|
void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
|
|
|
ASSERT_RTNL();
|
|
|
|
if (WARN_ON(wdev->netdev))
|
|
return;
|
|
|
|
nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
|
|
|
|
list_del_rcu(&wdev->list);
|
|
rdev->devlist_generation++;
|
|
|
|
switch (wdev->iftype) {
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
|
cfg80211_mlme_purge_registrations(wdev);
|
|
cfg80211_stop_p2p_device(rdev, wdev);
|
|
break;
|
|
case NL80211_IFTYPE_NAN:
|
|
cfg80211_stop_nan(rdev, wdev);
|
|
break;
|
|
default:
|
|
WARN_ON_ONCE(1);
|
|
break;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
|
|
|
static const struct device_type wiphy_type = {
|
|
.name = "wlan",
|
|
};
|
|
|
|
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
|
enum nl80211_iftype iftype, int num)
|
|
{
|
|
ASSERT_RTNL();
|
|
|
|
rdev->num_running_ifaces += num;
|
|
if (iftype == NL80211_IFTYPE_MONITOR)
|
|
rdev->num_running_monitor_ifaces += num;
|
|
}
|
|
|
|
void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|
struct wireless_dev *wdev)
|
|
{
|
|
struct net_device *dev = wdev->netdev;
|
|
struct cfg80211_sched_scan_request *sched_scan_req;
|
|
|
|
ASSERT_RTNL();
|
|
ASSERT_WDEV_LOCK(wdev);
|
|
|
|
switch (wdev->iftype) {
|
|
case NL80211_IFTYPE_ADHOC:
|
|
__cfg80211_leave_ibss(rdev, dev, true);
|
|
break;
|
|
case NL80211_IFTYPE_P2P_CLIENT:
|
|
case NL80211_IFTYPE_STATION:
|
|
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
|
if (sched_scan_req && dev == sched_scan_req->dev)
|
|
__cfg80211_stop_sched_scan(rdev, false);
|
|
|
|
#ifdef CONFIG_CFG80211_WEXT
|
|
kfree(wdev->wext.ie);
|
|
wdev->wext.ie = NULL;
|
|
wdev->wext.ie_len = 0;
|
|
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
|
#endif
|
|
cfg80211_disconnect(rdev, dev,
|
|
WLAN_REASON_DEAUTH_LEAVING, true);
|
|
break;
|
|
case NL80211_IFTYPE_MESH_POINT:
|
|
__cfg80211_leave_mesh(rdev, dev);
|
|
break;
|
|
case NL80211_IFTYPE_AP:
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
__cfg80211_stop_ap(rdev, dev, true);
|
|
break;
|
|
case NL80211_IFTYPE_OCB:
|
|
__cfg80211_leave_ocb(rdev, dev);
|
|
break;
|
|
case NL80211_IFTYPE_WDS:
|
|
/* must be handled by mac80211/driver, has no APIs */
|
|
break;
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
|
case NL80211_IFTYPE_NAN:
|
|
/* cannot happen, has no netdev */
|
|
break;
|
|
case NL80211_IFTYPE_AP_VLAN:
|
|
case NL80211_IFTYPE_MONITOR:
|
|
/* nothing to do */
|
|
break;
|
|
case NL80211_IFTYPE_UNSPECIFIED:
|
|
case NUM_NL80211_IFTYPES:
|
|
/* invalid */
|
|
break;
|
|
}
|
|
}
|
|
|
|
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|
struct wireless_dev *wdev)
|
|
{
|
|
wdev_lock(wdev);
|
|
__cfg80211_leave(rdev, wdev);
|
|
wdev_unlock(wdev);
|
|
}
|
|
|
|
void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|
gfp_t gfp)
|
|
{
|
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
|
struct cfg80211_event *ev;
|
|
unsigned long flags;
|
|
|
|
trace_cfg80211_stop_iface(wiphy, wdev);
|
|
|
|
ev = kzalloc(sizeof(*ev), gfp);
|
|
if (!ev)
|
|
return;
|
|
|
|
ev->type = EVENT_STOPPED;
|
|
|
|
spin_lock_irqsave(&wdev->event_lock, flags);
|
|
list_add_tail(&ev->list, &wdev->event_list);
|
|
spin_unlock_irqrestore(&wdev->event_lock, flags);
|
|
queue_work(cfg80211_wq, &rdev->event_work);
|
|
}
|
|
EXPORT_SYMBOL(cfg80211_stop_iface);
|
|
|
|
static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|
unsigned long state, void *ptr)
|
|
{
|
|
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
|
struct cfg80211_registered_device *rdev;
|
|
struct cfg80211_sched_scan_request *sched_scan_req;
|
|
|
|
if (!wdev)
|
|
return NOTIFY_DONE;
|
|
|
|
rdev = wiphy_to_rdev(wdev->wiphy);
|
|
|
|
WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
|
|
|
|
switch (state) {
|
|
case NETDEV_POST_INIT:
|
|
SET_NETDEV_DEVTYPE(dev, &wiphy_type);
|
|
break;
|
|
case NETDEV_REGISTER:
|
|
/*
|
|
* NB: cannot take rdev->mtx here because this may be
|
|
* called within code protected by it when interfaces
|
|
* are added with nl80211.
|
|
*/
|
|
mutex_init(&wdev->mtx);
|
|
INIT_LIST_HEAD(&wdev->event_list);
|
|
spin_lock_init(&wdev->event_lock);
|
|
INIT_LIST_HEAD(&wdev->mgmt_registrations);
|
|
spin_lock_init(&wdev->mgmt_registrations_lock);
|
|
|
|
wdev->identifier = ++rdev->wdev_id;
|
|
list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
|
|
rdev->devlist_generation++;
|
|
/* can only change netns with wiphy */
|
|
dev->features |= NETIF_F_NETNS_LOCAL;
|
|
|
|
if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
|
|
"phy80211")) {
|
|
pr_err("failed to add phy80211 symlink to netdev!\n");
|
|
}
|
|
wdev->netdev = dev;
|
|
#ifdef CONFIG_CFG80211_WEXT
|
|
wdev->wext.default_key = -1;
|
|
wdev->wext.default_mgmt_key = -1;
|
|
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
|
#endif
|
|
|
|
if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
|
|
wdev->ps = true;
|
|
else
|
|
wdev->ps = false;
|
|
/* allow mac80211 to determine the timeout */
|
|
wdev->ps_timeout = -1;
|
|
|
|
if ((wdev->iftype == NL80211_IFTYPE_STATION ||
|
|
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
|
|
wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
|
|
dev->priv_flags |= IFF_DONT_BRIDGE;
|
|
|
|
INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
|
|
|
|
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
|
|
break;
|
|
case NETDEV_GOING_DOWN:
|
|
cfg80211_leave(rdev, wdev);
|
|
break;
|
|
case NETDEV_DOWN:
|
|
cfg80211_update_iface_num(rdev, wdev->iftype, -1);
|
|
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
|
if (WARN_ON(!rdev->scan_req->notified))
|
|
rdev->scan_req->info.aborted = true;
|
|
___cfg80211_scan_done(rdev, false);
|
|
}
|
|
|
|
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
|
if (WARN_ON(sched_scan_req &&
|
|
sched_scan_req->dev == wdev->netdev)) {
|
|
__cfg80211_stop_sched_scan(rdev, false);
|
|
}
|
|
|
|
rdev->opencount--;
|
|
wake_up(&rdev->dev_wait);
|
|
break;
|
|
case NETDEV_UP:
|
|
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
|
|
wdev_lock(wdev);
|
|
switch (wdev->iftype) {
|
|
#ifdef CONFIG_CFG80211_WEXT
|
|
case NL80211_IFTYPE_ADHOC:
|
|
cfg80211_ibss_wext_join(rdev, wdev);
|
|
break;
|
|
case NL80211_IFTYPE_STATION:
|
|
cfg80211_mgd_wext_connect(rdev, wdev);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_MAC80211_MESH
|
|
case NL80211_IFTYPE_MESH_POINT:
|
|
{
|
|
/* backward compat code... */
|
|
struct mesh_setup setup;
|
|
memcpy(&setup, &default_mesh_setup,
|
|
sizeof(setup));
|
|
/* back compat only needed for mesh_id */
|
|
setup.mesh_id = wdev->ssid;
|
|
setup.mesh_id_len = wdev->mesh_id_up_len;
|
|
if (wdev->mesh_id_up_len)
|
|
__cfg80211_join_mesh(rdev, dev,
|
|
&setup,
|
|
&default_mesh_config);
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
wdev_unlock(wdev);
|
|
rdev->opencount++;
|
|
|
|
/*
|
|
* Configure power management to the driver here so that its
|
|
* correctly set also after interface type changes etc.
|
|
*/
|
|
if ((wdev->iftype == NL80211_IFTYPE_STATION ||
|
|
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
|
|
rdev->ops->set_power_mgmt)
|
|
if (rdev_set_power_mgmt(rdev, dev, wdev->ps,
|
|
wdev->ps_timeout)) {
|
|
/* assume this means it's off */
|
|
wdev->ps = false;
|
|
}
|
|
break;
|
|
case NETDEV_UNREGISTER:
|
|
/*
|
|
* It is possible to get NETDEV_UNREGISTER
|
|
* multiple times. To detect that, check
|
|
* that the interface is still on the list
|
|
* of registered interfaces, and only then
|
|
* remove and clean it up.
|
|
*/
|
|
if (!list_empty(&wdev->list)) {
|
|
nl80211_notify_iface(rdev, wdev,
|
|
NL80211_CMD_DEL_INTERFACE);
|
|
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
|
list_del_rcu(&wdev->list);
|
|
rdev->devlist_generation++;
|
|
cfg80211_mlme_purge_registrations(wdev);
|
|
#ifdef CONFIG_CFG80211_WEXT
|
|
kzfree(wdev->wext.keys);
|
|
#endif
|
|
flush_work(&wdev->disconnect_wk);
|
|
}
|
|
/*
|
|
* synchronise (so that we won't find this netdev
|
|
* from other code any more) and then clear the list
|
|
* head so that the above code can safely check for
|
|
* !list_empty() to avoid double-cleanup.
|
|
*/
|
|
synchronize_rcu();
|
|
INIT_LIST_HEAD(&wdev->list);
|
|
/*
|
|
* Ensure that all events have been processed and
|
|
* freed.
|
|
*/
|
|
cfg80211_process_wdev_events(wdev);
|
|
|
|
if (WARN_ON(wdev->current_bss)) {
|
|
cfg80211_unhold_bss(wdev->current_bss);
|
|
cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
|
|
wdev->current_bss = NULL;
|
|
}
|
|
break;
|
|
case NETDEV_PRE_UP:
|
|
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
|
|
return notifier_from_errno(-EOPNOTSUPP);
|
|
if (rfkill_blocked(rdev->rfkill))
|
|
return notifier_from_errno(-ERFKILL);
|
|
break;
|
|
default:
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
wireless_nlevent_flush();
|
|
|
|
return NOTIFY_OK;
|
|
}
|
|
|
|
static struct notifier_block cfg80211_netdev_notifier = {
|
|
.notifier_call = cfg80211_netdev_notifier_call,
|
|
};
|
|
|
|
static void __net_exit cfg80211_pernet_exit(struct net *net)
|
|
{
|
|
struct cfg80211_registered_device *rdev;
|
|
|
|
rtnl_lock();
|
|
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
|
if (net_eq(wiphy_net(&rdev->wiphy), net))
|
|
WARN_ON(cfg80211_switch_netns(rdev, &init_net));
|
|
}
|
|
rtnl_unlock();
|
|
}
|
|
|
|
static struct pernet_operations cfg80211_pernet_ops = {
|
|
.exit = cfg80211_pernet_exit,
|
|
};
|
|
|
|
static int __init cfg80211_init(void)
|
|
{
|
|
int err;
|
|
|
|
err = register_pernet_device(&cfg80211_pernet_ops);
|
|
if (err)
|
|
goto out_fail_pernet;
|
|
|
|
err = wiphy_sysfs_init();
|
|
if (err)
|
|
goto out_fail_sysfs;
|
|
|
|
err = register_netdevice_notifier(&cfg80211_netdev_notifier);
|
|
if (err)
|
|
goto out_fail_notifier;
|
|
|
|
err = nl80211_init();
|
|
if (err)
|
|
goto out_fail_nl80211;
|
|
|
|
ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
|
|
|
|
err = regulatory_init();
|
|
if (err)
|
|
goto out_fail_reg;
|
|
|
|
cfg80211_wq = alloc_ordered_workqueue("cfg80211", WQ_MEM_RECLAIM);
|
|
if (!cfg80211_wq) {
|
|
err = -ENOMEM;
|
|
goto out_fail_wq;
|
|
}
|
|
|
|
return 0;
|
|
|
|
out_fail_wq:
|
|
regulatory_exit();
|
|
out_fail_reg:
|
|
debugfs_remove(ieee80211_debugfs_dir);
|
|
nl80211_exit();
|
|
out_fail_nl80211:
|
|
unregister_netdevice_notifier(&cfg80211_netdev_notifier);
|
|
out_fail_notifier:
|
|
wiphy_sysfs_exit();
|
|
out_fail_sysfs:
|
|
unregister_pernet_device(&cfg80211_pernet_ops);
|
|
out_fail_pernet:
|
|
return err;
|
|
}
|
|
subsys_initcall(cfg80211_init);
|
|
|
|
static void __exit cfg80211_exit(void)
|
|
{
|
|
debugfs_remove(ieee80211_debugfs_dir);
|
|
nl80211_exit();
|
|
unregister_netdevice_notifier(&cfg80211_netdev_notifier);
|
|
wiphy_sysfs_exit();
|
|
regulatory_exit();
|
|
unregister_pernet_device(&cfg80211_pernet_ops);
|
|
destroy_workqueue(cfg80211_wq);
|
|
}
|
|
module_exit(cfg80211_exit);
|