1
0
Files
Greg Kroah-Hartman 718635b49d Merge 4.9.197 into android-4.9-q
Changes in 4.9.197
	KVM: s390: Test for bad access register and size at the start of S390_MEM_OP
	s390/topology: avoid firing events before kobjs are created
	s390/cio: avoid calling strlen on null pointer
	s390/cio: exclude subchannels with no parent from pseudo check
	KVM: nVMX: handle page fault in vmread fix
	ASoC: Define a set of DAPM pre/post-up events
	powerpc/powernv: Restrict OPAL symbol map to only be readable by root
	can: mcp251x: mcp251x_hw_reset(): allow more time after a reset
	crypto: qat - Silence smp_processor_id() warning
	usercopy: Avoid HIGHMEM pfn warning
	timer: Read jiffies once when forwarding base clk
	watchdog: imx2_wdt: fix min() calculation in imx2_wdt_set_timeout
	ieee802154: atusb: fix use-after-free at disconnect
	cfg80211: initialize on-stack chandefs
	ima: always return negative code for error
	fs: nfs: Fix possible null-pointer dereferences in encode_attrs()
	9p: avoid attaching writeback_fid on mmap with type PRIVATE
	xen/pci: reserve MCFG areas earlier
	ceph: fix directories inode i_blkbits initialization
	ceph: reconnect connection if session hang in opening state
	drm/amdgpu: Check for valid number of registers to read
	thermal: Fix use-after-free when unregistering thermal zone device
	fuse: fix memleak in cuse_channel_open
	sched/core: Fix migration to invalid CPU in __set_cpus_allowed_ptr()
	kernel/elfcore.c: include proper prototypes
	tools lib traceevent: Do not free tep->cmdlines in add_new_comm() on failure
	perf tools: Fix segfault in cpu_cache_level__read()
	perf stat: Fix a segmentation fault when using repeat forever
	perf stat: Reset previous counts on repeat with interval
	crypto: caam - fix concurrency issue in givencrypt descriptor
	coresight: etm4x: Use explicit barriers on enable/disable
	cfg80211: add and use strongly typed element iteration macros
	cfg80211: Use const more consistently in for_each_element macros
	nl80211: validate beacon head
	ASoC: sgtl5000: Improve VAG power and mute control
	panic: ensure preemption is disabled during panic()
	USB: rio500: Remove Rio 500 kernel driver
	USB: yurex: Don't retry on unexpected errors
	USB: yurex: fix NULL-derefs on disconnect
	USB: usb-skeleton: fix runtime PM after driver unbind
	USB: usb-skeleton: fix NULL-deref on disconnect
	xhci: Fix false warning message about wrong bounce buffer write length
	xhci: Prevent device initiated U1/U2 link pm if exit latency is too long
	xhci: Check all endpoints for LPM timeout
	usb: xhci: wait for CNR controller not ready bit in xhci resume
	xhci: Increase STS_SAVE timeout in xhci_suspend()
	USB: adutux: remove redundant variable minor
	USB: adutux: fix use-after-free on disconnect
	USB: adutux: fix NULL-derefs on disconnect
	USB: adutux: fix use-after-free on release
	USB: iowarrior: fix use-after-free on disconnect
	USB: iowarrior: fix use-after-free on release
	USB: iowarrior: fix use-after-free after driver unbind
	USB: usblp: fix runtime PM after driver unbind
	USB: chaoskey: fix use-after-free on release
	USB: ldusb: fix NULL-derefs on driver unbind
	serial: uartlite: fix exit path null pointer
	USB: serial: keyspan: fix NULL-derefs on open() and write()
	USB: serial: ftdi_sio: add device IDs for Sienna and Echelon PL-20
	USB: serial: option: add Telit FN980 compositions
	USB: serial: option: add support for Cinterion CLS8 devices
	USB: serial: fix runtime PM after driver unbind
	USB: usblcd: fix I/O after disconnect
	USB: microtek: fix info-leak at probe
	USB: dummy-hcd: fix power budget for SuperSpeed mode
	usb: renesas_usbhs: gadget: Do not discard queues in usb_ep_set_{halt,wedge}()
	usb: renesas_usbhs: gadget: Fix usb_ep_set_{halt,wedge}() behavior
	USB: legousbtower: fix slab info leak at probe
	USB: legousbtower: fix deadlock on disconnect
	USB: legousbtower: fix potential NULL-deref on disconnect
	USB: legousbtower: fix open after failed reset request
	USB: legousbtower: fix use-after-free on release
	staging: vt6655: Fix memory leak in vt6655_probe
	iio: adc: ad799x: fix probe error handling
	iio: light: opt3001: fix mutex unlock race
	efivar/ssdt: Don't iterate over EFI vars if no SSDT override was specified
	perf llvm: Don't access out-of-scope array
	perf inject jit: Fix JIT_CODE_MOVE filename
	CIFS: Gracefully handle QueryInfo errors during open
	CIFS: Force revalidate inode when dentry is stale
	CIFS: Force reval dentry if LOOKUP_REVAL flag is set
	kernel/sysctl.c: do not override max_threads provided by userspace
	staging: fbtft: Stop using BL_CORE_DRIVER1
	Staging: fbtft: fix memory leak in fbtft_framebuffer_alloc
	MIPS: Disable Loongson MMI instructions for kernel build
	Fix the locking in dcache_readdir() and friends
	media: stkwebcam: fix runtime PM after driver unbind
	tracing/hwlat: Report total time spent in all NMIs during the sample
	tracing/hwlat: Don't ignore outer-loop duration when calculating max_latency
	tracing: Get trace_array reference for available_tracers files
	x86/asm: Fix MWAITX C-state hint value
	xfs: clear sb->s_fs_info on mount failure
	Linux 4.9.197

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2019-10-24 21:40:50 +03:00

269 lines
6.2 KiB
C

/*
* Copyright (c) 2009, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*
* Author: Weidong Han <weidong.han@intel.com>
*/
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/pci-acpi.h>
#include <xen/xen.h>
#include <xen/interface/physdev.h>
#include <xen/interface/xen.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
#include "../pci/pci.h"
#ifdef CONFIG_PCI_MMCONFIG
#include <asm/pci_x86.h>
static int xen_mcfg_late(void);
#endif
static bool __read_mostly pci_seg_supported = true;
static int xen_add_device(struct device *dev)
{
int r;
struct pci_dev *pci_dev = to_pci_dev(dev);
#ifdef CONFIG_PCI_IOV
struct pci_dev *physfn = pci_dev->physfn;
#endif
#ifdef CONFIG_PCI_MMCONFIG
static bool pci_mcfg_reserved = false;
/*
* Reserve MCFG areas in Xen on first invocation due to this being
* potentially called from inside of acpi_init immediately after
* MCFG table has been finally parsed.
*/
if (!pci_mcfg_reserved) {
xen_mcfg_late();
pci_mcfg_reserved = true;
}
#endif
if (pci_seg_supported) {
struct {
struct physdev_pci_device_add add;
uint32_t pxm;
} add_ext = {
.add.seg = pci_domain_nr(pci_dev->bus),
.add.bus = pci_dev->bus->number,
.add.devfn = pci_dev->devfn
};
struct physdev_pci_device_add *add = &add_ext.add;
#ifdef CONFIG_ACPI
acpi_handle handle;
#endif
#ifdef CONFIG_PCI_IOV
if (pci_dev->is_virtfn) {
add->flags = XEN_PCI_DEV_VIRTFN;
add->physfn.bus = physfn->bus->number;
add->physfn.devfn = physfn->devfn;
} else
#endif
if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
add->flags = XEN_PCI_DEV_EXTFN;
#ifdef CONFIG_ACPI
handle = ACPI_HANDLE(&pci_dev->dev);
#ifdef CONFIG_PCI_IOV
if (!handle && pci_dev->is_virtfn)
handle = ACPI_HANDLE(physfn->bus->bridge);
#endif
if (!handle) {
/*
* This device was not listed in the ACPI name space at
* all. Try to get acpi handle of parent pci bus.
*/
struct pci_bus *pbus;
for (pbus = pci_dev->bus; pbus; pbus = pbus->parent) {
handle = acpi_pci_get_bridge_handle(pbus);
if (handle)
break;
}
}
if (handle) {
acpi_status status;
do {
unsigned long long pxm;
status = acpi_evaluate_integer(handle, "_PXM",
NULL, &pxm);
if (ACPI_SUCCESS(status)) {
add->optarr[0] = pxm;
add->flags |= XEN_PCI_DEV_PXM;
break;
}
status = acpi_get_parent(handle, &handle);
} while (ACPI_SUCCESS(status));
}
#endif /* CONFIG_ACPI */
r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, add);
if (r != -ENOSYS)
return r;
pci_seg_supported = false;
}
if (pci_domain_nr(pci_dev->bus))
r = -ENOSYS;
#ifdef CONFIG_PCI_IOV
else if (pci_dev->is_virtfn) {
struct physdev_manage_pci_ext manage_pci_ext = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
.is_virtfn = 1,
.physfn.bus = physfn->bus->number,
.physfn.devfn = physfn->devfn,
};
r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
&manage_pci_ext);
}
#endif
else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
struct physdev_manage_pci_ext manage_pci_ext = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
.is_extfn = 1,
};
r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
&manage_pci_ext);
} else {
struct physdev_manage_pci manage_pci = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
};
r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add,
&manage_pci);
}
return r;
}
static int xen_remove_device(struct device *dev)
{
int r;
struct pci_dev *pci_dev = to_pci_dev(dev);
if (pci_seg_supported) {
struct physdev_pci_device device = {
.seg = pci_domain_nr(pci_dev->bus),
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn
};
r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove,
&device);
} else if (pci_domain_nr(pci_dev->bus))
r = -ENOSYS;
else {
struct physdev_manage_pci manage_pci = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn
};
r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
&manage_pci);
}
return r;
}
static int xen_pci_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
int r = 0;
switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
r = xen_add_device(dev);
break;
case BUS_NOTIFY_DEL_DEVICE:
r = xen_remove_device(dev);
break;
default:
return NOTIFY_DONE;
}
if (r)
dev_err(dev, "Failed to %s - passthrough or MSI/MSI-X might fail!\n",
action == BUS_NOTIFY_ADD_DEVICE ? "add" :
(action == BUS_NOTIFY_DEL_DEVICE ? "delete" : "?"));
return NOTIFY_OK;
}
static struct notifier_block device_nb = {
.notifier_call = xen_pci_notifier,
};
static int __init register_xen_pci_notifier(void)
{
if (!xen_initial_domain())
return 0;
return bus_register_notifier(&pci_bus_type, &device_nb);
}
arch_initcall(register_xen_pci_notifier);
#ifdef CONFIG_PCI_MMCONFIG
static int xen_mcfg_late(void)
{
struct pci_mmcfg_region *cfg;
int rc;
if (!xen_initial_domain())
return 0;
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
return 0;
if (list_empty(&pci_mmcfg_list))
return 0;
/* Check whether they are in the right area. */
list_for_each_entry(cfg, &pci_mmcfg_list, list) {
struct physdev_pci_mmcfg_reserved r;
r.address = cfg->address;
r.segment = cfg->segment;
r.start_bus = cfg->start_bus;
r.end_bus = cfg->end_bus;
r.flags = XEN_PCI_MMCFG_RESERVED;
rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r);
switch (rc) {
case 0:
case -ENOSYS:
continue;
default:
pr_warn("Failed to report MMCONFIG reservation"
" state for %s to hypervisor"
" (%d)\n",
cfg->name, rc);
}
}
return 0;
}
#endif